LangChain LangGraph
Module 1 Module 2 Module 3
Module 3 · 中间件与 HITL
1 3.2 Managing Msgs
2 3.3 HITL
3 3.4 Dyn Models
4 3.4 Dyn Prompts
5 3.4 Dyn Tools
6 3.5 Email Agent
SUM Module Summary
HomeLangChainModule 3 · 中间件与 HITL3.3 HITL
📓 Notebook 📖 Explained
LANGCHAIN MODULE 3 · LESSON 3.3

Human-in-the-loop
Approve · Reject · Edit

本节给高风险工具加人工审批:读邮件可以自动执行,发邮件必须暂停等待人类决定,恢复时可以批准、拒绝或编辑工具调用。

1 HITL 解决什么问题

Agent 可以调用工具,但并不是所有工具都应该自动执行。读邮件风险较低,发邮件会产生外部影响,所以更适合加人工审批。

工具是否中断原因
read_email只读取 state 中的邮件内容,不产生外部副作用
send_email会发送邮件,属于需要确认的外部动作
本节核心

Human-in-the-loop 不是让人参与每一步,而是只在高风险动作执行前暂停。

2 定义读邮件和发邮件工具

Notebook 先定义两个工具。read_email 从 state 读邮件原文;send_email 模拟发送邮件。

Python
@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 sent"
state_schema

邮件正文被放在 EmailState.email 中,因此工具可以通过 runtime.state["email"] 读取。

3 配置 HumanInTheLoopMiddleware

HumanInTheLoopMiddleware 的关键配置是 interrupt_on。它精确声明哪些工具调用需要暂停。

Python
from langchain.agents.middleware import HumanInTheLoopMiddleware

class EmailState(AgentState):
    email: str

humanInTheLoopMiddleware = HumanInTheLoopMiddleware(
    interrupt_on={
        "read_email": False,
        "send_email": True,
    },
    description_prefix="Tool execution requires approval",
)

agent = create_agent(
    model=deepseek_model(),
    tools=[read_email, send_email],
    state_schema=EmailState,
    checkpointer=InMemorySaver(),
    middleware=[humanInTheLoopMiddleware],
)
必须有 checkpointer

中断后要用同一个 thread_id 恢复执行,所以 Agent 需要 checkpointer 保存暂停时的状态。

4 触发中断

用户要求“读邮件并立刻回复”。Agent 可以先读邮件,但当它准备调用 send_email 时会返回 __interrupt__,等待人类决策。

Python
config = {"configurable": {"thread_id": "1"}}

message = [HumanMessage(
    content="Please read my email and send a response immediately. Send the reply now in the same thread."
)]

response = agent.invoke(
    {
        "messages": message,
        "email": "Hi Seán, I'm going to be late for our meeting tomorrow. Can we reschedule? Best, John.",
    },
    config=config,
)

print(response)
暂停点

中断发生在工具执行前。此时可以检查模型打算发送的邮件正文,再决定是否允许。

5 三种恢复方式:approve、reject、edit

恢复执行时传入 Command(resume=...)。课程展示了三种决策:批准原工具调用、拒绝并给模型反馈、编辑工具参数后再执行。

Python
from langgraph.types import Command

response = agent.invoke(
    Command(resume={"decisions": [{"type": "approve"}]}),
    config=config,
)

response = agent.invoke(
    Command(resume={
        "decisions": [{
            "type": "reject",
            "message": "No please sign off - Your merciful leader, Seán.",
        }]
    }),
    config=config,
)

response = agent.invoke(
    Command(resume={
        "decisions": [{
            "type": "edit",
            "edited_action": {
                "name": "send_email",
                "args": {"body": "This is the last straw, you're fired!"},
            },
        }]
    }),
    config=config,
)
决策含义
approve按模型原计划执行工具调用
reject不执行工具,并把拒绝原因返回给 Agent
edit修改工具名称或参数后执行

6 本课 takeaway