interrupt() 函数。该函数接受任何可 JSON 序列化的值,该值会呈现给调用者。当你准备好继续时,通过使用 Command 重新调用图来恢复执行,Command 将成为节点内 interrupt() 调用的返回值。
与静态断点(在特定节点之前或之后暂停)不同,中断是动态的——它们可以放置在代码的任何位置,并且可以基于应用程序逻辑进行条件判断。
- 检查点保持你的位置: checkpointer 写入确切的图状态,以便你可以稍后恢复,即使处于错误状态。
thread_id是你的指针: 使用{ configurable: { thread_id: ... } }作为invoke方法的选项来告诉 checkpointer 加载哪个状态。- 中断负载呈现为
__interrupt__: 你传递给interrupt()的值会在__interrupt__字段中返回给调用者,以便你知道图在等待什么。
thread_id 实际上是你的持久游标。重用它会恢复同一个检查点;使用新值会启动一个状态为空的全新线程。
使用 interrupt 暂停
interrupt 函数暂停图执行并将值返回给调用者。当你在节点内调用 interrupt 时,LangGraph 保存当前图状态并等待你使用输入恢复执行。
要使用 interrupt,你需要:
- 一个 checkpointer 来持久化图状态(在生产环境中使用持久 checkpointer)
- 配置中的 thread ID,以便运行时知道从哪个状态恢复
- 在你想暂停的地方调用
interrupt()(负载必须是 JSON 可序列化的)
interrupt 时,会发生以下情况:
- 图执行在调用
interrupt的确切点暂停 - 状态被保存使用 checkpointer,以便稍后恢复执行。在生产环境中,这应该是一个持久 checkpointer(例如由数据库支持)
- 值被返回给调用者,位于
__interrupt__下;它可以是任何 JSON 可序列化的值(字符串、对象、数组等) - 图无限期等待直到你用响应恢复执行
- 响应被传回节点,当你恢复时,成为
interrupt()调用的返回值
恢复中断
在中断暂停执行后,你通过使用包含恢复值的Command 再次调用图来恢复它。恢复值被传回 interrupt 调用,允许节点使用外部输入继续执行。
- 恢复时必须使用与中断发生时相同的 thread ID
- 传递给
new Command({ resume: ... })的值成为interrupt调用的返回值 - 恢复时,节点从调用
interrupt的节点的开头重新启动,因此interrupt之前的任何代码都会再次运行 - 你可以传递任何 JSON 可序列化的值作为恢复值
常见模式
中断解锁的关键是暂停执行并等待外部输入的能力。这对各种用例都很有用,包括:- 审批工作流:在执行关键操作(API 调用、数据库更改、金融交易)之前暂停
- 处理多个中断:在单次调用中恢复多个中断时,将中断 ID 与恢复值配对
- 审查和编辑:让人们在继续之前审查和修改 LLM 输出或工具调用
- 中断工具调用:在执行工具调用之前暂停,以便在执行之前审查和编辑工具调用
- 验证人工输入:在进行下一步之前暂停以验证人工输入
带有中途中断 (HITL) 的流式传输
当构建带有人机交互工作流的交互式代理时,你可以同时流式传输消息块和节点更新,以便在处理中断的同时提供实时反馈。 使用多个流模式("messages" 和 "updates")以及 subgraphs=True(如果存在子图)来:
- 随着生成实时流式传输 AI 响应
- 检测图何时遇到中断
- 处理用户输入并无缝恢复执行
stream_mode=["messages", "updates"]:启用消息块和图状态更新的双重流式传输subgraphs=True:嵌套图中检测中断所必需的"__interrupt__"检测:发信号表示需要人工输入Command(resume=...):使用用户提供的数据恢复图执行
处理多个中断
当并行分支同时中断(例如,扇出到多个节点,每个节点都调用interrupt())时,你可能需要在单次调用中恢复多个中断。
当使用单次调用恢复多个中断时,将每个中断 ID 映射到其恢复值。
这确保每个响应在运行时与正确的中断配对。
批准或拒绝
中断最常见的用途之一是在关键操作之前暂停并请求批准。例如,你可能想要求人类批准 API 调用、数据库更改或任何其他重要决定。true 以批准或 false 以拒绝:
完整示例
完整示例
审查和编辑状态
有时你想让人类在继续之前审查和编辑部分图状态。这对于纠正 LLM、添加缺失信息或进行调整很有用。完整示例
完整示例
工具中的中断
你也可以将中断直接放在工具函数中。这使得工具本身在每次被调用时都会暂停以获得批准,并允许在执行之前对工具调用进行人工审查和编辑。 首先,定义一个使用interrupt 的工具:
完整示例
完整示例
验证人工输入
有时你需要验证来自人类的输入,如果无效则再次询问。你可以通过在循环中使用多个interrupt 调用来实现这一点。
完整示例
完整示例
中断规则
当你在节点内调用interrupt 时,LangGraph 通过引发一个信号运行时暂停的异常来暂停执行。此异常通过调用堆栈向上传播并被运行时捕获,运行时通知图保存当前状态并等待外部输入。
当执行恢复时(在你提供请求的输入后),运行时从头开始重新启动整个节点——它不会从调用 interrupt 的确切行恢复。这意味着 interrupt 之前的任何代码都会再次执行。因此,在使用中断时需要遵循一些重要规则,以确行为符合预期。
不要将 interrupt 调用包装在 try/catch 中
interrupt 在调用点暂停执行的方式是抛出一个特殊异常。如果你将 interrupt 调用包装在 try/catch 块中,你将捕获此异常,并且中断将不会传回图。
- ✅ 将
interrupt调用与容易出错的代码分开 - ✅ 如果需要,有条件地捕获错误
- 🔴 不要将
interrupt调用包装在裸 try/catch 块中
不要在节点内重新排序 interrupt 调用
在单个节点中使用多个中断很常见,但是如果不小心处理,这可能会导致意外行为。
当节点包含多个中断调用时,LangGraph 保留特定于执行该节点的任务的恢复值列表。每当执行恢复时,它从节点的开头开始。对于遇到的每个中断,LangGraph 检查任务的恢复列表中是否存在匹配值。匹配是严格基于索引的,因此节点内中断调用的顺序很重要。
- ✅ 保持
interrupt调用在节点执行之间的一致性
不要在 interrupt 调用中返回复杂值
根据使用的 checkpointer,复杂值可能不可序列化(例如,你无法序列化函数)。为了使你的图适应任何部署,最佳实践是仅使用可以合理序列化的值。
- ✅ 传递简单的、JSON 可序列化的类型给
interrupt - ✅ 传递具有简单值的字典/对象
- 🔴 不要传递函数、类实例或其他复杂对象给
interrupt
在 interrupt 之前调用的副作用必须是幂等的
因为中断的工作原理是重新运行调用它们的节点,所以在 interrupt 之前调用的副作用(理想情况下)应该是幂等的。就上下文而言,幂等性意味着同一操作可以应用多次,而不会在初始执行之外改变结果。
作为一个例子,你可能在节点内有一个 API 调用来更新记录。如果 interrupt 在该调用之后被调用,那么当节点恢复时,它将被多次重新运行,可能会覆盖初始更新或创建重复记录。
- 🔴 不要在
interrupt之前执行非幂等操作 - 🔴 不要在不检查是否存在的情况下创建新记录
与作为函数调用的子图一起使用
当在节点内调用子图时,父图将从调用子图并触发interrupt 的节点的开头恢复执行。同样,子图也将从调用 interrupt 的节点的开头恢复。
使用中断进行调试
为了调试和测试图,你可以使用静态中断作为断点,一次一个节点地单步执行图。静态中断在节点执行之前或之后的定义点触发。你可以在编译图时通过指定interruptBefore 和 interruptAfter 来设置这些。
静态中断不推荐用于人机交互工作流。请改用
interrupt 函数。- 编译时
- 运行时
- 断点在
compile时设置。 interruptBefore指定应在节点执行之前暂停执行的节点。interruptAfter指定应在节点执行之后暂停执行的节点。- 需要 checkpointer 来启用断点。
- 图运行直到遇到第一个断点。
- 通过传入
null作为输入来恢复图。这将运行图直到遇到下一个断点。
使用 LangSmith Studio
你可以使用 LangSmith Studio 在运行图之前在 UI 中设置静态中断。你还可以使用 UI 检查执行中任何点的图状态。
将这些文档连接 到 Claude、VSCode 等,通过 MCP 获取实时答案。

