agent_signal

Guide

LangGraph vs CrewAI: Which Agent Framework to Use

By Agent Signal · Published 2026-10-15 · Updated 2026-10-15

If you're choosing between LangGraph and CrewAI, you aren't really picking a "better" framework. You're picking where the control flow lives. LangGraph has you draw the graph yourself. CrewAI starts from a team of role-based agents and gives you Flows when you need to pin the steps down. This guide compares the two on the things that decide production fit: how execution is ordered, how state is kept, how a human approves a step, and how memory works. Every claim links to the official docs.

TL;DR

You need… Lean toward
Explicit, inspectable control flow you define node by node LangGraph
A quick "team of specialists" with roles and tasks CrewAI (Crews)
Event-driven pipelines that chain crews and plain code CrewAI (Flows)
Pause-for-approval that survives restarts Both can do it. Read the persistence and HITL sections
Long-term memory that works out of the box CrewAI's Memory is more batteries-included; LangGraph gives you a store primitive

1. Execution model: who decides what runs next?

LangGraph. You build a StateGraph, add nodes (plain functions that read and return state), and connect them with edges and conditional edges. The LangGraph interrupts docs show the full pattern: builder.add_node(...), builder.add_edge(START, "agent"), builder.add_conditional_edges("agent", should_continue, [...]), then builder.compile(checkpointer=...). The classic agent loop is literally a cycle in your graph: an agent node calls the model, a conditional edge routes to a tool_node when the model asked for tools, and an edge leads back to agent. Nothing runs that you didn't wire up.

CrewAI Crews. A crew is a set of agents plus a list of tasks, and you choose a process. The CrewAI Processes docs define two:

So with hierarchical crews, an LLM manager decides the order at runtime. That's handy for open-ended work, but it's less predictable than a graph you wrote yourself.

CrewAI Flows. For deterministic orchestration, CrewAI has Flows: "structured, event-driven workflows" built from decorated methods.

The docs say Flows support "conditional logic, loops, and branching" and can call whole Crews, single Agents, or bare LLM calls from any step.

Takeaway: a LangGraph graph and a CrewAI Flow are much closer than their marketing suggests. Both give you explicit, code-defined control flow. The real difference is that CrewAI also offers the higher-level crew abstraction (roles plus processes), while LangGraph starts low-level.

2. State

LangGraph state is a typed schema (the docs use TypedDict or Pydantic) that every node reads and partially updates. You can attach reducers to fields. The interrupts docs annotate a list with operator.add so parallel nodes append to it instead of overwriting it.

CrewAI Flows give you both options. Unstructured state is a dict on self.state. Structured state is a Pydantic BaseModel passed as Flow[MyState]. Either way, each state automatically gets a UUID id (Flows docs).

Both get you typed, validated state if you want it. Use it. Untyped dict state is the first thing to rot in a growing agent.

3. Persistence and resuming

This is where production pain usually shows up.

LangGraph has two persistence layers (Persistence docs):

The docs give clear warnings:

CrewAI puts persistence on Flows with the @persist decorator, at class or method level (Flows docs).

4. Human-in-the-loop

LangGraph: you call interrupt(payload) inside any node (Interrupts docs).

Three rules from the docs that will bite you if you skip them:

  1. The node re-runs from the top on resume. Code before interrupt() runs again, so side effects before it must be idempotent. Put them after the interrupt or in a separate node.
  2. Don't wrap interrupt() in a bare try/except. It works by raising a special exception, and catching it breaks the pause.
  3. Keep interrupt order deterministic. Resume values are matched to interrupts by index, so skipping one conditionally or looping over changing data misaligns them. For validation loops, call interrupt() once per node and loop with a conditional edge, not while True.

CrewAI: the @human_feedback decorator (CrewAI ≥ 1.8.0) pauses a Flow method to collect feedback (Flows docs).

Design note: CrewAI's LLM step that turns feedback into an outcome is convenient, but it adds a model call to your approval path. For anything irreversible (payments, deletes, outbound email), consider a strict boolean outcome rather than free text parsed by an LLM. LangGraph's typed response_schema gets you that directly.

5. Memory

LangGraph keeps short-term memory in thread state through checkpointers and long-term memory in stores (Persistence docs). What you remember, when, and how you retrieve it is up to you.

CrewAI ships a unified Memory class (Memory docs) that replaces the older short-term, long-term, entity, and external memory types.

So CrewAI gives you a lot for free, including hidden LLM calls and an OpenAI default. LangGraph gives you primitives and leaves the policy to you. We cover this in depth in our AI agent memory guide.

6. Observability and cost

How to choose

Pick LangGraph if:

Pick CrewAI if:

Use Flows as soon as you need determinism. Hierarchical crews let an LLM manager decide the order.

Either way, the production checklist is the same:


Agent Signal is a weekly newsletter for people building AI agents. Subscribe to get the next deep dive.

Free starter pack

The approval-flow starter pack

Tested human-in-the-loop approval starters for LangGraph, OpenAI Agents SDK, Vercel AI SDK and Google ADK, plus the weekly Agent Signal newsletter. Free.

Get tested agent templates weekly