πŸ€– AI Tools
Β· 4 min read

Human-in-the-Loop Patterns for AI Agents (2026)


Fully autonomous AI agents sound great in demos. In production, they’re terrifying. An agent that can deploy code, send emails, or modify databases without human approval is one hallucination away from a disaster.

Human-in-the-loop (HITL) patterns give you the best of both worlds: agents handle routine work autonomously, but pause for human approval on high-stakes actions. The trick is knowing where to draw the line.

The autonomy spectrum

Full manual ◄──────────────────────────────► Full autonomous
     β”‚           β”‚           β”‚           β”‚
  Human does   Human       Human       Human
  everything   approves    monitors    reviews
               every       alerts      after
               action      only        the fact

Most production agents should sit in the middle: autonomous for low-risk actions, approval-required for high-risk ones.

Pattern 1: Approval gates

Block specific actions until a human approves:

HIGH_RISK_TOOLS = {"deploy", "delete_file", "send_email", "modify_database", "create_pr"}

async def execute_with_approval(tool_name, args, user_id):
    if tool_name in HIGH_RISK_TOOLS:
        # Request approval
        approval_id = await create_approval_request(
            user_id=user_id,
            action=tool_name,
            details=args,
        )
        # Notify via Slack/email
        await notify_user(user_id, f"Agent wants to: {tool_name}\nDetails: {json.dumps(args, indent=2)}\nApprove: /approve {approval_id}")
        
        # Wait for approval (with timeout)
        approved = await wait_for_approval(approval_id, timeout=3600)
        if not approved:
            return {"error": "Action not approved", "action": tool_name}
    
    # Execute the action
    return await tools[tool_name](**args)

The OpenAI Agents SDK has built-in human-in-the-loop support. Claude Code implements this natively β€” it asks for permission before running shell commands or modifying files.

Pattern 2: Confidence thresholds

Let the agent self-assess. High-confidence actions proceed automatically; low-confidence ones pause for review:

async def run_with_confidence_check(agent, message):
    # First pass: get the action plan
    plan = await Runner.run(planning_agent, f"""
        For this request: {message}
        What actions would you take?
        Rate your confidence (0-100) for each action.
        Format: ACTION | CONFIDENCE | REASON
    """)
    
    actions = parse_plan(plan.final_output)
    
    for action in actions:
        if action.confidence >= 90:
            await execute(action)  # Auto-approve
        elif action.confidence >= 60:
            await execute_with_approval(action)  # Human approval
        else:
            await escalate_to_human(action)  # Human takes over

This works well for coding agents where formatting changes are high-confidence but architectural decisions are low-confidence.

Pattern 3: Escalation flows

When the agent gets stuck or encounters something unexpected, escalate to a human:

ESCALATION_TRIGGERS = [
    "I'm not sure how to proceed",
    "This could have unintended consequences",
    "I need access to",
    "I don't have enough context",
]

async def check_for_escalation(agent_response: str) -> bool:
    return any(trigger in agent_response.lower() for trigger in ESCALATION_TRIGGERS)

async def agent_loop(agent, message, user_id):
    result = await Runner.run(agent, message)
    
    if await check_for_escalation(result.final_output):
        await notify_user(user_id, 
            f"Agent needs help:\n{result.final_output}\n\nReply with guidance or take over.")
        human_input = await wait_for_human_input(user_id, timeout=7200)
        if human_input:
            result = await Runner.run(agent, human_input, session=result.session)
    
    return result

Pattern 4: Review after the fact

For lower-risk actions, let the agent proceed but flag everything for human review:

async def execute_and_log(tool_name, args, result):
    review_item = {
        "tool": tool_name,
        "args": args,
        "result": str(result)[:500],
        "timestamp": datetime.utcnow().isoformat(),
        "reviewed": False,
    }
    await db.insert("agent_review_queue", review_item)
    
    # Daily digest of agent actions
    # Reviewed by human each morning

This is how our AI Startup Race works β€” agents act autonomously, but every action is logged and reviewable on the dashboard.

Pattern 5: Staged rollout

New agent capabilities start with full approval, then graduate to autonomous:

CAPABILITY_STAGES = {
    "read_file": "autonomous",      # Proven safe
    "write_file": "autonomous",     # Proven safe
    "run_tests": "autonomous",      # Proven safe
    "create_pr": "approval",        # Still validating
    "deploy": "approval",           # Always requires approval
    "delete_branch": "disabled",    # Not ready yet
}

Promote capabilities from disabled β†’ approval β†’ autonomous as you build confidence. Demote back to approval if issues arise.

Implementing in different frameworks

OpenAI Agents SDK

The SDK has native HITL support:

from agents import Agent, Runner

agent = Agent(
    name="Deploy Agent",
    instructions="Help deploy applications. Always ask for confirmation before deploying.",
    human_in_the_loop=True,  # Pauses for approval on tool calls
)

Claude Code

Claude Code asks for permission by default. You can configure auto-approve patterns in .claude/settings.json:

{
  "permissions": {
    "allow": ["read_file", "search", "list_directory"],
    "ask": ["write_file", "shell_command"],
    "deny": ["delete_file"]
  }
}

Gemini CLI

Gemini CLI subagents can have restricted tool access per-agent, which is an implicit form of HITL β€” the agent simply can’t perform actions you haven’t authorized.

Choosing the right pattern

ScenarioPatternWhy
Deploying to productionApproval gateToo risky for auto
Code formattingAutonomousLow risk, high volume
Sending customer emailsApproval gateReputation risk
Reading log filesAutonomousRead-only, no risk
Database migrationsApproval gate + reviewIrreversible
Creating GitHub issuesConfidence thresholdUsually fine, sometimes wrong
Deleting resourcesAlways approvalIrreversible

The rule of thumb: if the action is reversible and low-impact, automate it. If it’s irreversible or high-impact, require approval.

Related: AI Agent Security Β· When NOT to Use AI Agents Β· Agent vs Workflow Β· How to Debug AI Agents Β· Test AI Agents Before Production Β· AI Agent Error Handling Β· Claude Code Routines