LangGraph vs CrewAI: Multi-Agent Framework Comparison

What multi-agent frameworks actually do, and how the two most prominent paradigms — LangGraph’s state graphs and CrewAI’s role-based crews — differ, explained for a developer new to the space. Semantic Kernel, the enterprise third camp, gets its own section (§4). Prerequisites: LLM Tool Calling (the tool loop both frameworks run underneath) and ideally Building-an-AI-Agent-from-Scratch (the loop written by hand, so you can see what these frameworks are wrapping).

Related: Frameworks, runtimes, and harnesses, Choosing-the-Right-Agentic-Design-Pattern, Deep-Agents, A2A-Protocol, NAT-Lesson-0-Getting-Started.


1. What a multi-agent framework actually is

Strip the marketing: an “agent” is the while-loop from LLM Tool Calling §5 — model call, maybe tool calls, repeat until done. A multi-agent framework is a program that runs several of those loops and coordinates them: which agent acts next, what state they share, when the process stops, when a human gets to intervene. All of it in one process, under one roof, written by you.

(Contrast A2A-Protocol, which is for coordinating agents across organizational boundaries over the network. This note is about the in-house case — by far the common one.)

The interesting question a framework answers is: who decides the control flow? The two paradigms give opposite answers, and that single difference explains almost everything else in this note.

2. LangGraph: you write the state machine

LangGraph (from the LangChain team) has you define the workflow as an explicit graph: nodes are functions (an agent step, a tool run, a plain Python function), edges are transitions, and a shared, typed state object flows through. Cycles are allowed — that’s what makes it agentic rather than a one-way pipeline.

If you’ve written a C program with an explicit finite-state machine — a switch on a state enum inside a loop, each case doing work and setting the next state — you already have the mental model. LangGraph is that FSM, where some case bodies happen to call an LLM, plus a big quality-of-life layer:

workflow = StateGraph(SupportState)
workflow.add_node("classify", classify_ticket)      # each node: fn(state) -> state update
workflow.add_node("resolve", attempt_resolution)
workflow.add_node("escalate", escalate_to_human)
workflow.add_conditional_edges("classify", route_by_severity)  # the switch statement
workflow.add_edge("resolve", END)

What the framework adds over your hand-rolled FSM:

  • Durable execution. State is checkpointed at every step. Kill the process mid-workflow and resume exactly where it stopped — same idea as a database WAL or a long computation writing restart files. This is what makes tasks that span days feasible.
  • Human-in-the-loop as a primitive. interrupt() pauses the graph at a defined point, persists everything, and waits — hours if necessary — for a human verdict before the edge fires. An approval gate is a node, not an afterthought.
  • Time travel. Because every step is checkpointed, you can rewind a thread, edit its state, and replay — invaluable for debugging why an agent went sideways.
  • Observability via LangSmith, and visual debugging via LangGraph Studio.

The cost is exactly what you’d guess: you must design the graph. Control flow, state schema, edge conditions — all explicit, all yours. Steeper learning curve, more code for simple things.

3. CrewAI: you describe the team

CrewAI inverts the question. You don’t design control flow — you declare agents with a role, a goal, and a backstory, hand them tasks, group them into a crew, and the framework (and the LLMs themselves) work out the orchestration, including agents delegating to each other:

researcher = Agent(role="Research Analyst",
                   goal="Find accurate, current information on the topic",
                   backstory="A meticulous analyst who verifies every claim.")
writer = Agent(role="Technical Writer",
               goal="Turn research into a clear, structured article")
crew = Crew(agents=[researcher, writer],
            tasks=[research_task, writing_task])
result = crew.kickoff()

The mental model is delegation to a team of new hires: you write the job descriptions and the assignment, not the procedure. That’s the paradigm’s whole trade in one sentence — you give up explicit control flow and get speed of construction. A working multi-agent prototype in an afternoon is realistic; role descriptions map naturally onto business processes (“researcher → writer → editor” needs no translation); YAML-based config keeps non-programmers in the loop.

The costs are the mirror image of LangGraph’s strengths:

  • Control flow is emergent. Why did the researcher delegate back to the writer twice? The answer lives in prompts and model behavior, not in code you can read. Debugging is archaeology.
  • Determinism suffers. The same input can take a different path through the crew. Fine for content generation; disqualifying for an audit-trail workflow.
  • CrewAI knows this, and its Flows feature bolts explicit, event-driven control flow back on top — a tacit admission that real deployments end up wanting the state machine after all.

4. The third camp: Semantic Kernel

LangGraph and CrewAI frame the paradigm question; Semantic Kernel (SK), Microsoft’s open-source SDK, competes on a different axis entirely: language and ecosystem. It’s written natively in C# (with solid Python and Java runtimes), which makes it the default choice in .NET shops, Azure infrastructures, and anything Copilot-adjacent — territory where LangGraph and CrewAI, both Python-first, are guests rather than residents. Its design ethos is the opposite of LangChain’s move-fast sprawl: typed, stable, reviewed interfaces — a platform SDK, not a research codebase.

Three abstractions carry the whole framework:

  • The Kernel — the central coordinator: registers your models (OpenAI, Azure OpenAI, local), connectors, and functions, and manages state. Think of it as the dependency-injection container the rest plugs into.
  • Plugins — everything the model can do. A plugin mixes semantic functions (prompt templates) and native functions (real compiled code — a C# method that runs a SQL query or fires an HTTP POST). SK auto-generates schemas from them and hands those to the model — the same schema/handler split from LLM Tool Calling, with the schema-writing automated. Naming trap: SK plugins were historically called “skills,” which has nothing to do with the agent-skills standard in AGENTS-md-vs-SKILLS-md — collision of names, not of concepts.
  • Planners — SK’s agent layer. Instead of hand-wiring steps, you state a goal (“find invoices over 30 days late and email a polite nudge”) and the planner compiles an execution plan over the registered plugins, then runs it. If you know databases, this is a query planner: you declare the outcome, the planner produces the plan from the operators available, and an executor carries it out.

On this note’s axis, SK straddles: the plugin/kernel core is explicit and typed (LangGraph’s end of the spectrum), while planners are declarative goal-handoff (CrewAI’s end). Its real differentiators are the ones the axis doesn’t measure — type safety, enterprise security posture, and first-class .NET. Worth knowing: Microsoft has been consolidating SK and AutoGen into a unified Agent Framework (announced late 2025), so expect the multi-agent story to increasingly live under that name.

Rule of thumb: Python-first prototyping → LangGraph or CrewAI will be faster. A .NET/Azure enterprise that has to survive a security audit → SK is the most structured middleware on the market, and the one your compliance team will approve first.

5. Head to head

LangGraphCrewAI
Mental modelDesign the state machineAssemble the team
Control flowExplicit — nodes and edges you wroteEmergent — roles, goals, LLM-driven delegation
Determinism / auditabilityHigh; every step checkpointed and replayableLower; paths vary run to run
Human-in-the-loopFirst-class (interrupt())Possible, less granular
Long-running / resumable tasksNative (durable execution)Not the design center
Time to working prototypeSlower — you design a graph firstFast — declare roles and go
Learning curveSteep (graph + LangChain ecosystem)Moderate (intuitive API, YAML)
Debugging storyRead the graph; time-travel the stateRead the transcripts; infer
Natural fitSupport flows with approvals, financial/auditable pipelines, week-long tasksContent pipelines, research crews, rapid business-process prototypes

The pattern to remember: this is the same imperative-vs-declarative trade-off you’ve met everywhere else — a shell script with explicit if/else versus handing a goal to a capable subordinate. Explicit costs more up front and pays off in production; declarative is faster to a demo and murkier under failure.

6. Choosing (and the hybrid escape hatch)

  • Process must be auditable, resumable, or gated by humans → LangGraph.
  • Task is creative/collaborative and tolerance for path variance is high → CrewAI.
  • Shop is .NET/Azure, or the deployment must clear enterprise security review → Semantic Kernel (§4).
  • Genuinely both → the documented hybrid: LangGraph owns the outer workflow (sequencing, approval gates, persistence), and a CrewAI crew runs inside one node as a bounded “autonomous work session” — its output re-entering the deterministic graph for review. The state machine contains the free-for-all, never the reverse.
  • Neither, sometimes. One agent with good tools beats a multi-agent system you can’t debug. Reach for multi-agent when distinct roles genuinely need distinct prompts/tools/context windows, not because the demo looked good. (Choosing-the-Right-Agentic-Design-Pattern has the decision tree.)

7. The finding that reframes the whole question

Here’s what actually running the same task in multiple frameworks teaches — one working comparison put the identical catalog-and-quoting agent through LangChain, CrewAI, LlamaIndex, and Semantic Kernel side by side: with the same model, the same tools, and the same prompt discipline, the frameworks’ end results and even token costs land within a few percent of each other. The model does the thinking; the framework is plumbing around it.

So the framework choice is rarely about output quality. It’s about the engineering properties of the plumbing: debuggability, persistence, auditability, ecosystem, hiring. That also means the choice is less irreversible than it looks — which is exactly the bet wrapper layers like the NeMo Agent Toolkit make: wrap agents from any framework behind one config/observability surface, and the framework becomes a swappable implementation detail (NAT-Lesson-0-Getting-Started).

8. Resources