Human-in-the-loop interrupts

RoadmapsAI Engineering

Scenario

A developer puts a standard Python `input("Approve this action?")` command in their AI agent to ask the user for permission. They deploy it to a cloud server.

What happens when the agent reaches this line in production?

Mental model

An interrupt is not a pause button; it's a save-and-quit button.

When you pause a video game, the console stays on and burns electricity. When you interrupt an agent, it saves the game and unplugs the console entirely. When the human finally returns to approve the action (even days later), the console plugs back in, loads the save, and continues.

Deep dive

Agents that execute destructive actions (like dropping a database, spending money, or sending emails) need **human-in-the-loop (HITL)** approval gates. We cannot trust the AI to make the final call on dangerous operations.

Dangerous agent actions require explicit human approval before execution.

You cannot use `input()` or `time.sleep()` to pause an agent. If you do, the server process stays alive waiting for an answer. In the cloud (like AWS Lambda), this will hit a timeout limit in 30 seconds, crash, and lose all memory of what the agent was doing.

Standard code pauses cause cloud timeouts and destroy agent state.

Instead, production frameworks use **interrupts**. An `interrupt()` suspends the graph and uses a checkpointer to save the state to a database. The server process then shuts down completely. Hours or days later, an external API call resumes the graph, injecting the human's response.

Interrupts save state to a database and shut down the process while waiting.

Prediction: A developer puts `send_email()` and then `interrupt()` inside the *same* agent node. The graph pauses. A day later, the human approves. The agent resumes... and sends the email again. Why? Because when a node resumes from an interrupt, the framework restarts that specific node from the top. Non-idempotent actions must be in separate nodes.

When an interrupted node resumes, all code before the interrupt re-executes.

Code examples

Safely interrupting and resuming an agent

from langgraph.types import interrupt, Command

def approval_node(state):
    # 1. The graph suspends here, saves state, and dies cleanly.
    user_decision = interrupt("Do you approve this $500 purchase?")
    
    if user_decision == "yes":
        return {"next_node": "buy_item"}
    return {"next_node": "cancel"}

# --- DAYS LATER, in a different file/server request ---

# 2. The human clicked 'Yes' in a UI. We resume the graph.
# The 'resume' value is injected directly into 'user_decision' above.
graph.invoke(
    Command(resume="yes"), 
    config={"configurable": {"thread_id": "123"}}
)

This is a durable pause. The server does not hang while waiting for the human. It completely stops. Later, `Command(resume=...)` wakes the graph back up and passes the human's answer exactly where the code left off.

Common mistakes

Glossary

human-in-the-loop (HITL)
A system design where an AI must pause and ask a human for permission before taking a dangerous action.
interrupt
A specific command that suspends the agent graph, saves its state, and cleanly shuts down the server process while waiting.

Recall questions

Questions & answers

Design an approval flow for an agent that drops a SQL table. How do you prevent the table from dropping while waiting for approval, without causing a server timeout?

Use a durable interrupt framework. The agent reaches an approval node, calls `interrupt()`, and halts. The state is saved to a checkpointer. A separate UI system alerts a human. Upon approval, the UI makes a new API call with `resume=True`, which loads the state and allows the graph to proceed to the actual execution node.

Approach: Demonstrate the difference between a blocking thread pause and a durable, stateless checkpoint interrupt.

Why can't you achieve human-in-the-loop by simply placing a `time.sleep()` or `input()` block inside a cloud-hosted agent?

Blocking the execution thread will cause the cloud function (e.g., AWS Lambda) to hit its timeout limit and terminate forcefully, resulting in the complete loss of the agent's in-memory state.

Approach: Highlight the difference between local blocking scripts and stateless, durable cloud architectures.

Continue learning

Previous: Agent checkpointing & resumability

Next: Agent Evals: Trajectory vs Outcome Scoring

Return to AI Engineering Roadmap