Skip to content

人机协同

interrupt 动态中断、Command 恢复、审核审批流。

Updated View as Markdown
For humans

人机协同

Agent 需要人在关键节点把关:转账、发邮件、改代码。LangGraph 的 interrupt 是官方机制:执行到任意位置暂停、等人、带结果恢复。

interrupt 机制

interrupt: 暂停 → 等待 → 恢复

from langgraph.types import Command, interrupt

def approval_node(state):
    decision = interrupt({
        "question": "批准这笔转账?",
        "amount": state["amount"],
    })   # 暂停点: 返回值来自外部 resume
    if decision:
        return Command(goto="transfer")
    return Command(goto="cancel")
  • interrupt(payload):暂停图执行,payload(JSON 可序列化)暴露给调用方
  • 恢复:用 Command(resume=值) 重新调用图,该值成为 interrupt() 的返回值
  • 动态:可在任意代码位置、按条件触发,不同于静态断点(固定节点前后)

审批流实现

config = {"configurable": {"thread_id": "tx-42"}}

# 第一次运行: 执行到 interrupt 暂停
result = graph.invoke({"amount": 10000}, config=config)
pending = result["__interrupt__"]   # 拿到待审批信息
# > (Interrupt(value={'question': '批准这笔转账?', ...}),)

# 人工审批后恢复: 带 True/False
graph.invoke(Command(resume=True), config=config)   # 批准, 走 transfer

关键点:

  • checkpoint 是前提:中断时状态已落盘(见持久化篇),恢复时从暂停点继续
  • thread_id 是会话指针:审批系统保存 thread_id,用户确认后用它恢复
  • interrupt 前别写副作用:恢复会从节点开头重跑,中断前的外部写入会重复执行

典型场景

场景 中断点
转账/支付 执行支付工具前
发邮件/消息 调用 send 工具前(工具内 interrupt)
代码生成 写文件前人工确认
数据删除 破坏性操作前

工具内 interrupt 的写法(在 @tool 函数里调用 interrupt):

@tool
def send_email(to: str, subject: str, body: str):
    """发送邮件"""
    decision = interrupt({"action": "send_email", "to": to,
                          "subject": subject, "body": body})
    if decision.get("action") == "approve":
        return "已发送"
    return "已取消"

与 LangChain 生态的关系

  • DeepAgents 内置 HITL:批准/编辑/拒绝工具调用(approve/edit/reject),底层就是 interrupt
  • LangSmith 提供人工审批界面(Agent 交互式界面),thread_id 对接

面试追问

  1. interrupt 怎么工作? 代码任意位置暂停,payload 暴露给外部;Command(resume) 恢复,resume 值成为 interrupt 的返回值
  2. 审批流怎么实现? 工具/节点里 interrupt → 保存 thread_id → 人工审批 → Command(resume=True/False) 恢复走不同分支
  3. 静态断点和 interrupt 的区别? 静态断点编译时固定位置;interrupt 动态、可在工具内、按条件触发
  4. 中断前要注意什么? 别写外部副作用:恢复会重跑节点开头,中断前的写入会重复(不是幂等的)
  5. interrupt 依赖什么? checkpoint:中断时状态落盘,恢复才能从暂停点继续
Navigation

Type to search…

↑↓ navigate↵ selectEsc close