interrupt() 函数。该函数接受任何 JSON 可序列化的值,并将其返回给调用者。当您准备好继续时,您可以通过使用 Command 重新调用图来恢复执行,该 Command 随后成为节点内部 interrupt() 调用的返回值。 与静态断点(在特定节点之前或之后暂停)不同,中断是动态的——它们可以放置在代码中的任何位置,并且可以根据应用程序逻辑进行条件设置。- 检查点保留您的位置:检查点会将精确的图状态写入,以便您以后可以恢复,即使在错误状态下也能恢复。
thread_id是您的指针:使用{ configurable: { thread_id: ... } }作为invoke方法的选项,以告诉检查点器加载哪个状态。- 中断负载以
__interrupt__形式呈现:您传递给interrupt()的值以__interrupt__字段的形式返回给调用者,以便您知道图正在等待什么。
thread_id 实际上是您的持久游标。重复使用它会恢复相同的检查点;使用新值会启动一个全新的空状态线程。
使用 interrupt 暂停
interrupt 函数会暂停图执行并向调用者返回一个值。当您在节点内调用interrupt时,LangGraph 会保存当前图状态并等待您带输入恢复执行。 要使用interrupt,您需要:- 一个检查点器来持久化图状态(在生产环境中使用持久检查点器)
- 配置中的一个线程 ID,以便运行时知道从哪个状态恢复
- 在您想要暂停的地方调用
interrupt()(负载必须是 JSON 可序列化的)
interrupt时,会发生以下情况:
- 图执行被挂起在调用
interrupt的精确位置 - 状态被保存使用检查点器,以便以后可以恢复执行。在生产环境中,这应该是一个持久的检查点器(例如,由数据库支持)
- 值返回给调用者,位于
__interrupt__字段下;它可以是任何 JSON 可序列化的值(字符串、对象、数组等) - 图无限期等待直到您带响应恢复执行
- 响应被传递回节点,当您恢复时,它成为
interrupt()调用的返回值
恢复中断
中断暂停执行后,您通过再次调用它,并带有一个包含恢复值的Command 来恢复图。恢复值被传递回 interrupt 调用,允许节点继续执行外部输入。
- 恢复时必须使用与中断发生时使用的相同线程 ID
- 传递给
Command(resume=...)的值成为interrupt调用的返回值 - 节点从调用
interrupt的节点开头重新启动,因此interrupt之前的任何代码会再次运行 - 您可以将任何 JSON 可序列化的值作为恢复值
常见模式
中断解锁的关键功能是暂停执行并等待外部输入的能力。这对于各种用例都很有用,包括- 审批工作流:在执行关键操作(API 调用、数据库更改、金融交易)之前暂停
- 审查和编辑:允许人类在继续之前审查和修改 LLM 输出或工具调用
- 中断工具调用:在执行工具调用之前暂停,以便在执行前审查和编辑工具调用
- 验证人类输入:在进入下一步之前暂停以验证人类输入
批准或拒绝
中断最常见的用途之一是在关键操作之前暂停并请求批准。例如,您可能希望要求人工批准 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 调用中返回复杂值
根据所使用的检查点器,复杂值可能无法序列化(例如,您无法序列化函数)。为了使您的图能够适应任何部署,最佳实践是仅使用可以合理序列化的值。
- ✅ 将简单、JSON 可序列化的类型传递给
interrupt - ✅ 传递带有简单值的字典/对象
- 🔴 不要将函数、类实例或其他复杂对象传递给
interrupt
中断前调用的副作用必须是幂等的
由于中断的工作原理是重新运行它们被调用的节点,因此在调用interrupt之前调用的副作用应该(理想情况下)是幂等的。上下文是,幂等性意味着相同的操作可以多次应用,而结果除了初始执行之外不会改变。 例如,您可能在一个节点内有一个 API 调用来更新记录。如果在此调用之后调用interrupt,当节点恢复时,它将被多次重新运行,可能会覆盖初始更新或创建重复记录。
- 🔴 不要在
interrupt之前执行非幂等操作 - 🔴 不要不检查记录是否存在就创建新记录
与作为函数调用的子图一起使用
当在一个节点内调用子图时,父图将从子图被调用并且interrupt被触发的节点开头恢复执行。类似地,子图也将从调用interrupt的节点的开头恢复。
使用中断进行调试
为了调试和测试图,您可以使用静态中断作为断点,一次步进一个节点执行。静态中断在节点执行之前或之后在定义点触发。您可以通过在编译图时指定interruptBefore 和 interruptAfter 来设置这些。
静态中断不建议用于人工参与工作流。请改用
interrupt方法。- 编译时
- 运行时
- 断点在
compile时设置。 interruptBefore指定在节点执行之前应暂停执行的节点。interruptAfter指定在节点执行之后应暂停执行的节点。- 需要检查点器才能启用断点。
- 图将运行直到遇到第一个断点。
- 通过传入
null作为输入来恢复图。这将运行图直到下一个断点被命中。
使用 LangGraph Studio
您可以使用LangGraph Studio在运行图之前在 UI 中设置图中的静态中断。您还可以使用 UI 在执行的任何点检查图状态。
以编程方式连接这些文档到 Claude、VSCode 等,通过 MCP 获取实时答案。