LangGraph Interrupt 完整解析:设计原理、工作流程、使用场景
一、Interrupt 整体定位
Interrupt 是 LangGraph 实现 Human-in-the-Loop(人机闭环) 的核心原语,核心目标:在 Agent 流转任意位置动态暂停工作流,等待人类输入 / 审批后,持久化恢复执行,解决纯自动化流程无法处理人工决策、信息补全、风险审核的痛点LangGraph。依赖两大底层基础:
- Pregel 执行引擎:LangGraph 底层迭代调度内核,负责捕获中断异常、管控节点执行上下文;
- Checkpointer(检查点持久化) :中断必备组件,存储全量状态、执行位置、中断上下文,支撑跨会话、服务重启、长时间暂停恢复。
二、设计原理(底层实现细节)
1. 核心本质
Interrupt 不是同步阻塞等待 IO,而是基于受控异常 + 状态快照 + 断点恢复 的可中断执行模型:节点内调用 interrupt(展示给人类的上下文数据) → 主动抛出内置 GraphInterrupt 异常 → Pregel 引擎捕获异常,终止本轮图迭代 → 完整状态写入 Checkpointer → 对外返回中断标记;外部传入 Command(resume=人工结果) 重新调用图 → 引擎加载历史检查点,重新执行节点,识别恢复信号后,interrupt() 返回人工结果,节点继续向下运行。
2. 关键设计要点
(1)动态中断,而非静态断点
- 静态断点:只能配置节点执行前 / 执行后固定暂停;
- Interrupt:可写在节点函数任意代码行、分支逻辑内,支持条件触发中断(LLM 判断信息不足、风险操作才暂停),灵活性极强LangChain。
(2)状态全局持久化,无限时长等待
中断瞬间会序列化保存:
- 当前整个 Graph State(所有业务数据、对话历史);
- 中断位置、中断携带的提示信息;
- 迭代步数、路由跳转记录;只要持有唯一
thread_id,哪怕间隔几天、服务重启、集群迁移,都可以精准从中断点恢复,进程退出状态不丢失。
(3)恢复机制特点:节点从头重跑(核心特性)
Python 版 LangGraph 规则:恢复执行时,会重新完整运行触发中断的整个节点函数 ,而非停留在 interrupt() 调用行继续:
- 首次执行:节点代码走到
interrupt()→ 抛异常暂停; - 恢复执行:再次进入该节点,执行前面所有代码,再次走到
interrupt(); - 引擎检测到存在 resume 恢复值,不再抛异常,直接将值返回给变量,节点继续往下执行LangGraph。
优点:状态可复现、无上下文错乱;缺点:节点前置逻辑会重复执行,耗时逻辑需要做好幂等。
(4)中断栈:支持单节点多次嵌套中断
同一个节点内可以调用多次 interrupt(),引擎通过下标栈依次接收每一轮人工输入,有序返回结果,适配多轮问答交互场景。
(5)两大核心 API 配对使用
interrupt(payload):触发暂停,入参是要展示给前端 / 人类的结构化信息(可 JSON 序列化);Command(resume=value):恢复图执行,resume 内的值就是 interrupt 的返回值。
三、完整工作流程(分两大阶段)
阶段 1:首次运行,触发中断(暂停流程)
- 业务调用
graph.invoke(初始输入, config={"configurable":{"thread_id":"唯一会话ID"}})启动工作流; - Pregel 引擎加载空 / 初始状态,按路由依次执行各个节点;
- 执行到自定义节点,内部满足条件调用
interrupt(上下文信息); - 函数内部封装
GraphInterrupt异常并抛出; - Pregel 顶层循环捕获异常,停止后续所有节点调度;
- Checkpointer 将当前完整状态快照持久化(内存 / Redis/Postgres);
- invoke 调用结束,返回结果中携带
__interrupt__字段,包含等待人类处理的全部信息; - 工作流无限期挂起,不再继续执行。
阶段 2:人工处理后,恢复工作流
- 前端 / 业务系统展示中断信息,用户完成审批、填写内容、编辑文本;
- 后端使用同一个 thread_id ,调用
graph.invoke(Command(resume=人工输入值), config); - Pregel 通过 thread_id 从 Checkpointer 加载上次中断时的完整状态;
- 重新执行触发中断的节点函数,再次走到
interrupt(); - 引擎读取 resume 恢复值,将该值作为 interrupt () 返回值赋值给变量;
- 节点剩余代码继续执行,完成本节点逻辑后,按照原有路由跳转后续节点;
- 每走完一轮迭代,自动写入新检查点;
- 若无新中断,工作流执行完毕,返回最终结果。
简易时序图
plaintext
scss
客户端 → Graph启动 → 执行节点 → interrupt()抛出异常
↓(状态存入Checkpointer)
客户端接收中断提示 → 人工操作 → 提交Command(resume)
↓
Graph加载快照 → 重跑节点 → interrupt返回结果 → 走完剩余流程 → 结束
四、典型使用场景
1. 高风险操作人工审批(最常用)
- Agent 要执行转账、删除线上数据、发送正式通知、下单付款等高危行为;
- 执行工具调用前触发中断,等待管理员审批通过 / 驳回后再执行操作;例:AI 财务助手生成报销单后,先推送审批,主管确认后再提交付款申请。
2. 信息缺失,主动向用户追问补全信息
LLM 执行任务时发现参数不足:预订机票缺少出发日期、做方案缺少预算范围、写报告缺少行业限定;动态中断流程,向用户提问收集信息,拿到回答后继续生成内容,替代生硬一次性表单填写。
3. 内容人工审核修订
AI 生成文案、合同、邮件、代码方案、知识库内容后:
- 暂停流转,交由人类校对修改;
- 人工修改后的文本传回 Agent,继续后续排版、归档、发送流程;适合公众号推文、法务合同、客服话术生成场景。
4. 多智能体协作交接审批
多 Agent 分层架构:执行 Agent 完成工作后,提交给主管 Agent 审核;通过中断实现跨角色人工 / 代理校验,审核不通过退回重写,通过则进入下一环节。
5. 长任务分段执行、跨会话接续
复杂任务(撰写毕业论文、项目规划、数据分析报告)耗时极长,用户中途退出会话;依靠中断 + 持久化检查点,下次打开页面可接续上次写到一半的流程,无需从头开始。
6. 工具调用前置校验拦截
Agent 想要调用第三方工具(地图查询、API 调取外部业务数据)时,业务规则要求每次调用都需要用户授权确认,通过中断实现授权弹窗。
五、补充:与普通 input () 函数核心区别
表格
| 特性 | LangGraph Interrupt | Python input () 原生输入 |
|---|---|---|
| 状态持久化 | ✅ 全程快照保存,重启可恢复 | ❌ 内存阻塞,进程退出全部丢失 |
| 暂停时长 | 无限期等待 | 同步阻塞,必须当场输入 |
| 分布式 / 服务端适配 | ✅ 适配 Web 接口、微服务架构 | ❌ 仅本地控制台可用 |
| 条件动态触发 | ✅ 代码分支里任意位置暂停 | ❌ 固定位置阻塞 |
| 多轮嵌套交互 | ✅ 支持连续多次问答中断 | ❌ 简单串行输入 |
六、核心约束
- 必须配置 Checkpointer(生产环境推荐 Postgres/Redis 持久化存储,MemorySaver 仅调试用);
- 恢复必须使用完全一致的 thread_id;
- 节点内前置逻辑会重复执行,节点代码必须保证幂等性。