Seven of the most-used agent frameworks (LangGraph, CrewAI, the OpenAI Agents SDK, the Claude Agent SDK, Google ADK, Microsoft Agent Framework, and PydanticAI) compared hands-on, with real code rather than feature lists.
For an ordinary agent, the seven are roughly the same. The basics are table stakes. The frameworks differ on a handful of specific things, and whether those things matter depends entirely on the shape of the job.
The useful question is "what shape is this job?" Below: the vocabulary, the three things that actually differ, the seven frameworks in one table, the method, one worked example that was actually run, and what real companies chose.
First, six words
Six terms cover everything that follows.
Model: the "brain in a jar." Text in, text out. It has no memory of its own and takes no actions.
Tool: a function given to the model so it can do things: search, calculate, read a file. The model asks for it; the application code runs it.
Loop: think → use a tool → see the result → repeat → stop when done. It's a loop whenever the next step depends on the last one.
Harness: the code that orchestrates the model: driving the steps, calling the tools, holding the state. The body for the brain.
Agent: model + harness, working toward a goal and deciding its own next steps.
Framework: the toolkit for building agents. Each ships one or more harnesses. (Vendor ones are called "SDKs," which is just their official library.)
One more distinction quietly decides more than any feature list: who decides the path. In some places the model decides ("should I call this tool now?"), a judgment call that differs every time. In others the engine decides ("after step 2, always run step 3"), fixed wiring that is the same every time. Where the fixed wiring lives is one of the three real differences below.
The three things that actually differ
1. Durability: what happens when it dies halfway, and who can wait
A seven-step workflow crashes at step five: redo everything, or resume at five? This is the single most consequential difference between frameworks, and the one least often asked up front.
Some engines auto-save a snapshot of the run after every step, called a checkpoint. If the server restarts, the run continues exactly where it stopped. Others hold the run only inside the running process: a restart means starting over. A third group sits in between: the run's state can be saved explicitly at certain points, for example when it pauses at a tool call, but nothing saves it automatically.
For a research summary, redoing is fine. For anything that already sent two of five emails, or already changed a salary, redoing is damage.
Human approval is the same question in disguise. Instant approval, where a person clicks yes or no while the program is running, is easy everywhere. Durable approval, where the approver answers on Thursday and the server was redeployed on Wednesday, needs the run's position saved with the pending question attached. Only frameworks that save the run's position can do that.
2. Control inside the loop: can the flow be shaped?
Some frameworks provide a ready-made loop that can be nudged but not redrawn; the fixed wiring is then plain Python written around the agent. Others expose the flow itself as a construct: any step to any step, pause anywhere, control over how parallel results merge.
3. Multi-agent patterns: how teams of agents are wired
Multi-agent setups come in many named patterns, but two questions sort them all: does every agent work, or just one? and do the agents hear each other? A router sends the job to one specialist, and the others never run. The choice of specialist can be made by code (a classifier and a rule) or by the model reading the request; when the model chooses and then passes the whole conversation to that specialist and steps out, it is called a handoff. A pipeline runs all of them in order, each seeing only the previous result. A supervisor hands out work and collects it but never does the job itself. A group chat lets everyone read everything with a moderator giving turns.
Seven frameworks, one shape each
Each of the seven was built around a different shape of problem. The shape identifies the framework; the features follow.
| Framework | Built for | The tell | Durability |
|---|---|---|---|
| LangChain / LangGraph | Complex, reliable, stateful flows, drawn explicitly | Fine control inside the loop; the most capable and the most complex of the seven. | Autosave: snapshot after every step |
| CrewAI | A team of role-agents collaborating | Little code to get a team running: researcher → writer → editor. | None across restarts |
| OpenAI Agents SDK | Routing: triage a request to the right specialist | Built-in tracing, minimal setup. | None across restarts |
| Claude Agent SDK | One capable agent operating a computer | Files, terminal, and web tools ship built in and run on the host machine. Coding agents are the dominant use. Claude-only. | None across restarts |
| Google ADK | Structured multi-agent pipelines | Compose agents as Sequential / Parallel / Loop; Google-Cloud-native; open A2A (agent-to-agent) protocol for agents from different systems or companies. | Partial: persistence exists; the approval pattern must be assembled |
| Microsoft Agent Framework | Durable enterprise workflows on Azure / .NET | Released April 2026 as Microsoft's successor to its two earlier agent libraries, AutoGen and Semantic Kernel; the only one shipping group chat natively. | Autosave: snapshot after every step |
| PydanticAI | Typed agents inside ordinary Python code | Declare output_type=Schema and answers come back validated and auto-retried; fake models for keyless tests. | Save file, no autosave: pauses at tool calls survive; crashes don't |
The method: classify, check, choose
The decision, as a schematic
Question 1: what shape is the job? Score it on the three differences (durability, control, team wiring) plus two constraints frameworks don't create but must respect: real-time or background, and the ecosystem the organization already lives in.
Question 2: is there a requirement that decisively points to one framework? If yes, it decides, and the rest is detail. Genuinely near-unique requirements are rare. A durable human approval anywhere in a workflow points to the frameworks with full autosave, LangGraph first. Native real-time voice points to a model owner's stack, OpenAI or Google, because native audio needs a native-audio model plus a live-streaming engine, and only they ship both.
Question 3: no decisive requirement? Pick by shape, least work. Match the job to the framework built for that shape: others could do it; that one does it with the least code. Extra power is a cost when the job does not need it.
Then choose the harness inside the framework; most ship both a ready-made loop and a more controllable engine (LangChain's ready-made agent versus LangGraph, CrewAI's Crews versus Flows, ADK's fixed workflow agents versus model-decided delegation). Sketch the architecture as boxes and arrows, not code: where it branches, where it pauses for a human, where it fans out to tools, where state is saved. And say why not the others: wrong shape, overkill, or missing the hard requirement. A choice without a "why not" is a preference, not a decision.
A worked example, actually run
The scenario: a message arrives saying "new salary for Alex is 500 from the 1st." Small changes are auto-approved; large ones go to the COO.
Classify it. Approval-gated. Shape: receive → route by amount → (on approval) fan out to three tools → record. State: long-lived. Multi-agent: a router plus a few tool calls, not a collaborating team. Async, not real-time. No ecosystem constraint.
The decisive requirement. Yes: durable approval. The COO may take days, and a salary change recorded twice because a restart replayed the run is damage, not a bug. That single requirement points to LangGraph.
The architecture adds one thing to that shape: an interrupt-and-checkpoint at the approval step. The part that matters is short:
# the node that pauses for the human
def approval(state):
decision = interrupt(f"Approve {state['amount']}?") # PAUSES here
return {"decision": decision}
graph = builder.compile(checkpointer=InMemorySaver()) # in-memory for the demo; a database checkpointer (SQLite/Postgres) survives a real restart
graph.invoke({"amount": 500}, config) # runs, then PAUSES for approval
# ... hours or days may pass here; with a database checkpointer, so may a restart ...
graph.invoke(Command(resume="approved"), config) # resumes EXACTLY where it stopped
=== big amount (needs approval) ===
[receive] request: Alex -> 500
PAUSED ASKING: Approve salary change for Alex to 500?
=== COO approves; resume from the exact pause ===
[approval] human decided: approved
[record] audit log:
- HR: Alex = 500 (approved)
- Accounting: Alex = 500 (approved)
- Finance: Alex = 500 (approved)
final decision: approved
The interrupt() is not a prompt asking the model to please wait; it's the engine stopping the graph and saving its position. The model cannot "infer that it didn't need permission," because the model was never asked. That distinction, an approval enforced by code versus an approval requested in a prompt, is the difference between a gate and a suggestion.
Why not the others? CrewAI's Flows could express every step of this flow; only the days-long pause rules it out. Make the approval instant (the COO clicks now, same session) and CrewAI is perfectly fine. That "if" is the whole lesson: change one requirement and the answer changes.
A production version needs one more node up front, a model reading the incoming email into structured fields, and that node is where validation and security work actually live. The demo takes clean inputs; the real world doesn't.
Who chose what, and why
One public case per framework. Metrics are vendor-reported; companies rarely publish why they rejected alternatives, so the reasoning is read off the shape of each job.
| Company | Job | Framework | Why this framework |
|---|---|---|---|
| Klarna | Customer-support assistant for ~85M users; reports ~80% faster resolution and the work of 853 full-time support staff | LangGraph | Millions of conversations that pause for a human or an external system and must resume exactly, even after a crash, with an audit trail. A lighter framework would have had to bolt persistence on. |
| KPMG | Clara AI audit agents: select expenses to test, ingest documents, extract data, draft the workpaper. The auditor reviews and signs off. | Microsoft Agent Framework | Not a feature decision but an ecosystem one. KPMG already had Semantic Kernel code, a decade-long Microsoft alliance, and regulated-industry governance requirements met by Azure. The framework followed the cloud the firm already lived in. |
| Box, HubSpot, Canva | Product agents whose core decision is which specialist, or which data source, should handle a request | OpenAI Agents SDK | The job is routing, and all three were already building on OpenAI models. Nothing in it needs state that survives a crash, so the thin routing SDK was the least work. |
| A Fortune 500 consumer-products company | Modernizing legacy Java and SAP code: one agent updates, another tests, a human reviews | CrewAI | The work maps one-to-one onto roles: updater, tester, reviewer. No step needs to survive a restart, so the framework's weakest area never comes into play. |
| Coding-agent deployments | Reviewing pull requests in CI (the automated build-and-test pipeline), developer tooling | Claude Agent SDK | The task is operating a computer over many steps: read files, run commands, check results. In every other framework those tools would have to be written first. |
| Gordon Food Service & Tyson | A cross-company supply-chain agent | Google ADK | Agents owned by two different companies have to exchange tasks, which needs an open protocol both sides can implement. Google Cloud was already the deployment target. |
| deepsense.ai | Document processing: messy documents in, validated structured data out | PydanticAI | The entire job is producing validated, typed data from unstructured input. The team's own verdict: a graph-based approach "added unnecessary complexity" for what is mostly a linear flow. |
One more thing the seven have in common: each agent does a single, clearly bounded job (support questions, one code-modernization task, one audit workflow). None is a general-purpose assistant. A narrow job can be tested, measured, and given exactly the tools and approvals it needs; a broad one cannot. The narrowness is not a limitation of these deployments. It is why they work.
Mixing frameworks: the one rule
Frameworks can be combined, and one combination is standard practice: a document library (LlamaIndex, which makes a model answer from your own files) used as one tool inside a PydanticAI or LangGraph agent. The glue is always the same: a tool is just a function, and a function body can run anything, including another framework's agent.
The rule that keeps this safe has two parts. Exactly one framework owns the outer loop; every other framework is a function it calls. And the outer one must carry the hardest requirement, because durability is a property of whoever owns the loop. A save is only as good as the caller's memory: if a checkpointing engine sits inside a tool of a framework that keeps no checkpoints, the inner engine saves its position while the calling program forgets it ever made the call. So: the durable engine outside; the inner ones must be request → response, never pausing for days themselves.
A protocol such as A2A belongs at real boundaries: separate teams, frameworks that cannot share a process, one agent shared by many products. Inside one codebase, a function call beats a network hop.
The part that isn't the framework
The framework is roughly 20% of a production agent. The other 80% is ordinary engineering wrapped around a component that is non-deterministic: it answers differently each time. That's the whole difficulty, and every production topic is a way of taming it:
- Traces: a flight recorder per run, capturing every step, prompt, tool call, and cost. When an answer was wrong, the run shows that step 3 extracted 5,000 instead of 500. Each framework has a first-party answer (LangSmith for LangGraph, Logfire for PydanticAI, the OpenAI SDK's built-in tracing).
- Evals: a scored test set run continuously, such as fifty cases with known-good answers, graded on every change. Without them a model cannot be upgraded safely, because model updates shift behavior silently. Most teams do not have them; it is the most common gap in production agent systems.
- Validation and gates: the model's output is a draft, not an oracle. Typed outputs (the answer must fill a declared form), checks against an independent source of truth (the message says Alex's new salary is 500; does Alex exist in the HR system, and is 500 a plausible change from the current record?), and a human gate on every irreversible action.
- Permissions and sandboxing: an agent with tools is a user with permissions. The dangerous tool shouldn't exist, not merely be forbidden; the process should run as a dedicated low-privilege user behind a firewall that allows only the addresses its job needs; and anything that executes model-generated code belongs in a proper sandbox.
Two practical notes. Cost: the frameworks are free and open-source; the model calls are the cost, and a chatty multi-agent setup can use many times the tokens of a single agent. Paid products exist only at the edges (managed durability and hosting, observability dashboards), all optional. Lock-in: switching models is cheap (most frameworks change providers in a line; the Claude SDK is the exception). Switching frameworks is not: tools and prompts port easily, but the orchestration wiring is rewritten from scratch, which is why teams tend to stay with their first choice for years. That makes the first choice worth getting right, and the way to get it right is the shape of the job.
The skill isn't memorizing frameworks. It's seeing the shape of the problem.
Before asking "which framework?", describe the job: what it must survive, how much control over the flow it needs, how many agents it takes and how they talk. The sharpest of those questions, what happens if it dies halfway through?, often narrows the choice to one framework on its own. The rest follows from the shape.
Sourcing & honesty. Company examples are drawn from published case studies and reporting. Durability, human-in-the-loop, and typed-output claims were checked by running code, keyless on local models where possible. This space moves fast; features and figures are current as of September 2026.