LangChain, CrewAI and AutoGen all describe themselves as agent orchestration and disagree about what an agent is. A comparison of the model each one holds, the code you write in it, what it costs to debug, and the important thing all three have in common: none of them is what you want for running coding agents on your own repository.
the short version
LangChain, through LangGraph, orchestrates a graph of steps you author. CrewAI orchestrates a cast of roles and does the delegating for you. AutoGen orchestrates a conversation, and the agents decide what happens next by talking. All three use the word orchestration and none of them means the same thing by it, which is why comparing them on features produces a table nobody can act on.
The real question is how much of the control flow you want to own. LangGraph gives you all of it and charges you the code. CrewAI gives you very little of it and charges you the guesswork when a run goes sideways. AutoGen puts it in the model's hands, which is the most flexible and the hardest to stop. Pick by that axis, not by which one has more integrations.
what each one means by agent
Start here, because every other difference falls out of it.
LangChain and LangGraph: an agent is a function in a graph
LangChain began as a library of components: prompt templates, model wrappers, retrievers, output parsers. Chaining them was the original idea and the original name. LangGraph is the part that does orchestration, and it is a different abstraction sitting on the same ecosystem. You declare a state object, you register nodes that take that state and return an update to it, and you wire edges between them, including conditional edges that branch on the state. Cycles are allowed, which is the whole point: an agent loop is a node that routes back to itself until a condition says stop.
In this model an agent is not a special kind of object. It is a node that happens to call a model and maybe some tools. Nothing about the framework knows what a role is or what delegation means. That is either the clean part or the tedious part depending on what you are building.
CrewAI: an agent is a persona
CrewAI models a team of people. You write an agent by giving it a role, a goal and a backstory, all in natural language, plus a set of tools. You write tasks with a description and an expected output, and you assign each task to an agent. Then you put the agents and the tasks in a crew and choose a process: sequential, where tasks run in the order you listed them, or hierarchical, where a manager agent decides who does what and in which order.
The persona text is not decoration. It goes into the prompt, so the backstory is functionally part of the system message. This is worth knowing because it explains both why CrewAI is so quick to start with and why its behaviour can feel non-deterministic: you are tuning behaviour by editing prose, and prose does not have a type signature.
AutoGen: an agent is a participant in a chat
AutoGen's core idea is that multi-agent work is a conversation. Agents send each other messages. A group chat has a set of participants and a rule for choosing who speaks next, which might be round robin or might be a model deciding. Control flow is emergent: the sequence of who does what is whatever the conversation produced this time.
This is genuinely powerful for open-ended problems, and it is also where AutoGen's hardest problem lives. A conversation has no natural end. Termination is something you have to construct, usually from some combination of a maximum message count, a text marker an agent is prompted to emit, or an explicit condition on the transcript. Getting that wrong gives you two agents thanking each other in a loop while the meter runs.
what the code you write actually looks like
Three small blocks, one per framework. These are illustrative shapes, not copy-pasteable production code: they exist to show what the authoring surface feels like, and the exact names and arguments differ by version. Check the current docs before you type any of it.
LangGraph
# illustrative shape, not runnable code
graph = StateGraph(MyState) # state is a typed object you define
graph.add_node("plan", plan_fn) # a node is a function: state -> state update
graph.add_node("write", write_fn)
graph.add_edge("plan", "write")
graph.add_conditional_edges("write", route_fn) # route_fn reads state, returns a node name
app = graph.compile()
app.invoke({"task": "..."})Note what is visible in six lines: every transition, the shape of the state, and the function that decides branching. Nothing is implied. That is the trade, and it is the reason LangGraph code is longer than the equivalent in either of the others.
CrewAI
# illustrative shape, not runnable code
researcher = Agent(role="Researcher",
goal="Find primary sources",
backstory="You are careful and cite everything.")
writer = Agent(role="Writer", goal="Draft the brief")
t1 = Task(description="Research X", expected_output="Notes", agent=researcher)
t2 = Task(description="Write it up", expected_output="500 words", agent=writer)
crew = Crew(agents=[researcher, writer], tasks=[t1, t2]) # process: sequential or hierarchical
crew.kickoff()Nothing here says how the output of the first task reaches the second. The framework handles that. If you like that, this is the shortest path from an idea to something that runs. If you do not, you have just given away the part you most wanted to see.
AutoGen
AutoGen's API changed substantially between its early line and its later rewrite, so rather than assert a signature we cannot pin to a version, here is the shape in words. You construct two or more agents, typically an assistant backed by a model and some form of proxy that executes tools or represents the human. You put them in a group chat with a strategy for selecting the next speaker. You attach a termination condition, most commonly a message cap, a text marker, or both combined. Then you start the chat with a first message and let it run.
# illustrative shape, described rather than typed
assistant = an agent backed by a model
executor = an agent that runs tools, or stands in for the human
team = group chat: [assistant, executor] + a speaker-selection rule
terminate = "stop when a message contains DONE, or after N messages"
run(team, "the task")The interesting line is the fourth one. In the other two frameworks termination is structural: the graph runs out of edges, or the task list runs out of tasks. Here it is a rule you wrote, competing against a model that has been asked to be helpful.
debugging a run that went wrong
This is the axis people underweight when choosing and complain about a fortnight later. A framework is not the code you write on a good day. It is what you can see on a bad one.
LangGraph is the easiest of the three to reason about after the fact, for a structural reason rather than a tooling one: the state object is explicit, so a failed run has a value you can print at every node boundary. You can ask which node ran, in what order, and what the state looked like going in. LangSmith, the paid tracing product from the same company, is the sanctioned way to see all that in a UI, and that is worth noticing as a commercial fact: the observability story is a product, not just a library feature.
CrewAI is the hardest, and it is the direct cost of its convenience. When a crew produces a bad answer you have to work out whether the role text was wrong, the goal was ambiguous, the task description underspecified, the tool description misleading, or the manager agent simply delegated badly. All five look identical from outside: bad output. Verbose logging shows you the messages, which helps, but the framework made the routing decision and the routing decision is the thing you most want to interrogate.
AutoGen sits in between and fails differently. The transcript is right there and it is readable, which is a genuine advantage: you can see exactly what each agent said. The problem is length. A group chat that went wrong for twenty messages before you noticed is twenty messages you have to read, and the failure is usually not one bad message but a slow drift in what the agents think they are doing. Reading a transcript is easy. Diffing two transcripts to find where behaviour diverged is not.
state and memory
The three answers are as different as the mental models, and they follow from them directly.
The practical consequence is about long runs. If your workflow needs to survive a process restart, resume from the middle, or be inspected by something that is not the framework, an explicit serialisable state object is worth a lot and a conversation transcript is worth less. If your workflow finishes in one go, this difference costs you nothing and LangGraph's ceremony is pure overhead.
whose control flow is it
Here is the single sentence version. In LangGraph the control flow is code. In CrewAI it is configuration. In AutoGen it is a model output.
That ordering is also an ordering of how much you can predict before you run anything. A LangGraph you can read the way you read any state machine, and you can unit test a node in isolation because it is a function. A CrewAI crew you can read as an intention, and the sequential process is fairly predictable while the hierarchical one is a manager agent making live decisions. An AutoGen group chat you cannot predict at all, by construction, because the ordering is the thing being computed.
None of those is wrong. Emergent ordering is exactly what you want when the shape of the problem is not known in advance, and hand-wiring a graph for a task you will run once is wasted effort. What is wrong is choosing a framework whose control-flow model does not match how predictable your problem needs to be, which is the most common way these choices go bad.
humans in the loop
Every framework claims human-in-the-loop support and they mean noticeably different things by it.
AutoGen has the most natural fit, because a human is just another participant in a conversation. A proxy agent can be configured to ask a person before it acts, and since the whole system is already message-passing, inserting a human is not an exception to the model. It is the model.
LangGraph handles it structurally: because execution is a graph with checkpointed state, a run can be interrupted at a node boundary, inspected, edited and resumed. This is arguably the more useful shape for anything approval-flavoured, since the pause point is somewhere you chose rather than wherever the conversation happened to reach, and the state you approve is a value rather than a paragraph.
CrewAI supports asking for human input on a task, which covers the common case of checking work before it moves on. It is the least granular of the three, which is consistent with the rest of its design: you are working at the level of tasks, so that is the level at which you can intervene.
maturity and churn
We are not going to quote version numbers or release dates here, because they would be wrong within weeks and this is a space where being confidently stale is worse than being vague. Two things can be said fairly.
First, all three have made breaking changes at the level of core concepts, not just signatures. LangChain reorganised into separate packages and grew LangGraph as a distinct thing. AutoGen was substantially rearchitected, to the point that tutorials written for the earlier line do not run against the later one. CrewAI has been steadily adding surface area, including a separate flows abstraction for people who wanted explicit control back. If you search for help, check what version the answer was written for before you trust it.
Second, all three carry real commercial context. LangChain has a paid observability and deployment platform. CrewAI has an enterprise offering. AutoGen comes out of Microsoft Research. None of that is a criticism, and a funded project is often a better bet than an unfunded one, but it does shape which parts get polished. Tracing, deployment and dashboards are the parts most likely to sit behind a paid tier in any of them.
how to choose, and what each is genuinely best at
Two questions get you most of the way. How predictable does the ordering need to be, and who is going to debug this in a month.
LangGraph is best at durable, inspectable workflows
If the thing you are building is going into production, has to survive restarts, needs an approval step in a specific place, or will be debugged by someone who did not write it, the explicit graph pays for itself. It is the only one of the three where you can point at a diagram of your system and be confident the diagram is true. Cost: more code for the same first demo, and a learning curve that is genuinely steeper because you have to hold the state-machine model in your head before anything runs.
CrewAI is best at getting a plausible multi-agent workflow running fast
The role metaphor is a real ergonomic win. Describing a researcher and a writer and letting the framework wire them is a shorter distance from idea to output than anything else here, and for prototypes, internal tools, content pipelines and demos that is exactly the right trade. It is also the easiest of the three to explain to someone who does not write code, which matters more than engineers usually admit. Cost: the routing you did not write is the routing you cannot inspect, and tuning behaviour through backstory prose has no ceiling and no test suite.
AutoGen is best at open-ended problems and at research
When you genuinely do not know the right sequence of steps, letting agents negotiate one is not a workaround, it is the feature. Conversation is also the most honest interface for anything where a human needs to be in the middle, and the transcript you get out is the most readable artefact of the three. Cost: termination is your problem, cost control is your problem, and the same emergence that finds a surprising solution will sometimes find a surprising way to waste twenty calls.
the thing none of them does
Now the part that matters if you arrived here from a search about running coding agents, because it is the most common mismatch we see and it is not the frameworks' fault.
All three of these orchestrate model calls inside one Python process. The agents are objects in memory. The tools are functions you registered. The whole run starts when you call something and ends when it returns. That is the correct design for what they are for, and it is not the shape of the problem you have when you want Claude Code in one pane, Codex in another and Grok in a third, all working on the same repository.
Those are not objects. They are long-lived processes with their own shells, their own context windows, their own tool permissions and their own opinions about your files. You are not composing model calls. You are supervising concurrent programs that edit a shared working tree. We wrote up that distinction at length in what AI agent orchestration actually means, and the short version is that framework orchestration and workspace orchestration are two different problems that share a word.
Three concrete things the frameworks do not address, none of which is a gap in their design so much as a category they are not in.
The tools that do address those are a different category, and they mostly look like desktop apps, terminal multiplexer front ends and worktree managers rather than Python libraries. We keep an honest table of them, including where each one beats us, at the comparison page. If you are choosing between LangGraph and CrewAI for a document pipeline, that page is irrelevant to you and this post's earlier sections are the useful part. If you got here because you have four terminals open and no idea what they are collectively spending, the frameworks are not the answer and it is better to say so plainly than to sell you one.