Human-in-the-loop
Human-in-the-loop 是在 Agent 执行流程中引入人类判断点的模式,用于审批高风险操作、纠正错误决策、提供缺失信息。它是 Agent 安全性和可靠性的关键保障。
#type / concept
#status / evergreen
#tech / ai
#tech / architecture
[!info] related notes
- 所属 MOC: AI Agent Application MOC, Agent MOC
- 相关概念: Agent Guardrails, Approval Checkpoints
- UI: Human Approval UI
- 运行时: Agent Runtime — 中断与恢复机制
Human-in-the-loop
一句话定义
Human-in-the-loop (HITL) 是在 Agent 自主执行流程中嵌入人类判断点的模式,让人类在关键节点介入:审批高风险操作、纠正错误决策、提供模型无法获取的信息。
它解决什么问题
完全自主的 Agent 有三个风险:
- 不可逆的错误: Agent 误删数据、误发邮件、误扣款项
- 缺乏领域判断: 某些决策需要人类的经验和直觉
- 用户信任缺失: 用户不放心让 Agent 自己做所有事
HITL 不是”让 Agent 变笨”,而是在自主性和安全性之间找到平衡。
核心原理
介入点类型
Agent 执行流程:
│
├─ [信息采集] → 用户提供缺失信息
│ 例: Agent 不确定用户要查哪个地区的数据
│
├─ [决策确认] → 用户确认 Agent 的计划
│ 例: Agent 说"我准备删除这 50 条记录,确认吗?"
│
├─ [审批检查] → 高风险操作必须审批
│ 例: 转账、删除、发布等不可逆操作
│
├─ [纠错介入] → 用户发现 Agent 方向错误
│ 例: Agent 搜索了错误的关键词
│
└─ [结果验收] → 用户确认最终结果
例: Agent 生成的报告是否满意
实现机制
HITL 的核心机制是中断 (Interrupt) + 恢复 (Resume):
Agent 运行中
│
▼
遇到需要人类判断的节点
│
▼
保存当前状态 (Checkpoint)
│
▼
暂停执行,返回中间结果给前端
│
▼
前端展示审批界面
│
▼
用户做出决策 (批准/拒绝/修改)
│
▼
恢复执行,携带用户的决策
│
▼
继续 Agent 流程
LangGraph 的 Interrupt 机制
from langgraph.graph import StateGraph
from langgraph.checkpoint import MemorySaver
graph = StateGraph(AgentState)
# 在工具执行前中断
graph.add_node("execute_tool", execute_tool_node)
graph.add_interrupt_before("execute_tool") # 执行前暂停
# 编译时启用 checkpoint
app = graph.compile(checkpointer=MemorySaver())
# 运行到中断点
result = app.invoke(input_data, config={"thread_id": "xxx"})
# 用户审批后恢复
app.resume(approval="approved", config={"thread_id": "xxx"})
在 React + Go + Python AI Service 架构中的位置
Python AI Service:
Agent 遇到高风险工具调用
→ 保存 Checkpoint
→ 返回 interrupt 事件
Go 后端:
收到 interrupt 事件
→ 通知前端需要审批
→ 等待用户决策
React 前端:
展示 Human Approval UI
→ 用户点击"批准"或"拒绝"
→ 发送审批结果到后端
Go 后端:
转发审批结果到 AI Service
Python AI Service:
恢复执行,携带审批结果
典型工程实现
事件协议
// Agent 返回的中断事件
{
"event": "interrupt",
"data": {
"interrupt_id": "int_001",
"type": "approval_required",
"tool_call": {
"name": "delete_records",
"arguments": {"record_ids": ["id_1", "id_2", "id_3"]}
},
"message": "即将删除 3 条记录,此操作不可撤销。",
"options": ["approve", "reject", "modify"]
}
}
// 用户的审批响应
{
"event": "resume",
"data": {
"interrupt_id": "int_001",
"decision": "approved",
"modifications": null
}
}
审批 UI 设计
function ApprovalCard({ interrupt }: { interrupt: InterruptEvent }) {
return (
<div className="approval-card">
<h3>⚠️ 需要确认</h3>
<p>{interrupt.message}</p>
<pre>{JSON.stringify(interrupt.tool_call, null, 2)}</pre>
<div className="actions">
<button onClick={() => resume("approved")}>✅ 批准</button>
<button onClick={() => resume("rejected")}>❌ 拒绝</button>
<button onClick={() => resume("modified")}>✏️ 修改后执行</button>
</div>
</div>
);
}
常见设计模式
1. 预定义审批点
在 Tool 定义中标记 requires_approval: true,Agent Runtime 自动在调用前中断。
2. 动态审批
根据参数动态判断是否需要审批(如金额 > 1000 需审批)。
3. 超时自动拒绝
用户长时间不响应,自动拒绝并通知 Agent。
4. 批量审批
多个低风险操作打包成一个审批请求。
常见坑
- 审批点太多: 每个操作都要审批,用户体验极差
- 审批点太少: 高风险操作没有人类把关
- 中断后状态丢失: 没有 Checkpoint,恢复时上下文丢失
- 审批界面信息不足: 用户看不到完整参数,无法做出判断
- 不做超时处理: 用户永远不响应,Agent 永远卡住
和其他概念的关系
- vs Guardrails: Guardrails 是自动化的规则检查,HITL 是人类判断
- vs Approval Checkpoints: Checkpoints 是 HITL 的具体实现机制
- vs Checkpoint: Checkpoint 是 HITL 的状态持久化基础
- vs Human Approval UI: Approval UI 是 HITL 的前端实现
总结
HITL 的核心是让 Agent 知道什么时候该问人。好的 HITL 设计既不会让 Agent 太自由(风险),也不会让 Agent 太受限(效率)。