Claude Agent SDK 和 LangGraph 都用过之后,我发现选型先问一个问题
两个框架都在真实项目里用过——一个开放式的内容生产流水线试过 Agent SDK,一个流程固定的审批类业务用图编排的思路落过地。这篇不搬营销话术,只回答一个问题:你的任务,该把控制权交给模型,还是留给代码? 急着选的可以直接跳到文末对比表。
一句话说清两条路线
- Claude Agent SDK(Anthropic 官方)——"给模型一台电脑":把 Claude Code 那套被验证过的智能体挽具(harness)打包给你,模型自己决定怎么干活;
- LangGraph(LangChain 公司)——"你来画控制流图":提供底层编排运行时,你用节点和边显式定义每一步怎么走。
哲学分歧:Agent SDK 相信模型,把控制权交给模型;LangGraph 相信工程师,把控制权留给代码。 没有对错,只有场景。
Claude Agent SDK:Claude Code 的可编程形态
先记住一个关键事实:Agent SDK 不是从零造的新框架,它就是 Claude Code 本体。Anthropic 在官方博客里说得直白:Claude Code 在内部早已不止是编码工具——深度研究、视频制作、记笔记都在用它,"驱动 Claude Code 的智能体挽具同样可以驱动许多其他类型的智能体",于是 Claude Code SDK 更名为 Claude Agent SDK。
你在终端里用到的全部能力——文件读写、bash、搜索、子智能体、权限控制——都能通过 Python/TypeScript 调用。
官方方法论是一个循环:收集上下文 → 采取行动 → 验证工作 → 重复。细节官方博客写得很全(见文末链接),这里只留三个最反直觉的点:
- 官方劝你先别上语义搜索。原文:"语义搜索通常比智能体式搜索快,但更不准确、更难维护、更不透明。建议从智能体式搜索开始。"——和"上来先建向量库"的 RAG 惯性正好相反,让模型自己 grep 往往够用;
- 文件系统本身就是上下文工程。"一个智能体的文件夹和文件结构本身就是一种上下文工程"——目录起什么名、放什么文件,就是在给模型设计记忆;
- 验证工作里,规则校验被官方称为最佳反馈形式(lint 式的明确规则),LLM 当裁判则"通常不够鲁棒、延迟代价重"——作为运行时验证手段要慎用(离线评估是另一回事)。
代码长什么样
一次性任务用 query():
from claude_agent_sdk import query, ClaudeAgentOptions
options = ClaudeAgentOptions(
system_prompt="You are a helpful assistant",
allowed_tools=["Read", "Write", "Bash"], # 权限白名单:这些工具免确认
permission_mode="acceptEdits",
cwd="/path/to/project",
)
async for message in query(prompt="Create a hello.py file", options=options):
print(message)
第一个坑(官方 README 特意强调,我也真的踩过):allowed_tools 是权限白名单,不是工具开关——默认模型拥有全套工具,列在里面的免审批,没列的走 permission_mode 决策;要禁用工具得用 disallowed_tools。
第二个坑:query() 是一次性会话;多轮交互、自定义工具、hooks 都必须走 ClaudeSDKClient。比如用 PreToolUse hook 拦截危险命令,光定义函数不生效,必须注册:
from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient, HookMatcher
async def check_bash_command(input_data, tool_use_id, context):
if "rm -rf" in input_data["tool_input"].get("command", ""):
return {"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "危险命令,已拦截",
}}
return {}
options = ClaudeAgentOptions(
hooks={"PreToolUse": [HookMatcher(matcher="Bash", hooks=[check_bash_command])]},
)
自定义工具同理,一个装饰器函数注册进 create_sdk_mcp_server,底层是进程内 MCP server(无子进程、无 IPC 开销)。
LangGraph:把流程画成状态图
LangGraph 的自我定位(官方原话):"非常底层,完全聚焦于编排",核心优势是在同一张图里混合确定性的手写步骤和 LLM 驱动的智能体步骤。
三个概念就够入门——State(共享状态)、Node(函数:接收状态→干活→返回更新)、Edge(固定边或条件边):
from langgraph.graph import StateGraph, MessagesState, START, END
def call_llm(state: MessagesState):
return {"messages": [llm.invoke(state["messages"])]}
def should_continue(state: MessagesState):
return "tools" if state["messages"][-1].tool_calls else END
graph = StateGraph(MessagesState)
graph.add_node("agent", call_llm)
graph.add_node("tools", tool_node)
graph.add_edge(START, "agent")
graph.add_conditional_edges("agent", should_continue)
graph.add_edge("tools", "agent")
app = graph.compile(checkpointer=checkpointer)
这就是一个 ReAct agent:agent → 有 tool_calls?→ tools → 回到 agent。这个循环在 Agent SDK 里是内置黑盒,在 LangGraph 里是你亲手画的——这是两者最本质的区别。
LangGraph 真正的硬差异化是两个:
- 应用状态按步快照:checkpointer 把每个 super-step 的状态存进内存/SQLite/Postgres,支持 time-travel 和分支。注意语义边界:崩溃恢复是从最近的节点边界整体重跑该节点,不是字面的"原地续跑"——节点内的副作用(发消息、写库)会重复执行,官方要求节点幂等或用
@task包裹副作用。把它当卖点用之前先想清楚幂等性,否则就是生产事故; - Human-in-the-loop:interrupt 机制在任意节点暂停,状态已持久化,"等人"可以等几天,人审批后从断点继续。
什么时候它更香?当你的业务流程本身就是一张图。比如电商售后的退款审批流:规则引擎初判 → 小额自动通过 → 大额进人工审批队列(interrupt 等审批)→ 通过打款 / 驳回关单,中间夹一个 LLM 节点生成给客服的争议摘要。流程是业务规则定死的、要可审计、人工环节可能等几天——这种场景用 Agent SDK 反而别扭,你根本不想让模型自由发挥流程走向。
正面对比
| 维度 | Claude Agent SDK | LangGraph |
|---|---|---|
| 哲学 | 模型驱动:给模型一台电脑 | 代码驱动:工程师画图 |
| 抽象层级 | 高——loop/工具/权限/压缩全内置 | 低——只给图原语,循环自己搭 |
| 运行时形态 | 驱动 Claude Code CLI 子进程(容器需带 Node,冷启动/多租户按进程算) | 纯库,可选托管平台 |
| 模型支持 | 官方仅 Claude(可经 Bedrock/Vertex 部署;协议层可接兼容端点,但 harness 是对 Claude 对齐的,换模型效果无保证) | 任意模型 |
| 内置工具 | Claude Code 全套 | 无,自己定义或用 LangChain 集成 |
| 持久化 | 对话轨迹落盘 + resume/fork 会话;应用级状态自管 | 任意应用状态按步快照,time-travel/分支 |
| 人工介入 | permission_mode + hooks 审批 | interrupt,可暂停数天 |
| 权限与安全 | 内置权限系统 | 自己实现 |
| 语言 | Python、TS(无官方 Java) | Python、JS(Java 有社区版 langgraph4j) |
| 上手速度 | 快(几行代码得到完整智能体) | 慢(先设计图),但可控性强 |
选型:先问约束,再问一个问题
先排除法:如果因合规/成本/多云要求必须用非 Claude 模型,或部署环境放不下 CLI 子进程(serverless/边缘),Agent SDK 直接出局,不用往下看。
约束过了之后,问这一个问题: "这个任务的正确流程,是事先能画出来的,还是要模型现场探索的?"
- 画不出来(开放式任务)→ Agent SDK。代码修复、深度研究、"帮我把这堆日志查明白"——步骤取决于中间发现,硬编码流程图只会限制模型;
- 画得出来(确定性业务流)→ LangGraph。审批流、多步 ETL、工单路由——流程是业务规则定死的,你要的是可审计、可等待、可恢复;
- 混合形态:LangGraph 画外层业务流程,某个节点内部调 Agent SDK 跑开放式子任务。两者不互斥。
这是启发式不是铁律,两侧都有反例:LangChain 自家的 Open Deep Research 就是用 LangGraph 写的开放式研究智能体(选它的真实理由是要换模型、要自定义 loop);反过来固定流水线也有人跑 Agent SDK,用 hooks + disallowed_tools 把流程钉死,图的是单步内部的 harness 质量。知道边界在哪,这个问题才好用。
成本这件事,别信简单二分。"LangGraph 节点写死所以成本可控"只对无环的 DAG 成立——条件边一旦成环(ReAct 就是环),调用次数同样由模型决定,兜底是 recursion_limit(超限抛异常,那是封顶不是可控)。Agent SDK 这边也有 max_turns、hooks、给子智能体配小模型这些预算手段,加上 harness 重度使用 prompt caching(缓存读约为标准输入价的十分之一),实际账单往往比直觉低。真实差异是:LangGraph 让你更容易把"必须封顶的环"和"固定的步"隔离开。上线前用真实任务跑一轮账单,别拍脑袋。
常见问题
LangChain 名声不好,LangGraph 会不会一样? LangGraph 是对早期批评的回应产物——刻意做得底层,不抽象 prompt,可以完全脱离 LangChain 使用。社区口碑明显好于本体。但观测和部署想省事就得进 LangSmith 平台,生态变现的倾向是存在的。
为什么不直接用 Claude API 的 tool use 自己写循环? 可以,简单场景官方也推荐这个起点(Java 团队目前也只有这条路:官方 Java SDK 有 Messages API + tool runner(beta),可以手搓 loop,但没有 harness 层)。Agent SDK 额外给的是 Claude Code 沉淀一年多的 harness:文件系统工具集、权限系统、自动压缩、子智能体、hooks。自己写至少几周,且很难调到同等质量。反过来,只需要两三个工具的固定流水线,裸 API 更轻。
OpenAI 那边对应什么? OpenAI Agents SDK(前身 Swarm)加上 AgentKit 介于两者之间:有 handoff/guardrails 原语和可视化编排(Agent Builder),durable execution 走 Temporal 集成,经 LiteLLM 也是模型中立的;差距主要在没有"给模型一台电脑"级别的完整 harness。我对它只有定位级了解,没深度用过,仅供参考。
延伸阅读
- Building agents with the Claude Agent SDK — Anthropic Engineering
- Claude Agent SDK Python / TypeScript
- Writing effective tools for agents — Anthropic
- LangGraph Overview / Persistence / Interrupts
"流程画得出来就别交给模型"这个判断,正是我做 AI 讲题视频流水线时的教训——整条流水线是确定性编排,只把"写分镜"这一个环节交给 LLM,产出还要过校验器。渲染部分开源在 storyboard2video,欢迎交流。