LangGraph vs CrewAI vs AutoGen vs Google ADK: How Each Framework Structures Multi-Agent Workflows
A structural comparison of LangGraph StateGraph, CrewAI Crew, AutoGen GroupChatManager, and Google ADK SequentialAgent — with real code patterns and a visual breakdown of how agents, tools, and edges connect.
Four production-ready frameworks. Four completely different ways to wire agents together. If you're choosing between LangGraph, CrewAI, AutoGen, and Google ADK — or trying to read someone else's code — understanding how each framework structures its graph is the first step.
This post maps out the core architectural primitives of each framework, the code patterns that produce them, and what the resulting agent graph looks like.
The Core Question: Who Owns Routing?
The deepest structural difference between these frameworks is who decides which agent runs next.
| Framework | Routing model |
|---|---|
| LangGraph | Explicit graph: you define nodes and edges in code |
| CrewAI | Sequential or hierarchical process; Crew owns task ordering |
| AutoGen | Conversation-driven; agents initiate chats with each other |
| Google ADK | Composition-based; parent agents contain sub-agents |
| OpenAI Agents SDK | Handoff-based; agents pass control via handoffs= or functions= |
Each model produces a fundamentally different graph shape.
LangGraph: Explicit State Machine
LangGraph's StateGraph is the most explicit of the five. Every node and edge is declared in code — there is no hidden orchestration layer.
from langgraph.graph import StateGraph, END
from typing import TypedDict
class State(TypedDict):
messages: list
graph = StateGraph(State)
graph.add_node("researcher", researcher_agent)
graph.add_node("writer", writer_agent)
graph.add_node("tools", ToolNode([search, calculator]))
graph.add_edge("researcher", "tools")
graph.add_conditional_edges(
"writer",
should_continue,
{"continue": "researcher", "end": END},
)
graph.set_entry_point("researcher")
What the graph looks like: A directed graph with explicit entry/exit nodes, tool nodes as peers (not children), and conditional routers as diamond nodes between agents. The add_conditional_edges call produces a routing node whose outgoing edges are labeled with the dict keys.
Strengths: Full control over routing logic. State is typed and flows through every node. Easy to inspect exactly what runs when.
Weakness: Verbosity. Wiring a 5-agent workflow takes 30+ lines of graph declarations.
CrewAI: Task-Centric Sequential Chains
CrewAI thinks in terms of tasks, not graph edges. You define agents, then tasks assigned to agents, then a Crew that runs them in order.
from crewai import Agent, Task, Crew, Process
researcher = Agent(
role="Senior Researcher",
goal="Find accurate information on {topic}",
llm="gpt-4o",
tools=[search_tool],
)
write_task = Task(
description="Write a report based on the research",
agent=writer,
context=[research_task],
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task],
process=Process.sequential,
)
What the graph looks like: A straight chain — START → task_1 → task_2 → END — with tool_binding edges linking each agent to its task. Hierarchical process adds a Manager node that fans out to all tasks.
Strengths: Intuitive for pipelines that have a clear linear order. The task abstraction maps cleanly to most real workflows.
Weakness: Conditional routing requires custom code. Not a natural fit for cyclic or branching flows.
AutoGen: Conversation-Driven Handoffs
AutoGen's model is fundamentally different: agents are conversational participants, and routing happens through initiate_chat calls or group chat orchestrators.
from autogen import AssistantAgent, UserProxyAgent, GroupChatManager, GroupChat
assistant = AssistantAgent("assistant", llm_config={"model": "gpt-4o"})
critic = AssistantAgent("critic", system_message="Review the assistant's output")
user_proxy = UserProxyAgent("user", human_input_mode="NEVER")
groupchat = GroupChat(agents=[user_proxy, assistant, critic], messages=[], max_round=10)
manager = GroupChatManager(groupchat=groupchat, llm_config={"model": "gpt-4o"})
user_proxy.initiate_chat(manager, message="Write and review a Python function")
What the graph looks like: A hub-and-spoke — START → GroupChatManager → each member agent → END. The manager is a conditional (router) node that fans out to all participants. initiate_chat calls produce direct agent-to-agent edges.
Strengths: Flexible for back-and-forth workflows where agents need to critique or revise each other's output. Easy to add participants without restructuring the graph.
Weakness: Harder to predict execution order. Debugging requires reading conversation history, not a graph.
Google ADK: Hierarchical Composition
Google ADK structures agents as a containment hierarchy. A SequentialAgent or ParallelAgent holds child agents as sub_agents, and the framework handles the execution order.
from google.adk.agents import LlmAgent, SequentialAgent, ParallelAgent
researcher = LlmAgent(
name="Researcher",
model="gemini-1.5-pro",
instruction="Research the given topic thoroughly",
tools=[google_search],
)
fact_checker = LlmAgent(
name="FactChecker",
model="gemini-1.5-pro",
instruction="Verify the claims in the research",
)
pipeline = SequentialAgent(
name="ResearchPipeline",
sub_agents=[researcher, fact_checker],
)
What the graph looks like: A tree — START → SequentialAgent → researcher → fact_checker → END. A ParallelAgent produces parallel edges to its children. Callback hooks (before/after model, before/after tool) appear as guardrail nodes attached to each agent.
Strengths: Composition is natural and declarative. Parallel execution is built in. Works well for pipelines with clear hierarchical structure.
Weakness: Less flexible for cyclic flows or runtime routing decisions.
OpenAI Agents SDK: Handoff-Based Control Transfer
The OpenAI Agents SDK (and its predecessor Swarm) routes via explicit handoffs. An agent can transfer control to another agent by listing it in handoffs=, or via Swarm-style functions that return an agent.
from agents import Agent, Runner
triage = Agent(
name="Triage Agent",
model="gpt-4o",
handoffs=[billing_agent, support_agent],
instructions="Route the user to the right specialist",
)
billing_agent = Agent(
name="Billing Agent",
model="gpt-4o-mini",
instructions="Handle billing questions",
tools=[lookup_invoice, process_refund],
)
What the graph looks like: A star from the triage agent — START → triage → (conditional edges) → billing_agent / support_agent → END. Guardrails appear as nodes attached to the agents that declare them.
Strengths: Handoffs are explicit and readable. Easy to build customer support flows where a router delegates to specialists.
Weakness: Cycles require careful handoff declarations to avoid loops. Less natural for pipeline-style processing.
Visualizing the Difference
Reading framework code is one thing — seeing the graph is faster. The Agent Workflow Visualizer scans any public GitHub repository and renders the full agent graph: nodes typed by role (agent, tool, router, guardrail, state), edges typed by relationship (unconditional, conditional, parallel, tool_binding), and a node inspector that shows each agent's LLM, tools, and source file.
Paste a LangGraph repo and you see the state machine. Paste a CrewAI repo and you see the task chain. Paste an AutoGen repo and you see the hub-and-spoke.
Which Framework Should You Use?
The graph shape tells you a lot about fit:
- LangGraph — when you need precise control over routing logic and want to audit every state transition
- CrewAI — when your workflow is a linear sequence of specialized tasks with clear agent assignments
- AutoGen — when agents need to debate, critique, or revise each other's output iteratively
- Google ADK — when your structure is naturally hierarchical and you want composition over explicit wiring
- OpenAI Agents SDK — when you're building customer-facing flows where a router delegates to specialists
The "best" framework is the one whose graph shape matches your problem's shape. Visualizing your repo makes that match obvious — or reveals where the mismatch is before it costs you debugging time.
Follow Trango Compute on LinkedIn
We post updates on new tools, context engineering patterns, and LLM cost research.