Agent 状态机——图、节点、检查点


文档摘要

Agent 状态机——图、节点、检查点 本节摘要:手写的 ReAct 循环是一个 。同样的循环写成显式图,你就能对它做检查点(checkpoint)、中断(interrupt)、分支(branch)和时间旅行(time-travel)。Agent 本身没变,变的是它外面的 harness。本节讲透 LangGraph 的三要素(状态/节点/边)、编译与检查点、它赋予 harness 的四大超能力(检查点/中断/流式/时间旅行),以及 reducer 为何是全库唯一微妙之处。读完本节,你能把一个 ReAct agent 画成四节点的 StateGraph,并获得生产级的状态持久化与人在环。 对应原课程:Phase 11 · Lesson 16 · (原英文 )。

Agent 状态机——图、节点、检查点

本节摘要:手写的 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)。

学习目标

阅读完本节,你应当能够:

  1. 说清手写 while True显式状态图的差别(后者可检查点/中断/分支/回溯)。
  2. 列举 LangGraph 的三要素(状态/节点/边)。
  3. 复述它赋予 harness 的四大超能力(检查点/中断/流式/时间旅行)。
  4. 理解 reducer 为何是关键(消息列表要用 operator.add 累积)。
  5. 四节点画出一个生产级 ReAct agent。

一、问题与直觉

你上线一个函数调用 agent。它跑三轮好好的,然后出问题:模型试了个返回 500 的工具、用户中途改主意、或 agent 没等人签字就退款了。while True: 循环没有钩子——你没法暂停、没法倒带、没法分支「要是模型选了另一个工具会怎样」。一旦过了 demo 阶段,agent 就成了一个「要么成了要么没成」的黑箱。

下一步一旦看清就显而易见:agent 本就是一个状态机——系统提示 + 消息历史 + 待处理工具调用 + 下一个动作。把这个状态机显式化:节点是「模型思考」「工具运行」「人审批」,边是它们之间的条件转移。一旦图显式了,harness 免费获得四样东西:检查点(步间存状态)、中断(为人暂停)、流式(流 token 与中间事件)、时间旅行(回到先前状态试别的分支)。

LangGraph 是这个抽象的参考实现——一个一等状态、一等持久化、一等中断的图运行时。Agent 循环是你出来的,不是手写的。

二、从零实现

StateGraph 三要素

  1. 状态(State):一个 TypedDict 或 Pydantic 模型,流过整图。每个节点收到完整状态,返回部分更新,LangGraph 用每字段的 reducer 合并——列表用 operator.add 累积,默认覆盖。
  2. 节点(Nodes):Python 函数 state -> partial_state,每个是离散步骤(「调模型」「跑工具」「总结」)。
  3. 边(Edges):节点间转移。静态边去一处;条件边带路由函数 state -> next_node_name,让图能按模型输出分支。

编译图(compile):绑定拓扑、挂上 checkpointer(生产必备)、返回一个 runnable。用初始状态和 thread_id 调用它,每步执行都按 (thread_id, checkpoint_id) 持久化一个检查点。

四大超能力

  • 检查点:每次节点转移把新状态写入存储(测试用内存,生产用 Postgres/Redis/SQLite)。用同一 thread_id 再调图,从暂停处继续。
  • 中断:给节点标 interrupt_before=["human_review"],执行在该节点前停止、状态持久化。你的 API 回「待审批」;后续对同一 thread_idCommand(resume=...) 恢复。
  • 流式:graph.stream(state, mode="updates") 产出状态增量;mode="messages" 流模型节点里的 LLM token;mode="values" 产出完整快照。
  • 时间旅行:graph.get_state_history(thread_id) 返回完整检查点日志。传任意先前 checkpoint_idgraph.invoke 即从该点分叉——调试「要是模型选了工具 B 会怎样」与回放生产轨迹做回归测试都靠它。

reducer 是关键

每个状态字段都有一个 reducer。多数默认即可(新值覆盖旧值),但消息列表需要 operator.add,让新消息追加而非替换。并行边通过 reducer 合并更新——若两个节点都更新 messages 而你忘了 Annotated[list, add_messages],第二个会静默覆盖,丢掉半轮。reducer 是全库唯一微妙处;搞对它,其余自然组合。

四节点 ReAct 图

生产级 ReAct agent 是四节点两边的图:

  1. agent——用当前消息历史调 LLM,返回助手消息(可能含 tool_calls)。
  2. tools——执行上一条助手消息里的 tool_calls,把结果作为 tool 消息追加。
  3. 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 合并、时间旅行做回归测试。

五、练习

  1. 四节点 ReAct:用 LangGraph 实现上述 agent/tools/END 图,挂内存 checkpointer,跑一个带 2 次工具调用的任务。
  2. 人在环:加一个 human_review 节点并 interrupt_before,在审批前暂停,用 Command(resume=...) 恢复,验证状态持久。
  3. reducer 陷阱:故意不给 messagesadd_messages reducer,观察并行更新时消息丢失;加上后验证修复。
  4. 时间旅行:跑一个任务后用 get_state_history 取回中间检查点,从该点改一个工具结果重新 invoke,对比两条分支结果。

本节要点回顾

  1. 显式化的价值:把 while True 变成显式图,免费获得检查点/中断/流式/时间旅行。
  2. 三要素:状态(类型化字典流过全图)、节点(state->partial_state 函数)、边(静态或条件路由)。
  3. 编译+检查点:compile 绑拓扑+挂 checkpointer,按 (thread_id, checkpoint_id) 持久化每步。
  4. 四大超能力:检查点(恢复)、中断(人在环 interrupt_before)、流式(三 mode)、时间旅行(get_state_history 回溯分叉)。
  5. reducer 是关键:消息列表必须用 operator.add/add_messages 累积,否则并行更新静默丢消息。
  6. 四节点 ReAct:agent(调 LLM)→ 条件边 → tools(执行)→ 回 agent,无工具调用则 END,是生产标配。

下一节,我们看** Agent 框架取舍**——LangGraph、CrewAI、AutoGen、Agno 各自的核心抽象与适用场景。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U