interrupt: pause for a human
interrupt() pauses a run to ask a person, and Command(resume=value) continues it with their answer. It needs a checkpointer so the paused run can be saved.
Last updated: 27 Sep, 2026 · LangGraph 1.2
Some actions are too costly to leave to a model, such as a refund or a delete. The safe pattern stops, asks a human, and only then goes on.
The interrupt and Command API
from langgraph.types import interrupt, Command
def approval(state):
decision = interrupt("Approve the refund?") # pauses here
return {"status": "approved" if decision else "rejected"}
# later, resume with the human's answer:
graph.invoke(Command(resume=True), config)The example pauses at a refund, waits for a yes, and then finishes. Build it in five small steps.
The imports
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import interrupt, CommandTwo names do the work here: interrupt pauses the run, and Command carries the human's answer back in. InMemorySaver is the checkpointer that saves the paused run.
The state
class State(TypedDict):
status: str # holds "approved" or "rejected"The state holds one field, status. It starts empty and ends as the human's decision.
The approval node
def approval(state):
decision = interrupt("Approve the refund?") # pauses here and asks
return {"status": "approved" if decision else "rejected"} # runs after the answer comes backinterrupt("Approve the refund?")stops the run at this line and hands the question out to you.- When you resume,
decisionbecomes the value you sent back. - The node then sets
statusto "approved" for a truthy answer, else "rejected".
Building the graph
builder = StateGraph(State)
builder.add_node("approval", approval)
builder.add_edge(START, "approval")
builder.add_edge("approval", END)
graph = builder.compile(checkpointer=InMemorySaver()) # checkpointer saves the paused runThe graph runs START -> approval -> END. Compiling with a checkpointer is what lets the paused run be saved and picked up again.
Pausing and resuming
cfg = {"configurable": {"thread_id": "1"}}
first = graph.invoke({"status": ""}, cfg) # runs until interrupt, then stops
print("__interrupt__" in first) # True: the run paused
final = graph.invoke(Command(resume=True), cfg) # resume with a yes
print(final["status"]) # approved- The first
invokeruns up tointerrupt()and stops, returning a result that contains an__interrupt__marker, so the first print isTrue. - The second
invokesendsCommand(resume=True), the node continues withdecisionset toTrue, andstatusbecomesapproved.
Pause and resume end to end
The five steps in one file.
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import interrupt, Command
class State(TypedDict):
status: str
def approval(state):
decision = interrupt("Approve the refund?")
return {"status": "approved" if decision else "rejected"}
builder = StateGraph(State)
builder.add_node("approval", approval)
builder.add_edge(START, "approval")
builder.add_edge("approval", END)
graph = builder.compile(checkpointer=InMemorySaver())
cfg = {"configurable": {"thread_id": "1"}}
first = graph.invoke({"status": ""}, cfg)
print("__interrupt__" in first)
final = graph.invoke(Command(resume=True), cfg)
print(final["status"])Why it paused then approved
- The first
invokeran untilinterrupt(), then stopped and returned an__interrupt__marker instead of finishing. - The second
invokepassedCommand(resume=True), which restarted the node and returned "approved". - This only works because the graph was compiled with a checkpointer that saved the paused state.
When to pause for a human
- Approving anything irreversible: a payment, a delete, an email to a customer.
- Letting a person edit or correct the agent before it continues.
interrupt() runs again. Keep side effects below it, and never wrap interrupt() in a bare try/except.Related
- Previous: Trimming and removing messages
- Next: Review and edit an action before it runs
- Reference: Interrupts
- Resume with
Command(resume=False)and read the status. - Add a
printaboveinterrupt()and count how many times it runs across the two invokes.
Little by little, you're building something great.