《LangChain 系列》Human-in-the-loop:什么时候必须让人工介入?

前面几章我们已经把 Agent、Tool、LangGraph 都讲完了。现在要补上最关键的一环:人工介入。

没有 HITL 的 Agent,很像没有刹车的自动驾驶。它能跑,也可能跑得很快,但真正上线会让人害怕。

企业里最危险的不是模型回答错一句话,而是模型真的去删数据、发邮件、改权限、执行 SQL、触发支付。

1. HITL 是什么?

Human-in-the-loop,直译是"人在环路中"。

放到 Agent 里,就是:模型想调用某个工具时,系统先暂停,把工具名、参数、风险展示给审批人。人做决定后,Agent 再继续。

|--------------------------------------|
| HITL 不是让人替模型思考。HITL 是让人对高风险动作负责。 |

LangChain 的 HITL middleware 会在模型生成工具调用之后、工具真正执行之前介入。命中策略后,它会触发 interrupt,暂停执行,并等待 approve、edit、reject 或 respond 决策。

2. 哪些操作必须人工介入?

判断标准不用复杂:动作一旦执行,是否会改变真实世界。

只读查询通常可以自动。会产生副作用的动作,要分级。高风险副作用动作,必须人工审批。

金融、医疗、法务、客服、运维、权限系统,都是 HITL 的重点场景。模型可以给建议,但不能替组织承担责任。

3. 四种人工决策,不只是"同意/拒绝"

LangChain 的 HITL middleware 内置四种决策。它们对应四种执行结果。

approve:原样执行。适合低风险但仍需确认的动作。

edit:改参数后执行。适合收件人、路径、金额、SQL 条件需要人修正的动作。

reject:拒绝执行。适合危险动作、越权动作、信息不足的动作。

respond:人直接作为工具返回结果。适合 ask_user 这类"向用户询问"的工具。

|----------------------------------------------------------------------|
| 不要用 respond 拒绝副作用工具。respond 会被模型理解成工具成功执行。拒绝删除、转账、发信,应使用 reject。 |

4. 源码级看 HITL:它拦在哪里?

关键位置只有一个:after_model。

模型先生成 AIMessage。AIMessage 里可能带 tool_calls。正常流程下一步会进入 ToolNode 执行工具。HITL middleware 在这中间插了一刀。

源码链路可以压缩成这样:

after_model 读取 state"messages"

从后往前找到最后一条 AIMessage。

检查这条 AIMessage 是否包含 tool_calls。

用 interrupt_on 判断哪些工具需要人工审批。

命中后构造 HITLRequest。里面有 action_requests 和 review_configs。

调用 interrupt(HITLRequest),图执行暂停。

人工审批后,用 Command(resume={decisions}) 恢复。

_process_decision 根据 approve/edit/reject/respond 改写 tool_calls 或追加 ToolMessage。

图继续执行。能执行的工具进入 ToolNode,被拒绝的工具不会继续。

5. HumanInTheLoopMiddleware 的核心逻辑

它不是一个 UI 组件。它是 Agent 执行环路里的一个中间件。

初始化时,你会给它一张策略表:哪个工具要拦,允许哪些决策,是否有条件拦截。

源码里最核心的字段是 interrupt_on。它按工具名配置。True 表示全部决策都允许;False 表示自动放行;配置对象可以指定 allowed_decisions、description、when。

|-----------------------------------------|
| 策略表是 HITL 的灵魂。不要把所有工具都拦,也不要让危险工具裸奔。 |

after_model 的逻辑很直接:只要最后一条 AIMessage 带了工具调用,就逐个检查。需要审批的工具会被放进 action_requests;审批规则会被放进 review_configs。

这两个列表一起组成 HITLRequest。它不是给模型看的,而是给审批系统看的。审批系统需要知道:谁要执行什么、参数是什么、审批人能做哪些决定。

6. interrupt:暂停不是异常,而是可恢复中断

interrupt 是 LangGraph 提供的能力。它可以在图执行中间暂停,并把一个 JSON 可序列化的值暴露给调用方。

