What you need to know
If you are starting an agent project in 2026, three Python frameworks will appear on every shortlist: LangGraph, CrewAI and the OpenAI Agents SDK. All three are production-viable. All three can call tools, coordinate multiple agents and stream results. And yet choosing between them is not a coin flip, because they encode three different answers to the same question: who controls what happens next?
LangGraph says you do — every transition is an explicit edge in a state machine you design. CrewAI says the framework does — you describe a team of role-playing agents and let its process engine coordinate them. The OpenAI Agents SDK says the model does — it hands the LLM a handful of primitives and stays out of the way. That philosophical split matters far more than any individual feature, because it determines how your system behaves when things go wrong, how hard it is to debug, and how expensive it is to run.
The short version, as of July 2026: LangGraph is the production leader for complex, stateful workflows — it pulls north of 65 million monthly downloads on PyPI and offers the deepest checkpointing and human-in-the-loop machinery, at the cost of a one-to-two-week learning curve. CrewAI, with more than 55,000 GitHub stars, wins on speed-to-prototype: a role-based crew is running in twenty lines, and its MCP support is the most first-class of the three. The OpenAI Agents SDK is the thinnest abstraction — agents, handoffs, guardrails and sessions — and gets you a multi-agent system with validation in under a hundred lines, though it is happiest inside the OpenAI ecosystem despite supporting 100+ models through LiteLLM.
The most common pattern we see among Builders in Bengaluru, Chennai, London and Manchester alike: prototype in CrewAI or the Agents SDK, validate the workflow with real users, then migrate the production-critical paths to LangGraph once durability and auditability start to matter. The rest of this guide explains why that pattern exists — and when you should ignore it.
Three philosophies: state machine, role crew, thin primitives
LangGraph — the explicit state machine
LangGraph models an agent as a directed graph. Nodes do work — call an LLM, run a tool, transform data. Edges define transitions, including conditional edges where a routing function inspects the state and decides where to go next. A shared, typed state object flows through the graph, merged at each step by reducer functions you declare. Nothing happens implicitly: if your agent can loop back to a research step, it is because you drew that edge.
That explicitness is the whole value proposition. Because every superstep is a known point in a known graph, LangGraph can checkpoint the entire state after each one. Checkpointing unlocks the features that define production readiness: durable execution that survives process restarts, human-in-the-loop interrupts that can pause a run for hours or days, and time-travel debugging where you rewind a thread to any historical checkpoint, edit the state and replay. LangGraph reached its stable 1.0 release with full backward compatibility, and the team behind it cites Uber, LinkedIn and Klarna among the companies running it in production. As of July 2026 it records tens of millions of monthly downloads on PyPI — comfortably the most-installed dedicated agent orchestration library in Python.
The cost is ceremony. You will define a state schema, write node functions, wire edges and think about reducers before your agent says a single word. Most engineers need one to two weeks to become genuinely productive, and the framework's durability concepts — checkpointers, threads, supersteps — are ideas you must actually learn, not conventions you can absorb by osmosis. It is also fully model-agnostic: the graph machinery does not care whether the node calls Claude, GPT, Gemini or a Llama model served from your own GPUs, which matters for teams with data-residency obligations in India or the UK. If you want a hands-on introduction, our step-by-step guide to building a LangGraph agent with state, tools and HITL walks the full path.
CrewAI — the role-based crew
CrewAI starts from a different metaphor: a team. You define agents with a role, a goal and a backstory ("a methodical research analyst who verifies sources"), give them tools, then define tasks and hand the lot to a crew with a process — sequential or hierarchical. The framework handles delegation, context passing and task ordering. For workflows that naturally decompose into human-like roles — researcher, writer, reviewer — this maps beautifully onto how you already think, which is why a working prototype takes an afternoon rather than a week.
CrewAI is an independent, open-source framework — built from scratch, not a LangChain wrapper — with more than 55,000 GitHub stars as of July 2026 and a large certified-developer community. Two capabilities stand out this year. First, Flows: an event-driven layer that adds precise, code-level control around crews, closing some of the gap with LangGraph for teams that outgrow pure autonomy. Second, first-class MCP (Model Context Protocol) support — MCP servers plug in as tool sources with minimal configuration, which matters more every month as the MCP server catalogue grows. It is model-agnostic via LiteLLM under the bonnet.
The trade-off is control. In a crew, the coordination between agents is partly LLM-driven: the framework prompts models to delegate, summarise and pass context. That costs tokens by construction: a routing decision that CrewAI makes with an LLM call is a routing decision LangGraph makes with an if statement, and delegation prompts carry prior task output as context. How much more you pay depends entirely on your workflow, so treat it as a variable to measure rather than a fixed penalty. It also makes exact behaviour harder to pin down. When a crew misbehaves, you are debugging emergent behaviour across role prompts rather than stepping through edges you drew yourself.
OpenAI Agents SDK — the thin primitives
The OpenAI Agents SDK is deliberately minimal. Its conceptual surface is four primitives: agents (an LLM with instructions and tools), handoffs (one agent delegating to another, implemented as a tool call), guardrails (input and output validation that runs alongside the agent) and sessions (persisted conversation history). A Runner executes the loop. That is the entire mental model — you can read it in one sitting, and a two-agent system with handoffs and guardrails fits comfortably in under a hundred lines.
Launched in March 2025, the SDK remains on a fast-moving 0.x version line as of July 2026 — mature enough for production, young enough that minor releases still land frequently. It is less locked-in than its name suggests: the official LiteLLM extension routes to more than 100 model providers, and any OpenAI-compatible endpoint works. But it is honest to call it ecosystem-centric. The built-in tracing dashboard lives on the OpenAI platform, the hosted tools (web search, file search, computer use) are OpenAI products, and the frictionless path assumes OpenAI models. What you give up relative to LangGraph is deep state control: there is no user-defined graph, checkpoint-level time travel or first-class rewind. What you gain is that there is almost nothing to learn and almost nothing that can surprise you.
The same task, three ways
Abstract philosophy is easier to judge with code. Here is the same small system — a researcher that uses a search tool, then produces a short brief — in each framework. Assume search_web(query: str) -> str exists as a plain Python function; if you want to write that tool layer well, see our guide to designing tools for AI agents.
LangGraph: nodes, edges, explicit loop
from typing import Annotated, TypedDict
from langchain.chat_models import init_chat_model
from langgraph.graph import StateGraph, START
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition
class State(TypedDict):
messages: Annotated[list, add_messages]
llm = init_chat_model("claude-sonnet-4-5").bind_tools([search_web])
def researcher(state: State) -> dict:
return {"messages": [llm.invoke(state["messages"])]}
graph = StateGraph(State)
graph.add_node("researcher", researcher)
graph.add_node("tools", ToolNode([search_web]))
graph.add_edge(START, "researcher")
graph.add_conditional_edges("researcher", tools_condition)
graph.add_edge("tools", "researcher")
app = graph.compile() # add checkpointer=... for durable state
result = app.invoke({"messages": [("user", "Brief me on the UK AI assurance market")]})
Every arrow is visible. The loop between researcher and tools exists because two lines of code created it, and swapping the model is one string. Adding durability later is a single argument to compile().
CrewAI: roles, tasks, a crew
from crewai import Agent, Task, Crew, Process
researcher = Agent(
role="Research Analyst",
goal="Find current, sourced facts about {topic}",
backstory="A methodical analyst who always cites sources.",
tools=[search_tool],
)
writer = Agent(
role="Technical Writer",
goal="Turn research notes into a crisp 200-word brief",
backstory="A concise writer for busy engineering leaders.",
)
research = Task(
description="Research {topic} and list key findings.",
expected_output="Bullet-point findings with source URLs.",
agent=researcher,
)
brief = Task(
description="Write a 200-word brief from the findings.",
expected_output="A 200-word executive brief.",
agent=writer,
)
crew = Crew(agents=[researcher, writer], tasks=[research, brief],
process=Process.sequential)
result = crew.kickoff(inputs={"topic": "the UK AI assurance market"})
Notice what is absent: no state schema, no edges, no routing function. You described a team and CrewAI coordinated it. That is delightful on day one and occasionally maddening on day thirty, when you need the writer to loop back to the researcher only under a specific condition and discover the process engine, not you, owns that decision — unless you reach for Flows.
OpenAI Agents SDK: agents and a handoff
from agents import Agent, Runner, function_tool
@function_tool
def search_web(query: str) -> str:
"""Search the web and return a summary of results."""
return my_search_backend(query)
writer = Agent(
name="Writer",
instructions="Summarise the research into a 200-word brief.",
)
researcher = Agent(
name="Researcher",
instructions="Research the topic thoroughly, then hand off to the Writer.",
tools=[search_web],
handoffs=[writer],
)
result = Runner.run_sync(researcher, "Brief me on the UK AI assurance market")
print(result.final_output)
This is the shortest of the three, and the control flow is the most implicit: the researcher decides when to hand off because its instructions say so. Guardrails, structured outputs and sessions bolt on with the same economy. For a team already on the OpenAI platform, the distance from idea to running agent is measured in minutes.
The decision matrix
The table below is the section to bookmark. Individual version numbers will churn; these dimensions — and each framework's position on them — have been stable for over a year and reflect deliberate design philosophy, not accidents of release timing. Positions dated as of July 2026.
| Dimension | LangGraph | CrewAI | OpenAI Agents SDK |
|---|---|---|---|
| State control | Full — typed state, explicit edges, reducers | Medium — process engine owns flow; Flows add control | Low — model-driven handoffs, no user-defined graph |
| Learning curve | 1–2 weeks to productive | Hours to first crew; days to solid | Hours — four primitives, one Runner loop |
| Observability | LangSmith integration; per-node tracing; OTel-friendly | Built-in tracing hooks; third-party integrations | Tracing dashboard on the OpenAI platform, on by default |
| Checkpointing | Native — every superstep; SQLite/Postgres savers; time travel | Task-level memory and checkpointing; coarser grain | Sessions persist history; no graph-level rewind |
| MCP support | Via LangChain MCP adapters | First-class — MCP servers as native tool sources | Official MCP support in the SDK |
| Model-agnosticism | Fully agnostic by design | Agnostic via LiteLLM | 100+ models via LiteLLM extension; smoothest with OpenAI |
| Best for | Production systems needing durability, HITL, audit trails | Rapid prototypes; role-shaped collaborative workflows | Fast starts; teams committed to the OpenAI ecosystem |
Read the matrix by rows, not columns. If one row is a hard requirement — say, checkpointing, because your agent approves invoice payments and a crash mid-run is unacceptable — that row alone can decide the question. If no row is a hard requirement, you are free to optimise for learning curve, and the right answer is probably whichever framework your team can ship with this fortnight. For the broader architectural context around these choices, our survey of agent design patterns covers the patterns every framework ultimately implements.
Production concerns: durability, error recovery, observability
Prototypes are judged by how fast they work; production systems are judged by how gracefully they fail. Three concerns separate the frameworks once real users arrive.
Durability. An agent that takes forty seconds and calls six tools will eventually be interrupted mid-run — a deploy, a pod eviction, a timeout. LangGraph's answer is the strongest: because state is checkpointed after every superstep, a restarted process resumes exactly where it stopped, and the same machinery powers approval workflows that pause for days. A Mumbai lending platform waiting on a compliance officer's sign-off and a London firm waiting on an FCA-regulated approval step have the same need, and it is the need LangGraph was built around. CrewAI persists task-level state and memory, which recovers coarser units of work. The Agents SDK persists conversation history through sessions, but an interrupted run is generally re-run, not resumed mid-loop.
Error recovery. Tools fail: APIs rate-limit, searches return nothing, schemas drift. In LangGraph you make failure a route — an error edge to a retry node, a fallback node, or an interrupt that escalates to a human. In CrewAI and the Agents SDK, recovery leans more on the model noticing the failure in a tool message and trying again, which usually works and occasionally burns tokens in a retry spiral. Wherever recovery lives, the groundwork is the same: tools that return structured, actionable errors rather than raw tracebacks.
LLM-mediated coordination is a token bill. Frameworks that route work by prompting a model to delegate — crew-style hierarchies especially — spend tokens on coordination that explicit transitions spend nothing on. Published comparisons vary too widely to quote a headline number, and none of them ran your workflow. Before you commit a high-volume workflow to any framework, run 50 representative tasks and record tokens per completed task. At Indian rupee or pound-sterling unit economics, orchestration overhead is the difference between a viable product and an expensive demo.
Observability. You cannot operate what you cannot see. Each framework ships its own lens — LangSmith for LangGraph, built-in tracing hooks in CrewAI, and the OpenAI platform's trace dashboard for the Agents SDK, which is on by default and genuinely excellent for its ecosystem. The strategic risk is that all three are framework-tied. The vendor-neutral move is to instrument your agent with OpenTelemetry spans so your traces outlive your framework choice; our guide to agent observability with OpenTelemetry covers the span design, tail-sampling and cost attribution in depth.
Keep your tool layer framework-neutral from day one. Write tools as plain Python functions with typed signatures and precise docstrings, then wrap them per framework — a LangChain @tool, a CrewAI tool class, an Agents SDK @function_tool — in thin adapter modules. Tools, prompts and eval datasets are 80 per cent of your agent's real IP; if they live outside any framework, switching frameworks becomes a re-wiring exercise instead of a rewrite.
Migration paths between frameworks
Framework choices are rarely final, and in 2026 the migration routes are well-trodden enough to plan around. The traffic is overwhelmingly one-directional: from convenient abstractions towards explicit control, as systems accrete users and audit requirements.
| Migration | How common | Typical trigger | Approach |
|---|---|---|---|
| CrewAI → LangGraph | The most common route | Hit the control-flow ceiling; need checkpointing or HITL | Map each crew agent to a node; convert the process order to explicit edges; move shared context into the state object |
| Agents SDK → LangGraph | Common for regulated workloads | Need durable state, rewind, or multi-provider guarantees | Each agent becomes a node; each handoff becomes a conditional edge; sessions map to checkpointed threads |
| LangGraph → Agents SDK | Rare | Team consolidation on the OpenAI platform; graph proved simpler than expected | Collapse linear node chains into single agents; keep only genuinely branching logic as handoffs |
| Anything → plain scripts | Underrated | The workflow turned out to be a fixed pipeline | Replace the framework with direct API calls in sequence; keep the tools |
The CrewAI-to-LangGraph route deserves a paragraph because so many teams walk it. The prototype phase in CrewAI is genuinely valuable — it forces you to articulate roles, tasks and expected outputs, which is precisely the specification you need for a graph. The migration is mechanical when your tools are framework-neutral: agents become nodes, the sequential process becomes edges, hierarchical delegation becomes a supervisor node with conditional routing, and crew memory becomes fields on the typed state. Teams that interleave the two — CrewAI for internal research crews, LangGraph for the customer-facing approval flow — report the least migration pain, because nothing has to move all at once.
Migrating away from the Agents SDK is similarly mechanical but emotionally harder, because you are trading real simplicity for capabilities you now need. Do it when a concrete requirement demands it — durable interrupts, provider-portability commitments to an enterprise client, checkpoint-level audit — and not because a comparison article told you the other framework is more powerful. Unused power is just surface area.
The verdict, as of July 2026
Dated deliberately, because verdicts in this space should carry timestamps. As of July 2026:
- Choose LangGraph when the agent is a product, not a feature — when runs must survive restarts, humans must approve actions mid-flow, auditors will ask what happened and why, or your clients in India and the UK impose different model and data-residency constraints. Budget the fortnight of learning; it is the highest-return fortnight in the agent stack.
- Choose CrewAI when you are validating an idea, the workflow decomposes naturally into roles, or MCP servers are central to your tool strategy. Accept the token overhead as the price of speed, and measure it before scaling.
- Choose the OpenAI Agents SDK when you are on the OpenAI platform and want the shortest path from idea to a traced, guarded, multi-agent system. Treat the LiteLLM escape hatch as insurance, not a strategy.
- Choose none of them when your workflow is a straight line. A script that calls an LLM twice needs no framework at all.
The releases will keep coming — every framework here shipped meaningful versions in the past quarter, and the numbers in this article will age. The decision criteria will not. Who controls the next step, what survives a crash, what a trace shows you at 2 a.m., and what a task costs at volume: those questions outlast every changelog, and they are the ones worth asking of whatever framework ships next.
Whichever you pick, the engineers who stand out are the ones who can explain the choice. "We prototyped the crew in CrewAI, measured what coordination was costing us per task, and migrated the approval path to a checkpointed LangGraph graph" is a sentence that gets you hired in Bengaluru or London. Ship something, write down why, and put it where the people hiring can see it.