interrupt() 函数。该函数接受任何 JSON 可序列化的值,并将其暴露给调用方。当你准备继续时,可以使用 Command 重新调用图来恢复执行,该值将成为节点内 interrupt() 调用的返回值。
与静态断点(在特定节点前后暂停)不同,中断是动态的——它们可以放置在代码的任意位置,并可根据应用逻辑设置条件。
- 检查点保存你的位置: 检查点器会写入精确的图状态,让你之后可以恢复执行,即使处于错误状态也可以。
thread_id是你的指针: 设置config={"configurable": {"thread_id": ...}}以告诉检查点器加载哪个状态。- 中断载荷以
__interrupt__形式暴露: 你传给interrupt()的值会通过__interrupt__字段返回给调用方,让你知道图在等待什么。
thread_id 实际上就是你的持久游标。重用它会恢复同一个检查点;使用新值则会启动一个状态为空的全新线程。
使用 interrupt 暂停
interrupt 函数会暂停图执行并将一个值返回给调用方。当你在节点中调用 interrupt 时,LangGraph 会保存当前图状态,并等待你带着输入恢复执行。
使用 interrupt 需要:
- 一个检查点器来持久化图状态(生产环境中请使用持久化检查点器)
- 配置中的一个 thread ID,让运行时知道从哪个状态恢复
- 在你想要暂停的地方调用
interrupt()(载荷必须是 JSON 可序列化的)
interrupt 时,会发生以下情况:
- 图执行被暂停,精确停在
interrupt被调用的位置 - 状态被保存,使用检查点器以便之后恢复执行。生产环境中应使用持久化检查点器(例如由数据库支持)
- 值被返回给调用方,以
__interrupt__形式呈现;可以是任何 JSON 可序列化的值(字符串、对象、数组等) - 图无限期等待,直到你带着响应恢复执行
- 响应被传回节点,成为
interrupt()调用的返回值
恢复中断
中断暂停执行后,你可以通过再次调用图并传入包含恢复值的Command 来恢复图执行。恢复值会被传回到 interrupt 调用处,让节点能够利用外部输入继续执行。
- 恢复时必须使用与中断发生时相同的 thread ID
- 传给
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 输出、补充缺失信息或进行调整非常有用。Full example
Full example
工具中的中断
你也可以直接在工具函数内部设置中断。这使得工具每次被调用时都会暂停等待审批,并允许在执行工具调用前进行人工审查和编辑。 首先,定义一个使用interrupt 的工具:
Full example
Full example
验证人类输入
有时你需要验证来自人类的输入,并在输入无效时重新提问。你可以在循环中使用多个interrupt 调用来实现这一点。
Full example
Full example
中断规则
当你在节点中调用interrupt 时,LangGraph 通过抛出一个特殊异常来暂停执行,该异常会通知运行时进行暂停。这个异常沿调用栈向上传播,被运行时捕获,通知图保存当前状态并等待外部输入。
当执行恢复时(在你提供了请求的输入之后),运行时会从节点开头重新启动整个节点——而不是从 interrupt 被调用的确切位置恢复。这意味着 interrupt 之前运行的任何代码都会再次执行。因此,在使用中断时有一些重要规则需要遵守,以确保其行为符合预期。
不要将 interrupt 调用包裹在 try/except 中
interrupt 在调用点暂停执行的方式是抛出一个特殊异常。如果你将 interrupt 调用包裹在 try/except 块中,就会捕获这个异常,中断将无法传回图。
- ✅ 将
interrupt调用与可能出错的代码分开 - ✅ 在 try/except 块中使用特定的异常类型
- 🔴 不要将
interrupt调用包裹在裸 try/except 块中
不要在节点内重排 interrupt 调用
在单个节点中使用多个中断很常见,但如果处理不当可能导致意外行为。
当节点包含多个 interrupt 调用时,LangGraph 会维护一个与执行该节点的任务对应的恢复值列表。每次恢复执行时,都从节点开头开始。对于遇到的每个 interrupt,LangGraph 检查任务恢复列表中是否存在匹配的值。匹配是严格基于索引的,因此节点内 interrupt 调用的顺序非常重要。
- ✅ 保持
interrupt调用在各次节点执行中一致
不要在 interrupt 调用中返回复杂值
根据所使用的检查点器,复杂值可能无法序列化(例如,函数不能被序列化)。为使你的图能适应任何部署环境,最佳实践是只使用可以合理序列化的值。
- ✅ 向
interrupt传入简单的 JSON 可序列化类型 - ✅ 传入包含简单值的字典/对象
- 🔴 不要向
interrupt传入函数、类实例或其他复杂对象
interrupt 之前的副作用必须是幂等的
由于中断通过重新运行所在节点来工作,在 interrupt 之前调用的副作用最好是幂等的。幂等性是指同一操作可以多次执行,但结果与首次执行相同。
例如,你可能在节点内有一个更新记录的 API 调用。如果该调用完成后才调用 interrupt,节点恢复时这个 API 调用会被多次重新执行,可能会覆盖初始更新或创建重复记录。
- 🔴 不要在
interrupt之前执行非幂等操作 - 🔴 不要在未检查记录是否已存在的情况下创建新记录
与以函数方式调用的子图配合使用
在节点中调用子图时,父图将从调用子图的节点开头恢复执行,即触发interrupt 的地方。同样,子图也会从调用 interrupt 的节点开头恢复。
使用中断进行调试
为了调试和测试图,你可以使用静态中断作为断点,逐节点地单步执行图。静态中断在节点执行前或执行后的定义位置触发。你可以在编译图时通过指定interrupt_before 和 interrupt_after 来设置这些断点。
静态中断不推荐用于人机协作工作流。请改用
interrupt 函数。- 编译时
- 运行时
- 断点在
compile时设置。 interrupt_before指定在节点执行之前暂停的节点。interrupt_after指定在节点执行之后暂停的节点。- 需要检查点器才能启用断点。
- 图运行直到命中第一个断点。
- 通过传入
None作为输入来恢复图。这会运行图直到命中下一个断点。
使用 LangSmith Studio
你可以使用 LangSmith Studio 在 UI 中运行图之前设置静态中断。你还可以使用 UI 在执行过程中的任意节点检查图状态。
连接这些文档 到 Claude、VSCode 等,通过 MCP 获取实时答案。

