别把 LangGraph 当成更长的 Chain:先把状态、打断和恢复路径写清楚
# 别把 LangGraph 当成更长的 Chain:先把状态、打断和恢复路径写清楚
很多人第一次看 LangGraph,会把它理解成“更复杂一点的 LangChain”。这个理解容易把重点带偏。
LangGraph 更适合的场景不是“我想把几个 prompt 串起来”,而是:你的 agent 已经开始有状态、有分支、有工具调用、有失败恢复、有人工确认,并且这些行为需要被检查、复盘和迁移。
我今天重新读了一遍 Doramagic 对 LangGraph 的项目说明书。它给我的核心提醒是:LangGraph 的第一价值不是让 agent 看起来更聪明,而是把 agent 的运行过程变成一个可以被声明、检查、暂停和恢复的图。
Doramagic 项目说明书:
https://doramagic.ai/en/projects/langgraph/manual/
这是一份独立整理的项目说明,不代表 LangGraph 官方。它比较适合作为第一次判断和准备接入 AI 宿主前的检查清单。
这里的重点不是再做一个提示词库,而是把一个开源项目拆成可带走的能力资产:manual、boundary、pitfall、smoke check、acceptance criteria 和面向 AI 宿主的上下文。读它的目标不是“被种草”,而是形成一个能执行的验证流程。
## 1. 真正的边界在 State,不在 prompt
如果只是一次性问答,prompt 本身就是主要边界。
但一旦进入 LangGraph 的使用场景,真正应该先写清楚的是 State:
- 哪些字段会在节点之间流动;
- 哪些字段允许被节点更新;
- 多个分支同时写入时如何合并;
- 哪些内容会进入 checkpoint;
- 哪些内容不应该被长期保存。
说明书里反复出现的一个点是 reducer。比如消息列表通常不是简单覆盖,而是通过 `add_messages` 或类似 reducer 做合并。这个细节看起来很工程化,但它决定了并行分支之后你的上下文会不会丢。
所以第一次试 LangGraph,我不建议从“做一个万能 agent”开始。更稳的方式是先定义一个很小的 State schema,然后只让一个节点返回一个明确的 partial update。先确认状态写入和合并规则,再继续加工具和分支。
## 2. `compile()` 是从描述到运行的边界
LangGraph 的图在 compile 之前,更像是一个结构描述:节点、边、条件路由、状态字段、reducer。
compile 之后,才进入真正可运行的 Pregel 风格 runtime:节点按 superstep 执行,节点返回的 partial state 通过 channel 和 reducer 写回,条件边决定下一步去哪里。
这意味着调试 LangGraph 时,不要只看某一个节点函数。你需要同时看四件事:
- State schema 是否允许这个节点写入;
- 节点返回的 key 是否真的属于 State;
- reducer 是否符合你想要的合并语义;
- 条件边是否存在退出路径。
说明书列出的 `InvalidUpdateError: Must write to at least one of [...]` 就是典型例子。表面上是一个运行时报错,本质上往往是节点返回值和 State schema 没对齐。
## 3. Human-in-the-loop 不是 UI 装饰,而是执行合同
LangGraph 的一个重要能力是 interrupt / human-in-the-loop。很多介绍会把它讲成“可以人工审批一下”,但更关键的是:它应该成为工具调用前的执行合同。
如果 agent 要发邮件、改文件、调用外部 API 或触碰生产系统,人工确认点要明确写在流程里,而不是靠操作者临时盯着屏幕。
一个更实用的设计方式是:
- LLM 先提出 tool call;
- 图中节点触发 interrupt;
- 人类只审批一个具体动作,而不是审批一段模糊意图;
- 审批结果以结构化 HumanResponse 回到图里;
- 图从 interrupt 点恢复,而不是重新开始一整轮。
这也是为什么 LangGraph 更适合“可恢复的工作流 agent”,而不仅是聊天机器人。
## 4. checkpoint 不是日志,是恢复机制
Checkpointing 很容易被误解成“保存一下历史”。但在 LangGraph 里,它更接近运行恢复机制。
说明书里把 checkpointing、serialization、store 分开讲,这个区分很重要:
- checkpointer 是 thread-scoped,用来支持 durable execution、replay、resume;
- store 更像 cross-thread long-term memory;
- serialization 决定 Python 对象如何变成可存储、可恢复的数据。
这里有一个需要认真看的安全点:说明书引用了 checkpoint serializer 的安全建议。默认 serializer 可能处理 checkpoint 中的任意 Python 类型。新的应用应该考虑设置 `LANGGRAPH_STRICT_MSGPACK=true`,或者显式给 `JsonPlusSerializer` 配置允许的模块列表。
这不是“高级用户才需要关心”的细节。只要 checkpoint 数据可能来自不完全可信的环境,反序列化边界就应该提前定义。
## 5. 第一轮试用建议:只跑一个可失败、可恢复的小图
我会把 LangGraph 的第一次试用压缩成一个非常小的验收路径:
1. 新建临时目录,不接入真实生产数据。
2. 定义一个最小 State,只包含 `messages` 和一个业务字段。
3. 写一个节点,只返回 State 里允许的字段。
4. 给消息字段配置 reducer,避免并行或追加场景下被覆盖。
5. 加一个 interrupt,让人工确认一个具体动作。
6. 加一个 checkpointer,然后故意让某个节点失败一次。
7. 验证恢复后哪些状态被保留,哪些节点被重新执行。
如果这七步跑不顺,先不要接入真实工具。因为问题不在“agent 不够强”,而在运行边界还没有被验证。
这个 smoke check 的通过标准应该写成 pass/fail,而不是“感觉能跑”。比如:节点只写入声明过的 State 字段;interrupt 前不会执行真实副作用;checkpoint 恢复后不会重复已经成功的 sibling write;serializer 的安全边界已经明确。任何一项说不清楚,都应该 HOLD,而不是继续扩大接入范围。
## 6. 我的判断
LangGraph 值得看的地方,不是它能不能快速做一个 demo,而是它是否能把 agent 工作流里最难管的东西显性化:
- 状态;
- 分支;
- 工具调用;
- 人工审批;
- checkpoint;
- 失败恢复;
- 长期记忆和线程内状态的区别。
如果你的需求只是一次性模型调用,LangGraph 可能偏重。
如果你的需求是让 AI 宿主执行多步骤任务,并且你希望每一步都能被检查、暂停、恢复和复盘,那么 LangGraph 的价值就会变得很清楚。
我的建议是:不要先问“LangGraph 能不能做 agent”。先问“我的 agent 状态、工具边界和恢复路径能不能被写成图”。这个问题答清楚以后,再决定是否引入它。
- 点赞
- 收藏
- 关注作者
评论(0)