《LangGraph Human-in-the-loop:Interrupt 如何让 Agent 等待人工确认》

前面我们已经解决了:

  • Graph 如何组织 Agent 流程
  • State 如何在节点之间流转
  • Conditional Edge 如何动态选择路径
  • Checkpointer 如何保存 State

但是实际 Agent 还有一个重要问题:

不是所有事情都应该让 Agent 自动完成。

有些操作需要人确认。

例如:

  • 转账
  • 删除文件
  • 发布文章
  • 发送邮件
  • 修改数据库

这时候就需要:

Human-in-the-loop(人在循环中)


1. 为什么 Agent 需要人工介入?

假设一个自动 Agent:

复制代码
用户:

帮我给张三转账100元


Agent:

调用转账工具


完成

如果 Agent 判断错误:

复制代码
转错账户

转错金额

后果很严重。

所以更合理:

复制代码
用户

↓

Agent准备执行

↓

暂停

↓

用户确认

↓

继续执行

2. Interrupt 是什么?

LangGraph 提供:

scss 复制代码
interrupt()

它的作用:

暂停当前 Graph 执行,并等待外部输入。

例如:

ini 复制代码
const awaitConfirm = (state)=>{

  const input = interrupt({
    action:"向张三转账100元"
  });

}

执行:

scss 复制代码
Node

↓

interrupt()

↓

暂停

3. Interrupt 发生了什么?

注意:

interrupt 不是普通函数返回。

它不会:

kotlin 复制代码
return "等待"

而是:

复制代码
暂停 Graph

此时:

diff 复制代码
当前 State

+

当前执行位置

需要保存。

所以:

复制代码
interrupt

必须依赖

checkpointer

4. 一个转账 Demo

State:

javascript 复制代码
const StateAnnotation = Annotation.Root({

  actionSummary:Annotation({
    reducer:(prev,next)=>next,
    default:()=> ""
  }),

  userInput:Annotation({
    reducer:(prev,next)=>next,
    default:()=> ""
  })

});

保存两个数据:

复制代码
actionSummary

用户要确认的动作


userInput

用户输入

第一个节点

dart 复制代码
const showTransfer = ()=>({

  actionSummary:
    "向张三转账 $100"

});

执行:

State:

bash 复制代码
{
 actionSummary:
 "向张三转账 $100"
}

第二个节点

arduino 复制代码
const awaitConfirm=(state)=>{

 const text=interrupt({

   actionSummary:
   state.actionSummary

 });

 return {
   userInput:text
 }

}

读取:

复制代码
state.actionSummary

得到:

bash 复制代码
向张三转账 $100

然后:

scss 复制代码
interrupt()

暂停。


5. Graph 暂停之后发生什么?

第一次:

arduino 复制代码
await graph.invoke({},config)

执行:

sql 复制代码
START

↓

showTransfer

↓

awaitConfirm

↓

interrupt暂停

返回:

类似:

css 复制代码
{
 __interrupt__:[
   {
    value:{
      actionSummary:
      "向张三转账 $100"
    }
   }
 ]
}

此时:

Agent 等待用户。

例如:

终端:

markdown 复制代码
是否确认?

> 确认

6. 如何恢复?

恢复需要:

复制代码
Command

例如:

arduino 复制代码
await graph.invoke(
  new Command({
    resume:"确认"
  }),
  config
);

含义:

告诉 LangGraph:

上次暂停的位置继续执行,并把这个值交给 interrupt。


恢复后:

原来的:

scss 复制代码
const text = interrupt(...)

会得到:

ini 复制代码
text="确认"

然后继续:

kotlin 复制代码
return {
 userInput:"确认"
}

最终:

bash 复制代码
{
 actionSummary:
 "向张三转账 $100",

 userInput:
 "确认"
}

流程结束。


7. 为什么一定需要 thread_id?

因为可能有很多用户同时暂停:

例如:

用户A:

复制代码
等待确认转账

用户B:

复制代码
等待确认删除文件

LangGraph 必须知道:

恢复哪个任务。

所以:

css 复制代码
{
 configurable:{
   thread_id:"user-a"
 }
}

表示:

恢复 user-a 的那一次执行。


8. Interrupt 完整流程

scss 复制代码
用户请求

↓

Agent执行

↓

准备执行危险操作

↓

interrupt()

↓

保存 State + 执行位置

↓

等待用户

↓

Command(resume)

↓

恢复 Graph

↓

继续执行

↓

结束

9. Interrupt 和普通函数暂停的区别

普通代码:

javascript 复制代码
function test(){

 console.log("开始");

 await input();

 console.log("继续");

}

如果程序关闭:

状态没了。

LangGraph:

复制代码
interrupt

↓

checkpointer保存现场

↓

之后恢复

它保存的是:

  • State
  • 当前节点
  • 执行路径

所以它适合长流程 Agent。


10. LangGraph 到这里形成完整 Agent 工作流

现在完整模型:

vbnet 复制代码
                 State

                   ↓


START

 ↓

Node

 ↓

Edge

 ↓

Conditional Edge

 ↓

Loop

 ↓

Checkpointer

 ↓

Interrupt

 ↓

Resume

 ↓

END

总结

一句话:

Interrupt 让 LangGraph 支持人工介入,它可以暂停 Agent 工作流,保存当前状态,等待用户输入后继续执行,是构建安全可靠 Agent 系统的重要能力。

相关推荐
2601_962218612 小时前
万象生鲜系统业财一体化底层打通技术自动生成经营账单
大数据·数据库·人工智能·python·算法
智塑未来2 小时前
中文短剧出海翻译工具横评:VMEG AI、鬼手、Vozo AI、ElevenLabs怎么选?
人工智能
东风破_2 小时前
《LangGraph 条件路由与循环:如何让 Agent 自己决定下一步?》
人工智能
我爱吃土豆12 小时前
AI 编程工具远程开发指南:Codex 桌面版与 WorkBuddy 通过 SSH 连接云服务器实践
服务器·人工智能·ssh
袁俪2 小时前
推理成本门槛
人工智能
2601_962304253 小时前
怎么用AI绘画零基础制作专属插画头像?
人工智能·ai作画
东风破_3 小时前
《LangGraph 状态管理:State、Node 和 Reducer 到底是什么?》
人工智能
东风破_3 小时前
《LangGraph 入门:为什么 Agent 需要 Graph 工作流?》
人工智能
MobotStone3 小时前
从产品角度:拆解WorkBuddy 功能
人工智能