Four frameworks now cover most production agent work: LangGraph, CrewAI, AutoGen, and Google ADK. By late 2026 they have converged on the same primitives — typed state, memory, resumability, tool and MCP support, observability hooks — so the decision is no longer “which has more features.” It is which abstraction you want to debug at 2 a.m.: a graph, a role-playing team, a conversation, or a hierarchy.

When to use which

  • LangGraph when your agent is a long-running, resumable workflow with custom control flow and audit requirements. The graph is the program, and the runtime owns durability.
  • CrewAI when the domain maps to named roles collaborating on tasks, and the team wants a fast path from idea to working demo.
  • AutoGen for reading and prototyping conversation-driven orchestration ideas. Microsoft has put it in maintenance mode — do not start new production work on it AutoGen GitHub README.
  • Google ADK when you want hierarchical agent teams with shared session state, especially on Google Cloud or in a polyglot codebase.

State management model

LangGraph models an agent as a state machine: typed state flows through nodes, and edges (including conditional ones) decide what runs next. The runtime is explicitly built for “long-running, stateful agents,” letting you mix deterministic hand-coded steps with LLM-driven ones in a single graph LangGraph overview. Persistence comes in two layers: checkpointers snapshot thread-scoped graph state after each step — enabling resume-after-failure, human-in-the-loop interrupts, and time-travel debugging — while stores hold long-term, cross-thread memory such as user preferences LangGraph persistence docs. You opt in by compiling the graph with a checkpointer and passing a thread_id per conversation LangGraph persistence docs.

CrewAI splits state across two layers. Flows own the workflow state: every flow instance gets a unique ID in its state, methods read and write a state attribute, and a @persist decorator at class or method level keeps that state across restarts and executions CrewAI Flows docs. Crews are the autonomous unit — role-based agents executing tasks with a process of sequential (default) or hierarchical, where a manager LLM or agent delegates and validates CrewAI Crews docs. State inside a crew is implicit: task outputs feed the next task, which is exactly why CrewAI’s docs recommend putting guardrails at flow boundaries.

AutoGen made a different bet: state is the conversation. Agents are “conversable” — they exchange messages until a termination condition fires, and every reply carries the accumulated context AutoGen docs. There is no checkpointing layer or state object in the classic library; the transcript is the state, and persisting it is your job. That made AutoGen brilliant for research on emergent coordination and awkward for anything that must survive a crash mid-task.

Google ADK organizes state around sessions. Each conversation runs in a session, and agents read and write session.state, a dictionary of serializable key-value pairs shared across the agent team ADK session state docs. Persistence is decided by the SessionService you plug in: InMemorySessionService for development, durable services (database- or Vertex-backed) in production ADK session state docs. That swap-without-rewrite design is the cleanest separation of state from execution of the four.

Orchestration patterns

LangGraph gives you explicit control flow: nodes, edges, subgraphs, and an orchestrator-worker pattern where a Send API spawns worker nodes that each write to a shared state key LangGraph workflows guide. CrewAI’s Flows are event-driven shells — @start and @listen decorators wire deterministic steps that can kick off crews — while crews internally run sequential pipelines or a manager-driven hierarchy CrewAI Flows docsCrewAI Crews docs. AutoGen’s orchestration is emergent: in a group chat, a manager agent broadcasts messages and picks the next speaker, so topology can adapt mid-conversation AutoGen docs. ADK’s default is automatic delegation: you give a root agent sub_agents, and its LLM reads each sub-agent’s description and transfers control to the best match for the turn ADK agent-team tutorial. The 2.0 line layers explicit graph workflows (routes, human input, dynamic graphs) on top of that hierarchy for deterministic paths ADK overview.

The same agent, four times

LangGraph — graph plus checkpointer:

from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver
from typing import TypedDict

class State(TypedDict):
    query: str
    report: str

def research(state): return {"report": f"sources for: {state['query']}"}
def write(state):  return {"report": f"draft from {state['report']}"}

graph = StateGraph(State)
graph.add_node(research)
graph.add_node(write)
graph.add_edge(START, "research")
graph.add_edge("research", "write")
graph.add_edge("write", END)
app = graph.compile(checkpointer=InMemorySaver())  # swap for Postgres in prod

app.invoke({"query": "LangGraph durability"},
           {"configurable": {"thread_id": "thread-1"}})

CrewAI — flow wrapping a crew:

from crewai import Agent, Crew, Task, Process
from crewai.flow.flow import Flow, start, listen

class ResearchFlow(Flow):
    @start()
    def run_crew(self):
        researcher = Agent(role="Researcher", goal="find sources",
                           backstory="methodical analyst")
        writer = Agent(role="Writer", goal="synthesize findings",
                       backstory="clear technical writer")
        crew = Crew(
            agents=[researcher, writer],
            tasks=[
                Task(description="Gather sources", agent=researcher,
                     expected_output="source list"),
                Task(description="Write the draft", agent=writer,
                     expected_output="markdown draft"),
            ],
            process=Process.sequential,
        )
        self.state["draft"] = crew.kickoff(inputs={})  # state survives

    @listen(run_crew)
    def ship(self):
        return self.state["draft"]

