Pick between AutoGen, CrewAI, LangGraph supervisor, and OpenAI Swarm for a deep research multi-agent product. And defend the choice
You are building a deep research multi-agent product where a planner agent decomposes a query, several worker agents fan out to retrieve and analyse, and a synthesizer composes the final report. Pick one of AutoGen GroupChat, CrewAI, LangGraph supervisor, or OpenAI Swarm / Agents SDK as the orchestration layer, and defend the choice against the other three.
LangGraph supervisor. The deep-research shape is a supervisor with conditional routing graph, and only LangGraph offers explicit routing, durable state via the checkpointer, and inspectability together.
Picture coordinating a small research team. AutoGen is a free-form brainstorm in a chat room. Anyone can speak. CrewAI is a relay race where each runner hands the baton to the next in order. Swarm is two friends passing a question back and forth via short notes. LangGraph is a project manager with a wall-sized chart, a save every step planner, and an interruptible workflow. For a planner workers synthesiser product where you need to know who is running, save partial progress, and let a human approve the next step, the project manager wins. The other three are good at different shapes.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Multi-agent orchestration choice is one of the few framework decisions where the workload shape genuinely narrows the field. A deep-research product, planner decomposes, workers fan out and analyse, synthesiser composes, has three structural requirements that select one framework family over the others.
The lazy answer is 'depends on your team.' The senior answer maps the shape to the requirements and shows which framework satisfies them. The four candidates, AutoGen, CrewAI, LangGraph supervisor, OpenAI Swarm, each have a home shape, and only one home shape matches this product.
The shape and its requirements
Planner fanout synthesiser is the textbook supervisor pattern. The supervisor dispatches one of several workers; workers operate in parallel and report back; the supervisor decides whether to dispatch more workers or hand off to the synthesiser; the synthesiser composes the final report.
This shape has three structural requirements.
- Explicit routing. The supervisor must pick the next worker (or fan out to many) based on the planner's decomposition. The routing must be inspectable, deterministic, and replay-safe.
- Durable state. Research runs are long. Partial worker outputs must survive a crash, and a human must be able to inspect a run mid-flow without aborting it.
- Inspectability and human gates. Research products benefit from approving the plan before workers execute, and from time-travel debugging when a synthesised answer is wrong.
Each requirement maps to a framework primitive. Frameworks that lack the primitive force you to build it yourself; that build cost is what selects the right framework.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
from langgraph.graph import StateGraph, END
from langgraph.constants import Send
from langgraph.checkpoint.postgres import PostgresSaver
def plan(state):
return {"subqueries": planner_llm(state["query"])}
def dispatch(state):
# Parallel fan-out: one Send per subquery, each runs the worker node
return [Send("worker", {"subquery": sq}) for sq in state["subqueries"]]
def worker(state):
return {"findings": [analyse(retrieve(state["subquery"]))]}
def synthesise(state):
return {"report": synth_llm(state["findings"])}
g = StateGraph(dict)
g.add_node("plan", plan)
g.add_node("worker", worker)
g.add_node("synth", synthesise)
g.set_entry_point("plan")
g.add_conditional_edges("plan", dispatch, ["worker"])
g.add_edge("worker", "synth")
g.add_edge("synth", END)
app = g.compile(checkpointer=PostgresSaver.from_conn_string(POSTGRES_URL))
| Framework | Routing shape | Persistence | Best fit |
|---|---|---|---|
| LangGraph supervisor | Conditional edges + Send | Postgres checkpointer, time-travel | Planner fanout synthesizer |
| AutoGen GroupChat | Speaker selection (chat-shaped) | Shallow in 0.4 | Free-form analyst chat |
| CrewAI | Role/goal text, Hierarchical Process | Callbacks, no checkpointer | Sequential or hierarchical role pipelines |
| OpenAI Swarm / Agents SDK | Handoff via tool call | None native | Two-agent triage and handoff |
Real products, models, and research that use this idea.
- Anthropic's Claude research preview uses a planner workers synthesizer pattern that maps to a LangGraph-style supervisor
- OpenAI's Deep Research product implements a similar shape under the hood, planner, parallel browsers, synthesiser, backed by durable state for long-running queries
What an interviewer would ask next. Try answering before peeking at the approach.
QHow does LangGraph's Send primitive interact with the checkpointer for parallel fan-out?
Walk through how Send dispatches parallel node invocations with independent state shards, how each shard checkpoints separately, and how the runtime joins their results back into the parent state.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Defaulting to the 'depends on your team' non-answer. The deep-research shape has structural requirements (routing, persistence, inspectability) that select for LangGraph regardless of team taste.
60 second bullets to scan on the way to the call.
Why planner fanout synthesiser maps to supervisor with conditional routing
Three structural requirements: routing, durability, inspectability
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.