Agent 状态机——图、节点、检查点 本节摘要:手写的 ReAct 循环是一个 。同样的循环写成显式图,你就能对它做检查点(checkpoint)、中断(interrupt)、分支(branch)和时间旅行(time-travel)。Agent 本身没变,变的是它外面的 harness。本节讲透 LangGraph 的三要素(状态/节点/边)、编译与检查点、它赋予 harness 的四大超能力(检查点/中断/流式/时间旅行),以及 reducer 为何是全库唯一微妙之处。读完本节,你能把一个 ReAct agent 画成四节点的 StateGraph,并获得生产级的状态持久化与人在环。 对应原课程:Phase 11 · Lesson 16 · (原英文 )。
本节摘要:手写的 ReAct 循环是一个
while True。同样的循环写成显式图,你就能对它做检查点(checkpoint)、中断(interrupt)、分支(branch)和时间旅行(time-travel)。Agent 本身没变,变的是它外面的 harness。本节讲透 LangGraph 的三要素(状态/节点/边)、编译与检查点、它赋予 harness 的四大超能力(检查点/中断/流式/时间旅行),以及 reducer 为何是全库唯一微妙之处。读完本节,你能把一个 ReAct agent 画成四节点的 StateGraph,并获得生产级的状态持久化与人在环。
对应原课程:Phase 11 · Lesson 16 ·
langgraph-state-machines(原英文phases/11-llm-engineering/16-langgraph-state-machines/docs/en.md)。
阅读完本节,你应当能够:
while True 与显式状态图的差别(后者可检查点/中断/分支/回溯)。operator.add 累积)。你上线一个函数调用 agent。它跑三轮好好的,然后出问题:模型试了个返回 500 的工具、用户中途改主意、或 agent 没等人签字就退款了。while True: 循环没有钩子——你没法暂停、没法倒带、没法分支「要是模型选了另一个工具会怎样」。一旦过了 demo 阶段,agent 就成了一个「要么成了要么没成」的黑箱。
下一步一旦看清就显而易见:agent 本就是一个状态机——系统提示 + 消息历史 + 待处理工具调用 + 下一个动作。把这个状态机显式化:节点是「模型思考」「工具运行」「人审批」,边是它们之间的条件转移。一旦图显式了,harness 免费获得四样东西:检查点(步间存状态)、中断(为人暂停)、流式(流 token 与中间事件)、时间旅行(回到先前状态试别的分支)。
LangGraph 是这个抽象的参考实现——一个一等状态、一等持久化、一等中断的图运行时。Agent 循环是你画出来的,不是手写的。
operator.add 累积,默认覆盖。state -> partial_state,每个是离散步骤(「调模型」「跑工具」「总结」)。state -> next_node_name,让图能按模型输出分支。编译图(compile):绑定拓扑、挂上 checkpointer(生产必备)、返回一个 runnable。用初始状态和 thread_id 调用它,每步执行都按 (thread_id, checkpoint_id) 持久化一个检查点。
thread_id 再调图,从暂停处继续。interrupt_before=["human_review"],执行在该节点前停止、状态持久化。你的 API 回「待审批」;后续对同一 thread_id 发 Command(resume=...) 恢复。graph.stream(state, mode="updates") 产出状态增量;mode="messages" 流模型节点里的 LLM token;mode="values" 产出完整快照。graph.get_state_history(thread_id) 返回完整检查点日志。传任意先前 checkpoint_id 给 graph.invoke 即从该点分叉——调试「要是模型选了工具 B 会怎样」与回放生产轨迹做回归测试都靠它。每个状态字段都有一个 reducer。多数默认即可(新值覆盖旧值),但消息列表需要 operator.add,让新消息追加而非替换。并行边通过 reducer 合并更新——若两个节点都更新 messages 而你忘了 Annotated[list, add_messages],第二个会静默覆盖,丢掉半轮。reducer 是全库唯一微妙处;搞对它,其余自然组合。
生产级 ReAct agent 是四节点两边的图:
agent——用当前消息历史调 LLM,返回助手消息(可能含 tool_calls)。tools——执行上一条助手消息里的 tool_calls,把结果作为 tool 消息追加。agent 出一条条件边:最后一条消息有 tool_calls 则去 tools,否则去 END。| 维度 | 手写 while True | LangGraph StateGraph |
|---|---|---|
| 检查点/恢复 | 自己 pickle | 一等,多后端 |
| 人在环中断 | 难 | interrupt_before 一行 |
| 流式 | 自己接 token | 三种 mode 内置 |
| 回溯/分支 | 不可能 | get_state_history |
| 调试可见性 | 黑箱 | 图 + 状态日志 |
本节产出 outputs/skill-langgraph-patterns.md——LangGraph 生产模式清单:四节点 ReAct、人在环审批、长任务检查点恢复、并行 fan-out 用 reducer 合并、时间旅行做回归测试。
human_review 节点并 interrupt_before,在审批前暂停,用 Command(resume=...) 恢复,验证状态持久。messages 加 add_messages reducer,观察并行更新时消息丢失;加上后验证修复。get_state_history 取回中间检查点,从该点改一个工具结果重新 invoke,对比两条分支结果。while True 变成显式图,免费获得检查点/中断/流式/时间旅行。state->partial_state 函数)、边(静态或条件路由)。(thread_id, checkpoint_id) 持久化每步。interrupt_before)、流式(三 mode)、时间旅行(get_state_history 回溯分叉)。operator.add/add_messages 累积,否则并行更新静默丢消息。下一节,我们看** Agent 框架取舍**——LangGraph、CrewAI、AutoGen、Agno 各自的核心抽象与适用场景。