Skip to main content
Some tool operations may be sensitive and require human approval before execution. Deep Agents support human-in-the-loop workflows through LangGraph’s interrupt capabilities. You can configure which tools require approval using the interrupt_on parameter. When interrupt_on is set, HumanInTheLoopMiddleware is added to the Deep Agents stack. If a run is cancelled or interrupted before a tool returns a result, PatchToolCallsMiddleware in the same stack repairs the message history automatically.

Basic configuration

The interrupt_on parameter accepts a dictionary mapping tool names to interrupt configurations. Each tool can be configured with:
  • True: Enable interrupts with default behavior (approve, edit, and reject allowed)
  • False: Disable interrupts for this tool
  • InterruptOnConfig: Custom configuration. Set allowed_decisions to control review options.

Decision types

The allowed_decisions list controls what actions a human can take when reviewing a tool call: Use reject when the human denies a proposed action.
When editing tool arguments, make changes conservatively. Significant modifications to the original arguments may cause the model to re-evaluate its approach and potentially execute the tool multiple times or take unexpected actions.
You can customize which decisions are available for each tool:

Handle interrupts

When an interrupt is triggered, the agent pauses execution and returns control. Check for interrupts in the result and handle them accordingly. If the user rejects an action, include a clear message that tells the agent the tool was not executed and what to do next.

Handle interrupts with streaming

For real-time UIs, use .stream() instead of .invoke() to display tokens and tool call progress while handling HITL interrupts. Interrupts appear as __interrupt__ entries in the updates stream. After the stream completes, collect human decisions and resume by streaming again with Command(resume=...).
For a typical interrupt_on HITL pause, resume with a flat {"decisions": [...]} payload, the same shape as with .invoke(). When multiple interrupts are pending at once (for example, parallel branches), map each interrupt ID to its resume value instead. See Handling multiple interrupts.
Combine "messages" and "updates" stream modes to show real-time LLM tokens to the user while still catching HITL interrupts. The "messages" mode streams tokens; the "updates" mode delivers interrupt payloads.

Multiple tool calls

When the agent calls multiple tools that require approval, all interrupts are batched together in a single interrupt. You must provide decisions for each one in order.

Rejection messages

When a reviewer returns a reject decision, Deep Agents skip the tool call and send rejection feedback back to the agent. If you omit message, the default feedback tells the model that the tool was not executed and not to retry the same tool call unless the user asks. For sensitive or side-effecting tools, pass a domain-specific message with the decision. Be explicit about whether the agent should abandon the action, ask a follow-up question, or try a safer alternative.

Edit tool arguments

When "edit" is in the allowed decisions, you can modify the tool arguments before execution:

Subagent interrupts

When using subagents, you can use interrupts on tool calls and within tool calls.

Interrupts on tool calls

Each subagent can have its own interrupt_on configuration that overrides the main agent’s settings:
When a subagent triggers an interrupt, the handling is the same—check for __interrupt__ on the result and resume with Command. When streaming, subagent interrupts also surface as __interrupt__ entries in the parent updates stream. You do not need subgraphs=True for interrupt delivery. Enable subgraphs=True if you also want to stream subagent tokens and progress events. See Handle interrupts with streaming for the full pattern.

Interrupts within tool calls

Subagent tools can call interrupt() directly to pause execution and await approval:
When run, this produces the following output: