为什么 Agent 框架要按需求选,而不是默认上 LangGraph
用决策树和取舍表讲清 LangGraph / Checkpoint / Map-Reduce / Multi-Agent 何时该上、何时别上。
立靶:选错框架、过早上框架,代价都不小
先抛一个常见场景。一个团队要做「文档自动审查」,第一周就把 LangGraph、向量库、多 Agent 编排全套搭上。结果两周后发现:真正卡住进度的不是编排,而是提示词还没调对、单步输出还不稳定。框架的复杂度提前付了费,业务价值却迟迟没兑现。
过早上框架的三笔隐性账:
- 抽象遮住了可观察性。框架替你把「调模型 - 解析 - 路由」打包成一个黑盒,结果哪一步慢了、哪一步输出坏了,你看不见。Agent 调试的第一性原理是「每步 I/O、延迟、token 必须可见」,框架装早了,这条就先丢了。
- 复杂度错配。一个本质上是「单步问答」的需求,套上节点图、状态机、Checkpoint,维护成本翻几倍,而它根本不需要条件流转。
- 锁定成本。框架的核心抽象一旦渗进业务代码,想换框架等于重写。
但反过来,选错「不上框架」同样有代价:一个真正有复杂条件分支、需要断点续跑、需要人工介入(HITL)的生产任务,硬用裸 SDK 手搓状态管理,最后会搓出一个更烂、更不可维护的「土制 LangGraph」。
所以这一讲的靶子不是「框架好不好」,而是:你的需求到底处在复杂度光谱的哪个位置,匹配的工具是什么。
框架:四类工具的能力与取舍
常见选项不是平行的四个品牌,而是覆盖「复杂度光谱」不同段位的工具。
| 框架 | 核心抽象 | 适用场景 | 取舍 |
|---|---|---|---|
| 裸 SDK | 无(自己调模型) | 简单单步 Agent | 最透明、最可控;但复杂流转要全手搓 |
| LangChain | Chain / Agent / Memory | 快速原型 | 上手快、组件多;抽象偏厚,生产可观察性需额外补 |
| LangGraph | 节点图(Node + Edge + State) | 生产级复杂单任务 Agent | 显式状态机、可做 Checkpoint;学习成本高,简单任务杀鸡用牛刀 |
| AutoGen | 多 Agent 对话 | Agent 需要互相讨论 | 适合协作推理;通信开销大、结果不易控 |
判定核心抽象的本质区别:裸 SDK 没有状态机,LangGraph 把状态机显式化,AutoGen 把「多个 Agent 之间的对话」作为一等公民。 选型就是判断你的需求需要哪一层显式化。
围绕 LangGraph 这层,还有三个必须理解的「能力」(它们决定生产可用性,不是另立的框架):
| 能力 | 解决什么问题 | 何时需要 |
|---|---|---|
| State / Node / Edge 三要素 | 把复杂流程显式建模为共享字典 + 函数节点 + 固定/条件边 | 单任务内部有条件分支时 |
| Checkpoint(状态持久化) | 中途失败不从头跑、支持 HITL、审计追踪、断点续跑 | 任务长、要人工介入、要可追溯时 |
| Map-Reduce | 大任务拆成 N 个子任务并行,再汇总 | 子任务之间无依赖、想压缩耗时时 |
Checkpoint 的三种存储后端按部署规模递进,别一上来就上最重的:MemorySaver(仅开发调试)→ SqliteSaver(单机生产)→ PostgresSaver(分布式)。
case:一个合同审查任务的演化路径
需求:审查商业合同,识别风险条款,高风险的交人工复核。
第一版(单份合同) 的正确形状是一张 LangGraph 节点图,因为它内部确实有条件分支:
[输入] → [解析] → Checkpoint
→ [Map: 并行审查 ×4(付款 / 违约 / 保密 / 争议)] → 各自 Checkpoint
→ [Reduce: 汇总去重] → Checkpoint
→ 条件边:高风险?
是 → [HITL Node] ← Checkpoint 持久等待
否 → [报告生成] → [输出]
每个能力都对应一个真实诉求:四个审查维度之间没有数据依赖,所以走 Map-Reduce 并行,耗时从 4 倍降到约 1 倍;任务链路长,所以每步落 Checkpoint,失败不必从头跑;高风险要人工,所以用 条件边 + HITL Node,靠 Checkpoint 把状态持久挂起、等人回来再续。
第二版(1000 份独立合同) 是一个高频踩坑点。直觉会想「那就用 LangGraph 把批处理也编排进去」,但这是错的。1000 份合同之间彼此独立,不存在条件流转,真正的瓶颈是并发控制和失败重试,不是状态机。正确形状是分层:
外层:asyncio 控制并发(防 API 限速)+ 任务队列
内层:每份合同仍用 LangGraph 处理它自己的单任务流程
全局:支持断点续跑 + 单份失败独立重试
一句话提炼:「单任务内部的复杂度」用 LangGraph 解,「任务之间的批量与并发」用队列和异步解,两者不要混为一谈。
如果再升级成「多个 Agent 互相讨论裁定风险等级」,才轮到考虑 AutoGen 那类多 Agent 对话框架;而多 Agent 不是免费的,它等于在单 Agent 的全套能力之上再叠一层:
单 Agent = Tool Use + Context 管理 + HITL + 安全 + 幂等性 + 错误重试
Multi-Agent = 单 Agent × N + 状态持久化 + 三级错误处理 + 并行优化 + 通信协议 + Orchestrator
看清楚这个加号链,就不会轻易为了「听起来高级」而上多 Agent。
可操作做法:选型决策树 + 工程清单
第一步:跑一遍选型决策树。
Q1:单任务内部有没有复杂条件流转(分支 / 循环 / 人工介入)?
有 → LangGraph 没有 → 裸 SDK
Q2:多个任务之间有没有依赖?
有依赖 → 用 Orchestrator 协调
无依赖 → 并行批处理(asyncio + 队列),不要硬塞进 LangGraph
第二步:确认要不要这三个能力,需要才上,别预付。
- 任务链路长、中途可能失败 / 要审计 / 要断点续跑 → 上 Checkpoint(开发用 MemorySaver,单机用 Sqlite,分布式才上 Postgres)
- 有 N 个互相无依赖的子任务且想压耗时 → 上 Map-Reduce
- 需要人工卡点放行 → 上 HITL Node,并依赖 Checkpoint 持久挂起
第三步:如果决定要封装框架,守住三原则。
- 只封装稳定的部分(提示词经常变,不要封装进去)
- 封装不能遮住可观察性(每步 I/O / 延迟 / token 必须可见)
- 隔离层防抽象泄漏(自己的接口 → 适配器 → 框架,换框架时不动业务代码)
第四步:只要做到 Multi-Agent,这「四件套」是工程底线,缺一个就会在生产里翻车。
- 三级错误处理:自动重试(指数退避 2-3 次)→ 降级处理 → 上报人工
- 幂等性:写操作绑定唯一操作 ID,执行前检查是否已执行(单 Agent 同样需要)
- 状态持久化:每步结果入库(关联 pipeline_id),重启从断点续跑
- 并行优化:有数据依赖走顺序,无依赖才并行
收口
先问「我的复杂度在哪一层」,再决定「上不上框架、上哪一层能力」;单任务内部的复杂度交给 LangGraph,任务之间的批量交给队列,听起来高级的多 Agent 永远是最后才动用的那张牌。多一分是负债,少一分是手搓。