人在回路(HITL)中间件让您可以向智能体工具调用添加人工监督。 当模型提出可能需要审查的操作时(例如,写入文件或执行 SQL),中间件可以暂停执行并等待决策。 它通过根据可配置策略检查每个工具调用来实现这一点。如果需要干预,中间件会发出 interrupt,暂停执行。图状态使用 LangGraph 的持久层保存,因此执行可以安全暂停并稍后恢复。 然后,人工决策决定接下来会发生什么:可以原样批准操作(approve)、运行前修改(edit)或拒绝并提供反馈(reject)。

中断决策类型

中间件定义了三种内置方式,人类可以响应中断:
决策类型描述示例用例
approve操作按原样批准并执行,不做任何更改。完全按照编写的内容发送电子邮件草稿
✏️ edit工具调用在修改后执行。在发送电子邮件之前更改收件人
reject工具调用被拒绝,并将解释添加到对话中。拒绝电子邮件草稿并解释如何重写
每个工具的可用决策类型取决于您在 interrupt_on 中配置的策略。 当多个工具调用同时暂停时,每个操作都需要单独的决策。 必须按照操作在中断请求中出现的顺序提供决策。
编辑工具参数时,请谨慎进行更改。对原始参数的重大修改可能会导致模型重新评估其方法,并可能多次执行工具或采取意外操作。

配置中断

要使用 HITL,在创建智能体时将中间件添加到智能体的 middleware 列表中。 您使用工具操作到每个操作允许的决策类型的映射来配置它。当工具调用与映射中的操作匹配时,中间件将中断执行。
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware 
from langgraph.checkpoint.memory import InMemorySaver 


agent = create_agent(
    model="gpt-4o",
    tools=[write_file_tool, execute_sql_tool, read_data_tool],
    middleware=[
        HumanInTheLoopMiddleware( 
            interrupt_on={
                "write_file": True,  # All decisions (approve, edit, reject) allowed
                "execute_sql": {"allowed_decisions": ["approve", "reject"]},  # No editing allowed
                # Safe operation, no approval needed
                "read_data": False,
            },
            # Prefix for interrupt messages - combined with tool name and args to form the full message
            # e.g., "Tool execution pending approval: execute_sql with query='DELETE FROM...'"
            # Individual tools can override this by specifying a "description" in their interrupt config
            description_prefix="Tool execution pending approval",
        ),
    ],
    # Human-in-the-loop requires checkpointing to handle interrupts.
    # In production, use a persistent checkpointer like AsyncPostgresSaver.
    checkpointer=InMemorySaver(),  
)
您必须配置检查点器以在中断之间持久化图状态。 在生产环境中,使用持久化检查点器,如 AsyncPostgresSaver。对于测试或原型设计,使用 InMemorySaver调用智能体时,传递包含 线程 IDconfig,以将执行与会话线程关联。 有关详细信息,请参阅 LangGraph 中断文档

响应中断

当您调用智能体时,它会运行直到完成或引发中断。当工具调用与您在 interrupt_on 中配置的策略匹配时,会触发中断。在这种情况下,调用结果将包含一个 __interrupt__ 字段,其中包含需要审查的操作。然后,您可以将这些操作呈现给审查者,并在提供决策后恢复执行。
from langgraph.types import Command

# Human-in-the-loop leverages LangGraph's persistence layer.
# You must provide a thread ID to associate the execution with a conversation thread,
# so the conversation can be paused and resumed (as is needed for human review).
config = {"configurable": {"thread_id": "some_id"}} 
# Run the graph until the interrupt is hit.
result = agent.invoke(
    {
        "messages": [
            {
                "role": "user",
                "content": "Delete old records from the database",
            }
        ]
    },
    config=config 
)

# The interrupt contains the full HITL request with action_requests and review_configs
print(result['__interrupt__'])
# > [
# >    Interrupt(
# >       value={
# >          'action_requests': [
# >             {
# >                'name': 'execute_sql',
# >                'arguments': {'query': 'DELETE FROM records WHERE created_at < NOW() - INTERVAL \'30 days\';'},
# >                'description': 'Tool execution pending approval\n\nTool: execute_sql\nArgs: {...}'
# >             }
# >          ],
# >          'review_configs': [
# >             {
# >                'action_name': 'execute_sql',
# >                'allowed_decisions': ['approve', 'reject']
# >             }
# >          ]
# >       }
# >    )
# > ]


# Resume with approval decision
agent.invoke(
    Command( 
        resume={"decisions": [{"type": "approve"}]}  # or "edit", "reject"
    ), 
    config=config # Same thread ID to resume the paused conversation
)

决策类型

  • ✅ approve
  • ✏️ edit
  • ❌ reject
使用 approve 按原样批准工具调用并在不做任何更改的情况下执行它。
agent.invoke(
    Command(
        # Decisions are provided as a list, one per action under review.
        # The order of decisions must match the order of actions
        # listed in the `__interrupt__` request.
        resume={
            "decisions": [
                {
                    "type": "approve",
                }
            ]
        }
    ),
    config=config  # Same thread ID to resume the paused conversation
)

执行生命周期

中间件定义了一个 after_model 钩子,该钩子在模型生成响应之后但在执行任何工具调用之前运行:
  1. 智能体调用模型以生成响应。
  2. 中间件检查响应中的工具调用。
  3. 如果任何调用需要人工输入,中间件会构建一个包含 action_requestsreview_configsHITLRequest 并调用 interrupt
  4. 智能体等待人工决策。
  5. 根据 HITLResponse 决策,中间件执行已批准或已编辑的调用,为被拒绝的调用合成 ToolMessage,并恢复执行。

自定义 HITL 逻辑

对于更专业的工作流程,您可以直接使用 interrupt 原语和中间件抽象构建自定义 HITL 逻辑。 查看上面的执行生命周期以了解如何将中断集成到智能体的操作中。
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.