LangGraph vs Claude Agent SDK: which one for your agent stack?
One is an orchestration runtime you wire by hand; the other is a batteries-included agent loop. They aren't rivals — they sit at different layers. Here's how to tell which job needs which, with diagrams and the hybrid that uses both.
TL;DR
- LangGraph is a graph-shaped orchestration runtime. You draw the flow yourself: nodes, edges, state, checkpoints. Model-agnostic, total control, more code.
- Claude Agent SDK is a batteries-included agent runtime: an agentic loop with real file/bash/ search tools, subagents, hooks, MCP, and context management — the same engine as Claude Code. Fast to ship, tightly coupled to Claude.
- They don’t compete. LangGraph owns the stateful business flow; the Agent SDK owns the agent doing real work on a machine or codebase.
1. Two different philosophies
LangGraph: you draw the flow
LangGraph models an agent as a state graph. You declare a StateGraph, each node is a function that
takes the state and returns an update (merged through a reducer), and edges decide where to go next —
including conditional edges and loops.
Its real power: you can mix deterministic steps and LLM-decided steps in one graph. Want step 3 to always hit Postgres before the model gets a say? Hard-code that node.
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver
from typing import Annotated, TypedDict
import operator
class S(TypedDict):
messages: Annotated[list, operator.add]
retries: int
def plan(s: S): ...
def act(s: S): ...
def route(s: S):
return "act" if s["retries"] < 3 else END
g = StateGraph(S)
g.add_node("plan", plan)
g.add_node("act", act)
g.add_edge(START, "plan")
g.add_conditional_edges("plan", route, {"act": "act", END: END})
g.add_edge("act", "plan")
app = g.compile(checkpointer=MemorySaver())
flowchart LR
START((START)) --> plan[plan node]
plan --> route{route}
route -->|retry| act[act node]
route -->|done| E((END))
act --> plan
plan -. checkpoint .-> DB[(state store)]
act -. checkpoint .-> DB
Three features that genuinely earn their keep:
- Persistence / checkpointing — state is saved after every super-step. If the process dies mid-run, it resumes exactly where it stopped. This is the foundation for durable execution of workflows that run for hours.
- Human-in-the-loop — pause the graph, let a human edit the state, then continue. Not a hack — a
first-class primitive (
interrupt). - Granular streaming — stream by token, by node, or by state update.
Claude Agent SDK: you assign the work
The Agent SDK goes the other way: the agent loop is already written — by the team behind Claude Code. You don’t build a graph; you configure an agent and drop it into an environment.
from claude_agent_sdk import query, ClaudeAgentOptions
options = ClaudeAgentOptions(
system_prompt="You are an SRE for a Proxmox homelab.",
allowed_tools=["Read", "Grep", "Bash"],
permission_mode="acceptEdits",
cwd="/opt/hive",
)
async for msg in query(prompt="Find why the gateway container is getting OOM-killed", options=options):
print(msg)
What you get from the very first line:
- Real work tools: read/write files, glob/grep, run bash, fetch/search the web. No re-implementing a filesystem tool layer for the tenth time.
- Subagents: split work into its own context, fan out in parallel, return only the conclusion. Perfect for broad search/review — the main context stays clean.
- Hooks: intercept on events (
PreToolUse,PostToolUse,Stop, …). This is where policy lives: blockrm -rf, run a formatter after every edit, write an audit log. - Permission system: allow/deny tools, ask-and-approve modes, sandbox. Essential once an agent can run bash on real infrastructure.
- MCP: plug in external tools (Linear, GitHub, an internal DB) without touching the runtime.
- Context management: auto-compaction on long conversations — a problem that’s very easy to get wrong by hand.
flowchart TB
P[prompt + ClaudeAgentOptions] --> L{{agent loop}}
L --> M[Claude picks the next step]
M -->|tool call| G[/permission + PreToolUse hook/]
G -->|allowed| T[Read · Grep · Bash · WebFetch]
G -->|denied| M
T --> PH[PostToolUse hook]
PH --> L
M -->|delegate| SUB[subagent · own context]
SUB --> L
M -->|MCP| X[(Linear · GitHub · DB)]
X --> L
M -->|done| R[ResultMessage]
The SDK ships in TypeScript and Python, and runs on the same engine as Claude Code, so the agent
behaves exactly like the thing you already know from the terminal. For multi-turn, interactive sessions
there’s also ClaudeSDKClient (connect once, send many prompts, interrupt() mid-run); query() is the
one-shot form.
2. Head to head
| Criterion | LangGraph | Claude Agent SDK |
|---|---|---|
| Core abstraction | Graph + State | Agent loop + Tools |
| Model | Any (OpenAI, Claude, local…) | Claude |
| Flow control | Total, explicit | Mostly model-decided |
| Durable / resume | Checkpointer (strong, first-class) | Session resume, lighter |
| Human-in-the-loop | interrupt primitive | Permission prompt / hook |
| Built-in coding tools | No (write your own) | Yes (file, bash, search) |
| Multi-agent | Build your own supervisor/swarm | Subagents built in |
| Policy / guardrails | Bake into nodes | Hooks + permissions |
| Learning curve | Steeper | Gentler |
| Vendor lock-in | Low | High |
3. Which one do you pick?
Pick LangGraph when:
- The business flow has many mandatory steps you must audit one by one.
- It must run for a long time, survive crashes, and resume precisely.
- You need to swap models, or use several models inside one flow.
- Human approval mid-flow is a valid state, not an exception.
Pick the Claude Agent SDK when:
- The agent has to operate on a real machine: edit code, run commands, read logs, open a PR.
- The task is open-ended and can’t be pinned to a fixed graph (“figure out why the build broke”).
- You need guardrails on capability more than guardrails on flow.
- You want a prototype by the end of the afternoon.
4. Use both — the model that actually holds up
For any serious system, this is the split I keep coming back to:
flowchart TB
START((START)) --> triage[triage_incident]
triage --> fix[propose_fix]
fix --> appr{human_approval
interrupt}
appr -->|approved| deploy[deploy]
appr -->|rejected| fix
deploy --> E((END))
triage -. runs .-> A1[Claude Agent SDK
read logs · run commands]
fix -. runs .-> A2[Claude Agent SDK
edit code · run tests]
deploy -. plain code, no LLM .-> C[shell / API call]
subgraph LG[LangGraph — skeleton: state · retry · HITL · checkpoint]
START
triage
fix
appr
deploy
E
end
LangGraph is the skeleton: it knows which step you’re on, how to retry, and who approves. The Agent SDK is the muscle: it does the open, messy work that needs real tools. Clean boundary — the graph holds state, the agent holds action.
5. Common traps
- Using LangGraph for work the model can already do. Drawing 12 nodes for something an agent loop solves in 3 turns is self-inflicted maintenance cost.
- Using the Agent SDK for a flow that must be deterministic. Payments, DB migrations, writing to a ledger — don’t let the model decide the order.
- Forgetting the checkpointer. LangGraph without one throws away its single biggest advantage.
- Giving an agent bash with no hooks or permissions. On real infrastructure, that’s a when, not an if.
- Stuffing everything into the main context. If you have subagents, fan out; keep the root context lean.
6. Closing
LangGraph and the Claude Agent SDK don’t compete head-on — they live at different layers. The right question isn’t “which one,” it’s:
Which part of the system needs a known flow, and which part needs the ability to improvise?
Answer that, and the architecture draws itself.
References: LangGraph · Claude Agent SDK
Want something like this built for your team?
Get a quote →