注:以下所提的“文档”,是指LangGraph官方指南(https://langchain-ai.github.io/langgraph/guides/),参考版本是0.6.8。

以下代码的开发环境

[project]
name = "my-langgraph"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
    "dotenv>=0.9.9",
    "langchain>=0.3.27",
    "langchain-openai>=0.3.33",
    "langfuse>=3.5.0",
    "langgraph>=0.6.7",
    "langgraph-checkpoint-sqlite>=2.0.11",
    "numpy>=2.3.3",
]

一、update_state 的作用

update_state 是 LangGraph 提供的一个机制,用于 在图的执行过程中插入 / 修改状态(state),从而实现类似 “时光旅行”(time travel)或中断点恢复(checkpoint resume)之类的功能。

具体来说:

  • 当一个执行线程(thread)在某个 checkpoint(检查点)处暂停时,你可以用 update_state 修改该 checkpoint 处的状态值(values),然后从这个修改后的状态继续执行(即 “重新分支”)。
  • update_state 会创建一个新的 checkpoint(具有新的 checkpoint_id),但仍然属于同一个 thread。
  • 它可以用于“插入人类反馈”“工具返回值注入”或“局部测试子图”等场景。

在中断或暂停的情形下,如果你希望在恢复之前先修改状态(例如人工干预、补充信息等),这就是 update_state 的主要用途。

二、方法签名 / 用法(Python 端)

在文档里(如 “Use the graph API”),update_state 是 CompiledStateGraph 的方法之一。它通常的参数包括:

  • config(或称 config/thread configuration):指定当前执行线程/上下文,用于告诉图你要在哪个线程/哪条执行线上做更新。
  • values:一个字典,用来指定你要更新 / 覆盖 /注入(inject)的状态字段与其对应的新值。
  • as_node(可选参数):告诉 update_state 你希望状态被视作从哪个节点(node)发出的。也就是说,后续执行会从 as_node 的后继节点开始。这个参数用于模拟“状态是在某个节点刚执行完毕后”的情形。文档里在测试(partial execution)里就有用例用了 as_node。
  • 除此之外,还可能还有 checkpoint_id(或类似参数)用于指定你要修改的是哪个 checkpoint(如果一个 thread 有多个历史 checkpoint)。在服务端 REST / SDK 接口中也有这一参数。

例如,文档里给了一个例子:

new_config = graph.update_state(
    config=selected_state.config,
    values={"topic": "chickens"}
)

这里是直接在某个已选中的 checkpoint 修改其中 topic 字段的值。

另外,在测试场景中,有这样一个用法:

compiled_graph.update_state(
    config={"configurable": {"thread_id": "1"}},
    values={"my_key": "initial_value"},
    as_node="node1",
)
result = compiled_graph.invoke(
    None,
    config={"configurable": {"thread_id": "1"}},
    interrupt_after="node3",
)

这里就模拟从节点 node1 执行完之后的状态继续执行。

三、内部语义 & 合并策略(Reducer)

在 LangGraph 中,每一个状态字段(state key)可以有自己的 reducer 函数,用于决定当多个节点对同一个字段进行更新时,如何合并这些更新。

因此,update_state 注入或覆盖状态的行为,会受到这些 reducer 的影响:

  • 如果某个字段被定义了合并逻辑(非简单覆盖),那么 update_state 插入的新值可能与历史值通过 reducer 逻辑合并。
  • 如果没有自定义 reducer,默认是覆盖(overwrite)行为(即新值替换旧值)。在 GitHub issue 里有人提到 “update graph state by default 是覆盖行为”

所以你在使用 update_state 时,要留意该字段是否有特殊 reducer(如 append、累加、合并等)影响。

四、常见场景与典型用途

下面列举一些 update_state 的典型用途:

  1. 中断点人工干预
    在图运行过程中,设置某些节点为中断点(interrupt_before / interrupt_after)。当执行暂停时,你可以读取当前状态、让人工输入 / 编辑 / 注入信息,然后用 update_state 把新的状态写回去,再继续执行。
  2. 时光旅行 / 替代路径探索
    你在某个 checkpoint 回到过去状态,修改该状态然后分支执行不同路径,以做模拟、比较或调试。
  3. 子图 / 片段测试
    在测试中,你可能只想执行图的一部分。那就可以用 update_state(as_node=…) 模拟从中间某节点开始。
  4. 工具 / 外部系统注入状态
    在新版 LangGraph 中,工具(Tool)也能直接更新图状态(即工具调用可以触发 update_state 背后的机制)。

五、注意事项 & 限制 / 常见坑

在实际使用 update_state 时,有几个地方需要特别留意:

  1. 中断状态下 get_state().next 可能为空
    在某些情况下,如果你在两个节点之间用 update_state,可能出现 graph.get_state(thread).next 为空的问题。有人在 issue 中反馈说在 “interrupted state” 下,有时调用 update_state 后 next 为空。
  2. as_node 参数的正确使用
    如果你没有指定 as_node,系统默认可能把你插入的状态视为更靠后的节点(或起始节点)。若你希望控制从哪个节点开始继续执行(即从那个节点的后继节点继续),就要用 as_node 指定得当。
  3. Reducer 冲突 / 合并逻辑
    若某个字段有合并 logic,而你的 update_state 提供的值与已有历史冲突,你可能得到意料之外的合并结果。必须理解该字段的 reducer 行为。
  4. Checkpoint 指定
    如果一个 thread 有多个 checkpoint 历史,而你要更新的不是当前最新的 checkpoint,就要明确指定 checkpoint_id(视 API 支持情况而定)。否则修改可能作用在不正确的 checkpoint。服务端 SDK 接口中就有此类参数。
  5. 版本 / 文档变动
    LangGraph 的文档里提到,某些用法可能在未来版本(如 v1.0)会改变。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