暂停之后,图状态会通过 persistence layer 保存。等人做完审批,再用 Command(resume=...) 恢复。

这里有三个硬规则:

必须配置 checkpointer。否则暂停后状态没地方保存。

必须传 thread_id。否则恢复时找不到同一个会话。

interrupt 的 payload 要简单可序列化。不要塞复杂对象。

官方文档也提醒:副作用动作如果发生在 interrupt 之前,必须保证幂等。否则恢复、重试、失败重放时,很容易重复执行。

7. Command(resume):人类决策怎么回到 Agent?

审批系统不是直接调用工具。审批系统只返回决策。

恢复时传入 Command(resume={"decisions": ...})。LangGraph 会把这个 resume 值交回之前暂停的 interrupt 调用点。

然后 HumanInTheLoopMiddleware 继续往下跑:

approve:保留原 tool_call。

edit:构造新的 ToolCall,保留原 tool_call_id,替换工具名或参数。

reject:生成 status="error" 的 ToolMessage,把拒绝原因交给模型。

respond:生成 status="success" 的 ToolMessage,把人类回复当成工具结果。

|-------------------------------------------------------|
| 本质上,人工决策最终会变成两类东西:新的 tool_calls,或者新的 ToolMessage。 |

8. 为什么说 HITL 必须工程化?

很多人以为 HITL 就是加一个弹窗:"是否执行?"

这不够。真正上线要有审批任务、权限体系、审计日志、超时策略、幂等控制、回调机制。

推荐落地方式:Java 主服务负责用户、权限、审批任务、审计日志;Python AI 服务负责 Agent、LangGraph、HITL middleware 和工具编排。

审批中心要展示人能看懂的内容。不要只展示 JSON。要展示动作说明、原始参数、风险提示、影响范围、发起人、traceId、历史上下文。

9. 上线检查表

HITL 的好坏,不看 Demo,看这张表。

特别强调幂等。

发邮件、扣款、改状态、删文件这类动作,都要有业务唯一键。审批恢复后再执行,不能因为网络重试导致重复执行。

10. 常见坑

还有一个隐藏坑:审批人不能只看模型总结。必须能看到原始工具名和原始参数。模型总结可以辅助理解,但不能成为唯一依据。

11. 总结

|-----------------------------------|
| HITL 的价值不是降低自动化,而是让自动化进入可控范围。 |

Agent 的能力越强,越需要边界。

工具越多,越需要权限。

动作越危险,越需要人类确认。

LangChain 的 HumanInTheLoopMiddleware 给的是拦截机制。LangGraph 的 interrupt 给的是暂停和恢复能力。checkpointer 给的是状态安全。真正的企业落地,还要靠审批中心、审计日志、幂等设计和权限体系。

下一章进入 Middleware:LangChain 里最容易被忽视,却最接近企业级治理的一层。


内容来源:《LangChain 系列》Human-in-the-loop:什么时候必须让人工介入?:功能变化与行业影响解析_热闻岛

相关推荐
冬哥聊AI1 小时前
Loop Engineering 来了:从写 Prompt 到设计 Loop,AI 编程的第四次范式跃迁
人工智能
柒星栈1 小时前
Codex 不只是更强的代码助手,它开始像代理一样推进开发任务了
人工智能
o_insist2 小时前
04-从零手写 ReAct 循环:Agent 的心跳是怎么转起来的
人工智能·agent
DayByDay2 小时前
从“单专家”到“多专家辩论”:多大脑对话实现复盘
人工智能
狗哥哥2 小时前
知乎回答二次创作转AI 漫画/视频思路分享
人工智能
makise-2 小时前
破译大数据底层密码:从 HDFS 存储基石到现代分布式计算引擎的架构演进
大数据·hdfs·架构
zzqssliu2 小时前
基于策略模式与责任链的代购商品多源采集架构实战
架构·策略模式
极速蜗牛2 小时前
我在 Taro 小程序项目里实践的 API First + AI 编程方式
前端·人工智能·后端