ResearchFlow().kickoff()

AutoGen — two conversable agents:

import os
from autogen import AssistantAgent, UserProxyAgent

assistant = AssistantAgent(
    name="assistant",
    llm_config={"config_list": [
        {"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}
    ]},
)
user_proxy = UserProxyAgent(name="user_proxy",
                            code_execution_config=False)  # disable exec

user_proxy.initiate_chat(assistant, message="Summarize AutoGen's model")

Google ADK — root agent delegating to sub-agents:

from google.adk.agents import Agent
from google.adk.sessions import InMemorySessionService
from google.adk.runners import Runner

searcher = Agent(name="searcher", instruction="Search and rank sources",
                 description="Handles research queries")
writer = Agent(name="writer", instruction="Draft from the given sources",
               description="Handles drafting")
root = Agent(name="coordinator",
             instruction="Delegate each query to the matching sub-agent",
             sub_agents=[searcher, writer])  # auto delegation

session_service = InMemorySessionService()   # durable service in prod
runner = Runner(agent=root, app_name="research", session_service=session_service)
session = await session_service.create_session(app_name="research",
                                               user_id="u1", session_id="s1")
# Drive turns with runner.run_async(...), which yields typed events

None of these snippets is better code; each shows the abstraction you will debug. The LangGraph version names every step and edge. The CrewAI version reads like an org chart. The AutoGen version is a chat log. The ADK version is a delegation tree sharing one session.

Production readiness

Checkpointing and recovery. LangGraph has the most mature story: checkpointers give you resume-after-failure, interrupts, and time travel out of the box LangGraph persistence docs. CrewAI’s @persist keeps flow state across restarts CrewAI Flows docs. ADK’s durability depends on choosing a persistent SessionService; with the in-memory one, state dies with the process ADK session state docs. Classic AutoGen has no built-in checkpointing — a hard constraint for long-running work.

Observability. LangGraph is built to feed LangSmith, and because the runtime is just Python, OpenTelemetry tracing slots in directly — we have a full LangGraph + OTel research-agent walkthrough on this blog LangGraph + OTel walkthrough. CrewAI’s docs ship tracing integrations for Arize Phoenix, Langfuse, Datadog, and MLflow among others CrewAI observability docs. ADK’s docs cover logging, metrics, and traces, with a first-party Cloud Trace integration ADK overviewADK deployment docs. For AutoGen, plan to instrument the conversation loop yourself.

Deployment. LangGraph markets itself as framework and runtime for deploying stateful agents LangGraph overview, with the Agent Server handling persistence infrastructure automatically LangGraph persistence docs. ADK documents managed paths on Cloud Run and GKE plus its agent runtime ADK deployment docs. CrewAI stays out of your runtime — you containerize it. AutoGen has no first-party hosting because Microsoft’s platform story now belongs to Agent Framework, the successor project AutoGen’s README points new users toward AutoGen GitHub README.

Comparison table

Dimension LangGraph CrewAI AutoGen Google ADK
Core abstraction State machine / graph Flows + role-based crews Agent conversation Agent hierarchy + sessions
State Typed graph state; checkpoints + stores LangGraph persistence docs Flow.state dict, @persist CrewAI Flows docs Message transcript AutoGen docs session.state key-values ADK session state docs
Resume after crash Yes, via checkpointer LangGraph persistence docs Flow persistence CrewAI Flows docs Manual With durable SessionService ADK session state docs
Orchestration Explicit nodes/edges, Send workers LangGraph workflows guide @start/@listen, manager process CrewAI Flows docsCrewAI Crews docs GroupChat manager picks speakers AutoGen docs Auto delegation + graph workflows ADK agent-team tutorialADK overview
Observability LangSmith / OTel LangGraph overviewLangGraph + OTel walkthrough Phoenix, Langfuse, Datadog, MLflow CrewAI observability docs DIY Logging/metrics/traces, Cloud Trace ADK overviewADK deployment docs
Languages Python, JS/TS Python Python Python, TS, Go, Java, Kotlin ADK overview
Status (Sep 2026) Active, stable Active Maintenance mode AutoGen GitHub README Active, 2.x ADK overview

Decision matrix

You are building… Start with
A long-running resumable workflow with custom routing and audit trails LangGraph
A business process where roles, tasks, and handoffs match an org chart CrewAI
A prototype to test conversation-driven multi-agent ideas AutoGen (then migrate)
A product where one coordinator should route to specialists, on GCP or in a polyglot stack Google ADK
Anything on AutoGen today Migrate to Agent Framework via the official guide AutoGen GitHub README

The pattern that matters most is the one you can inspect: where state lives, how you replay a bad run, and what a trace shows you without extra plumbing. If the framework hides one of those, it will cost you in week three, not day one. We detailed the LangGraph side of that in the OTel research-agent build LangGraph + OTel walkthrough; run the other three through the same drill before you commit.

  • ToolBrain — tool reviews, LLM comparisons, and AI workflow guides

Cross-links automatically generated from NiteAgent.

← Back to all posts