LangChain的Human In The Loop让AI学会请示你再动手AI太能干有时候是一种烦恼。你有没有遇到过这种情况让AI帮你发邮件它直接发出去了——措辞没问题但发错了人 让AI帮你删文件它删得干干净净——连回收站都没留 让AI帮你回复客户它真的回复了——语气比你还真诚。AI太听话有时候也是一种烦恼。今天我们来聊聊LangChain里解决这个问题的核心机制Human In The Loop人在回路中。通过一个真实的邮件处理案例手把手教你如何让AI在关键操作前先请示你。一、问题场景AI的顺手操作假设你正在开发一个AI助手帮用户处理邮件。用户说请读取我的邮件然后立即回复。邮件内容是Hi Seán, Im going to be late for our meeting tomorrow. Can we reschedule? Best, John.AI看到后顺手就帮你回复了——可能回得不错但万一呢在AI代理Agent的世界里这种顺手操作就是定时炸弹。我们需要一种机制让AI在发送邮件之前先暂停等人类确认。这就是Human In The LoopHITL要解决的问题。二、LangChain的解决方案HumanInTheLoopMiddlewareLangChain 提供了HumanInTheLoopMiddleware中间件可以在工具执行前拦截等待人工审批。核心思路很简单AI想要调用 send_email ↓ 中间件拦截检测到 send_email 需要审批 ↓ ⏸️ 暂停展示审批界面 ↓ 人类选择批准 / 拒绝 / 修改 ↓ ✅ 继续执行 / ❌ 取消 / 修改后执行三、代码实战一个邮件代理的完整流程下面我们基于一个真实的 LangChain 案例完整演示 HITL 的用法。3.1 定义工具首先我们定义两个邮件相关的工具from langchain.tools import tool, ToolRuntime tool def read_email(runtime: ToolRuntime) - str: Read an email from the given address. # 从状态中读取邮件内容 return runtime.state[email] tool def send_email(body: str) - str: Send an email to the given address with the given subject and body. # 模拟发送邮件 return Email sentread_email读取邮件低风险不需要审批send_email发送邮件高风险需要审批3.2 创建带审批的Agentfrom langchain.agents import create_agent, AgentState from langgraph.checkpoint.memory import InMemorySaver from langchain.agents.middleware import HumanInTheLoopMiddleware # 自定义状态包含邮件字段 class EmailState(AgentState): email: str agent create_agent( modelgpt-5-nano, tools[read_email, send_email], state_schemaEmailState, checkpointerInMemorySaver(), middleware[ HumanInTheLoopMiddleware( interrupt_on{ read_email: False, # 读取邮件不需要审批 send_email: True, # 发送邮件需要审批 }, description_prefixTool execution requires approval, ), ], )关键配置interrupt_on一个字典键是工具名值是布尔read_email: False→ 直接执行不暂停send_email: True→ 暂停等人类确认description_prefix审批提示的前缀文字checkpointer保存中间状态确保暂停后能恢复3.3 运行代理触发中断from langchain.messages import HumanMessage config {configurable: {thread_id: 1}} response agent.invoke( { messages: [ HumanMessage( contentPlease read my email and send a response immediately. Send the reply now in the same thread. ) ], email: Hi Seán, Im going to be late for our meeting tomorrow. Can we reschedule? Best, John., }, configconfig, )运行后AI 会先调用read_email读取邮件不暂停然后想要调用send_email被拦截暂停响应中包含__interrupt__字段表示代理正在等待人工输入print(response[__interrupt__])3.4 查看中断详情你可以获取待审批的操作内容# 获取 send_email 工具的 body 参数 print(response[__interrupt__][0].value[action_requests][0][args][body])这会显示 AI 想要发送的邮件内容供人类审阅。四、三种审批操作批准、拒绝、修改当代理暂停后你可以通过Command恢复执行支持三种操作4.1 批准Approvefrom langgraph.types import Command response agent.invoke( Command( resume{decisions: [{type: approve}]} ), configconfig, # 使用同一个 thread_id 恢复暂停的对话 )AI 收到批准指令后继续执行send_email。4.2 拒绝Rejectresponse agent.invoke( Command( resume{ decisions: [ { type: reject, message: No please sign off - Your merciful leader, Seán. } ] } ), configconfig, )AI 收到拒绝指令后取消发送并返回拒绝原因。4.3 修改后执行Edit这是最实用的功能——人类可以修改 AI 的操作内容response agent.invoke( Command( resume{ decisions: [ { type: edit, edited_action: { name: send_email, # 工具名 args: { body: This is the last straw, youre fired!# 修改后的内容 }, }, } ] } ), configconfig, )AI 收到修改指令后用人类修改后的内容执行send_email。五、完整流程图用户输入读取邮件并立即回复 ↓ AI 调用 read_email → 成功读取邮件不暂停 ↓ AI 想要调用 send_email → 被 HumanInTheLoopMiddleware 拦截 ↓ ⏸️ 暂停返回 __interrupt__ 状态 ↓ 人类查看待发送内容选择 ├── 批准approve→ 继续执行 ├── 拒绝reject→ 取消操作 └── 修改edit→ 修改内容后执行 ↓ ✅ 代理继续运行完成后续任务六、为什么这个机制如此重要6.1 防止不可逆操作发送邮件、删除文件、转账支付——这些操作一旦执行就很难撤回。HITL 在关键节点加入人工确认是防止AI手滑的重要防线。6.2 符合合规要求在金融、医疗、法律等领域AI的决策必须有人工审核。HITL 机制天然满足合规要求。6.3 建立人机协作信任AI不是替代人类而是辅助人类。HITL 让AI成为副驾驶而非自动驾驶建立正确的协作关系。七、总结今天我们通过一个邮件处理案例完整演示了 LangChain 的 Human In The Loop 机制步骤说明1. 定义工具read_email低风险、send_email高风险2. 配置中间件HumanInTheLoopMiddleware(interrupt_on{send_email: True})3. 运行代理AI 在send_email处自动暂停4. 人工审批批准 / 拒绝 / 修改5. 恢复执行根据人类决策继续运行一句话记住HITL 让AI从先斩后奏变成先奏后斩——关键操作必须等人类点头。延伸思考HITL 会不会让AI变慢确实会慢一点但在涉及资金、数据、重要决策的场景下慢一点恰恰是正确的设计。速度和安全需要平衡HITL 就是那个平衡点。