HumanInTheLoopMiddleware.
When To Use
Use HITL when a tool call can have side effects or needs human judgment:- Sending emails, messages, tickets, or notifications.
- Writing files, updating databases, or changing records.
- Running SQL, scripts, shell commands, or browser actions.
- Calling paid APIs or external systems.
- Any action where rejection or argument editing should be possible before execution.
How It Works
- The model returns one or more tool calls.
- The middleware runs after the model and checks the latest AI message.
- Tool calls configured in
interruptOnare grouped into a single review request. - Unconfigured tool calls are auto-approved.
- The human returns one decision per interrupted tool call.
- Approved and edited calls stay pending so the graph can execute them.
- Rejected calls receive synthetic error
ToolMessages. If every pending call is rejected, the middleware jumps back to the model so it can respond to the rejection.
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
interruptOn | Record<string, boolean | InterruptOnConfig> | none | Mapping from tool name to review behavior. If omitted, the middleware does nothing. Tools without an entry are auto-approved. |
descriptionPrefix | string | Tool execution requires approval | Prefix used to build the human-facing review description when a tool does not provide a custom description. |
interruptOn Values
| Value | Behavior |
|---|---|
true | Pause for review and allow approve, edit, and reject. |
false | Auto-approve the tool call. This is equivalent to not listing the tool. |
InterruptOnConfig | Customize allowed decisions, description, and optional edit schema. |
InterruptOnConfig
| Field | Type | Description |
|---|---|---|
allowedDecisions | ("approve" | "edit" | "reject")[] | Decisions allowed for this tool. |
description | string or function | Optional custom description shown to the reviewer. If absent, the middleware uses descriptionPrefix, tool name, and JSON arguments. |
argsSchema | Record<string, any> | Optional JSON schema for edited arguments when edit is allowed. |
Decision Types
| Decision | Result |
|---|---|
approve | Keeps the original tool name and arguments. The tool executes normally. |
edit | Replaces the tool name and arguments with the reviewed editedAction, preserving the original tool-call ID. |
reject | Creates an error tool message. The model receives the rejection message and can decide what to do next. |
Example
Review Payload
The middleware sends a HITL request with:actionRequests: tool names, arguments, and descriptions for the reviewer.reviewConfigs: allowed decisions and optional argument schema for each action.
decisions array with the same length as the interrupted tool calls. A mismatch is treated as an error.
Runtime Overrides
At runtime, middleware options are merged withruntime.context. This allows advanced integrations to provide or override interruptOn policy for a specific run without changing the saved middleware node.
Best Practices
- Configure HITL only for tools that need review. Unconfigured tools are auto-approved.
- Use
editfor high-value actions where the reviewer should correct arguments instead of restarting the conversation. - Provide concise custom descriptions for risky tools.
- Use
argsSchemawhen edited arguments must follow a strict shape. - Combine with Browser Automation or sandbox tools to review risky actions before they reach the user’s environment.
Troubleshooting
- No review prompt appears: Confirm
interruptOnis configured and the tool name matches the actual tool call name. - The tool runs without approval: Tools missing from
interruptOnare auto-approved. - Edit fails: The edited action must include a string
nameand objectargs. - Reject does not end the run: Rejection is returned to the model as an error tool message; the model may choose a safer follow-up response.