软件需要在生产环境中变更。新需求、错误修复和重构最终都会落地到你的图代码中。因为 LangGraph 使用最新部署的图来处理已为现有线程持久化的状态,所以你发布的每一个更改实际上都是相对于现有检查点的向后兼容 API 变更。 与将运行固定到启动时代码版本的工作流引擎不同,LangGraph 会立即将最新的图应用到所有线程,包括新线程和从检查点恢复的线程。这很方便:错误修复可以直接传播到正在进行的对话和智能体中。但这也意味着你必须考虑每个更改如何与在旧版本代码下启动的运行进行交互。 需要关注三类兼容性问题,大致按照你会遇到的顺序排列:Documentation Index
Fetch the complete documentation index at: https://nvd-54.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
- 技术兼容性:最常见;新代码必须仍然能够加载并针对现有状态执行。
- 业务兼容性:不太常见;即使代码已更改,现有运行也应继续遵循旧的业务逻辑。
- 非确定性:仅适用于 Functional API。
技术兼容性
技术兼容性相当于微服务中的 API 破坏性变更。这里的”API”是你的图代码与检查点器为现有线程持久化的数据之间的约定。当线程恢复时,LangGraph 反序列化保存的状态,按名称将其分发到节点,并期望节点返回符合状态模式的值。 常见的技术破坏:- 重命名或删除节点,而线程正暂停在该节点或即将进入该节点,例如在
interrupt处或通过仍路由到旧名称的检查点条件边。恢复时,LangGraph 找不到保存名称对应的节点,运行将失败。恢复运行的起点是执行停止的节点的开头,因此缺失的节点将没有恢复的地方。 - 重命名或删除状态键,而旧检查点仍然包含该键或下游节点仍在读取该键。
- 收紧状态字段,例如将
Optional字段变为必需、缩窄类型或添加没有默认值的新必需字段。现有检查点将不满足新模式。
推荐模式
-
将新状态字段添加为
NotRequired(或Optional[...] = None),以便旧检查点仍然有效: - 将删除视为弃用。至少在一个排空周期内保持字段在状态上的定义,即使没有节点读取它,以便现有检查点继续加载。
- 通过先添加后删除进行重命名。将新字段或节点与旧的并列添加,在弃用窗口期双写或路由到两者,然后在确认没有正在进行的线程依赖旧字段后再删除它。
-
保持节点函数对未知键的容忍性。
TypedDict在运行时会忽略多余的键,因此来自旧代码版本的残留状态不会引发错误,除非节点显式读取一个缺失的键。 -
使用时间旅行和
graph.get_state在暂存部署中抽查现有线程与新代码的兼容性,然后再正式发布。
检测正在进行的线程
在你删除节点、重命名状态键或进行其他旧线程无法容忍的更改之前,你需要知道是否有任何线程当前停留在你即将弃用的代码版本上。LangGraph 本身不维护线程状态的搜索索引,因此答案取决于你的图在哪里运行。 如果你部署到 LangSmith。 使用 Agent Server 的线程搜索按状态过滤。status 字段接受 idle、busy、interrupted 和 error,因此你可以批量查询 interrupted 或 busy 线程,可选地使用元数据过滤器缩小范围。参见按线程状态过滤和列出线程。
LangGraph 运行的任何地方。 使用 LangSmith 追踪监控生产环境中哪些节点正在被进入和退出。这是确认某个节点或状态字段在任何活跃代码路径中不再可达的最可靠信号。
当你已有 thread_id 时。 直接检查该单个线程:
graph.get_state(config)返回最新的检查点,包括线程暂停在哪个节点以及任何待处理的中断。graph.get_state_history(config)返回线程的完整时间顺序检查点列表。
业务兼容性
有时候更改在技术上是有效的(每个现有检查点仍然加载,每个节点仍然解析),但新图的含义与旧的不同。新行为对新线程是正确的,你不希望将其追溯应用到在旧逻辑下启动的线程。 例如,假设你的图运行intake → triage → respond,而你决定在 triage 和 respond 之间插入一个新的 policy_check 步骤:
- 已经通过
triage的线程应继续直接到respond(旧流程)。 - 新线程应运行完整的新流程。
triage 之后恢复的旧线程从其保存的状态中读取 flow_version(或回退到 v1 默认值)并跳过 policy_check。新线程从 intake 开始,被标记为 flow_version=2,并运行新路径。一旦所有 v1 线程完成,你就可以删除版本标记和条件边。
此模式仅在你在线程开始时设置版本才有效,即在任何需要版本控制的分支之前。稍后设置意味着现有线程在需要时不会设置该值。
非确定性
此类别仅适用于 Functional API。Graph API 在恢复时从节点边界重新进入,因此节点代码不会像 Temporal 风格的工作流那样从函数开头”重放”。 相比之下,Functional API 在运行恢复时从头重放@entrypoint 的主体,使用缓存的 @task 结果来跳过已完成的工作。两种更改会破坏此模型:
- 添加、删除或重新排序在恢复点之前的
@task调用或interrupt调用。LangGraph 通过重放中的位置将缓存结果和恢复值匹配到调用,因此移动该位置可能导致错误的缓存值被重放到不同的调用上。 - 在
@task之外引入非确定性操作,例如time.time()、random.random()或内联在入口点主体中的网络调用。在重放时,这些操作产生的值与首次运行时不同,可能会改变控制流。
@entrypoint 进行非平凡的代码更改,最安全的选项是:
- 在部署更改之前让正在进行的运行排空。
- 将任何新逻辑包装在新的
@task中,以便其结果独立进行检查点。 - 在
langgraph.json中以新的图名称注册新的入口点用于新行为,并将新线程路由到它。
将这些文档连接到 Claude、VSCode 等工具,通过 MCP 获取实时答案。

