How to Configure the interrupt_on Parameter in DeepAgents for Human-in-the-Loop Workflows

To configure custom human-approval workflows, supply a dictionary mapping tool names to boolean values or InterruptOnConfig objects via the interrupt_on parameter in create_deep_agent or individual subagent definitions, and ensure you configure a checkpointer such as MemorySaver.

The interrupt_on parameter in the langchain-ai/deepagents repository enables Human-in-the-Loop (HITL) workflows by specifying which tool calls require human approval before execution. This middleware configuration automatically injects HumanInTheLoopMiddleware into the agent graph, creating interrupt points that pause execution until a reviewer provides a decision. You can define these interrupts at the top-level agent configuration or override them for specific subagents to create granular approval workflows.

Understanding the interrupt_on Parameter

The interrupt_on parameter accepts a mapping where keys are tool names and values indicate whether to pause for human review. According to the source code in libs/deepagents/deepagents/middleware/subagents.py (lines 74-76), the type signature is dict[str, bool | InterruptOnConfig], allowing either simple boolean flags or detailed configuration objects.

When a tool call triggers an interrupt, the middleware records an entry in the agent's state under the interrupts field. This payload contains:

  • action_requests – A list of pending tool calls awaiting approval
  • review_configs – Per-action configuration specifying allowed reviewer decisions

Prerequisites for Human-in-the-Loop Workflows

Before configuring interrupt_on, you must satisfy two critical requirements:

  1. Checkpoint Saver: The HumanInTheLoopMiddleware requires a checkpointer to persist interrupt state. Use MemorySaver or any compatible checkpoint store when initializing your agent.
  2. Automatic Middleware Injection: You do not manually add HumanInTheLoopMiddleware. The framework automatically inserts it via SubAgentMiddleware and create_deep_agent when interrupt_on is present (as implemented in libs/deepagents/deepagents/middleware/subagents.py, lines 353-355).

Configuration Methods

You can configure interrupts at three levels of granularity, each overriding the previous when specified.

Top-Level Agent Configuration

Define default interrupt behavior for all tools used by the main agent and default-generated subagents by passing interrupt_on to create_deep_agent in libs/deepagents/deepagents/graph.py (lines 180-284):

from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver
from tests.utils import sample_tool, get_weather

# Top-level interrupt configuration

interrupt_cfg = {
    "sample_tool": True,                         # always ask before running

    "get_weather": {"allowed_decisions": ["approve", "reject"]},
}

agent = create_deep_agent(
    model="gpt-4o-mini",
    tools=[sample_tool, get_weather],
    interrupt_on=interrupt_cfg,          # ← key parameter

    checkpointer=MemorySaver(),          # required for HITL

)

Per-Subagent Overrides

Override top-level settings for specific subagents by including interrupt_on in the subagent definition dictionary. In libs/deepagents/deepagents/middleware/subagents.py (line 652), the framework extracts this configuration and creates a dedicated HumanInTheLoopMiddleware for that subagent (line 654):

from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver
from tests.utils import sample_tool, get_weather, get_soccer_scores

agent = create_deep_agent(
    model="claude-sonnet-4-20250514",
    tools=[sample_tool, get_weather, get_soccer_scores],
    interrupt_on={                     # default for the main agent

        "sample_tool": True,
        "get_weather": False,
    },
    checkpointer=MemorySaver(),
    subagents=[
        {
            "name": "task_handler",
            "description": "Handles complex tasks",
            "system_prompt": "You are a task handler.",
            "tools": [sample_tool, get_weather, get_soccer_scores],
            # Sub-agent overrides: sample_tool disabled, others require approval

            "interrupt_on": {
                "sample_tool": False,
                "get_weather": True,
                "get_soccer_scores": True,
            },
        }
    ],
)

Advanced Configuration with InterruptOnConfig

For fine-grained control over available reviewer decisions, use the InterruptOnConfig class instead of boolean values. This allows you to restrict the human reviewer to specific actions such as approve, edit, or reject:

from deepagents import create_deep_agent, InterruptOnConfig
from langgraph.checkpoint.memory import MemorySaver
from tests.utils import sample_tool, get_soccer_scores

# Custom config allowing only "approve" or "reject"

soccer_cfg = InterruptOnConfig(allowed_decisions=["approve", "reject"])

agent = create_deep_agent(
    model="gpt-4o",
    tools=[sample_tool, get_soccer_scores],
    interrupt_on={"sample_tool": True, "get_soccer_scores": soccer_cfg},
    checkpointer=MemorySaver(),
)

Resuming Execution After Human Review

When the agent interrupts, execution pauses until you send a Command with resume instructions. The test file libs/deepagents/tests/evals/test_hitl.py (lines 78-80) demonstrates this pattern:

from langgraph.types import Command

# After the agent pauses, the UI (or API) sends a resume command:

resume_cmd = Command(
    resume={"decisions": [
        {"type": "approve"},   # for sample_tool

        {"type": "approve"},   # for get_soccer_scores

    ]}
)

result = agent.invoke(resume_cmd, config={"configurable": {"thread_id": thread_id}})

The result contains the tool messages generated after the approvals are processed.

Summary

  • Configure interrupt_on as a dictionary mapping tool names to True, False, or InterruptOnConfig objects to enable human approval workflows.
  • Set at the top level in create_deep_agent for default behavior across all tools and subagents, or override per-subagent for specific approval requirements.
  • Always include a checkpointer such as MemorySaver; the HumanInTheLoopMiddleware requires checkpointing to store interrupt state.
  • Resume interrupted workflows by sending a Command(resume={"decisions": [...]}) containing the reviewer's choices for each pending action.
  • Reference implementation details in libs/deepagents/deepagents/middleware/subagents.py (lines 74-76, 353-355, 652-654) and libs/deepagents/deepagents/graph.py.

Frequently Asked Questions

What happens if I don't provide a checkpointer with interrupt_on?

The HumanInTheLoopMiddleware will fail to function correctly because it relies on checkpointing to persist the interrupt state between steps. Always pass a checkpointer such as MemorySaver to create_deep_agent when using interrupt_on.

Can I use interrupt_on with multiple subagents simultaneously?

Yes. You can define different interrupt_on configurations for each subagent in the subagents list parameter. According to libs/deepagents/deepagents/middleware/subagents.py (line 652), the framework extracts per-subagent configurations and creates individual middleware instances for each (line 654), allowing granular control over which tools require approval in different agent contexts.

How do I restrict the human reviewer to only specific decisions?

Instead of setting a tool's value to True, pass an InterruptOnConfig object with the allowed_decisions parameter set to a list of permitted actions (e.g., ["approve", "reject"] or ["approve", "edit", "reject"]). This configuration appears in the review_configs field of the interrupt state.

Do I need to manually add HumanInTheLoopMiddleware to my graph?

No. When you provide the interrupt_on parameter to create_deep_agent or a subagent definition, the framework automatically injects HumanInTheLoopMiddleware via SubAgentMiddleware (as implemented in libs/deepagents/deepagents/middleware/subagents.py, lines 353-355). Manual middleware insertion is unnecessary and may cause conflicts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →