Not every action an agent takes should run unsupervised. LangGraph lets you pause a graph at any node, wait for human approval, and resume exactly where it left off.
An agent that sends emails to customers, executes transfers, modifies records in an ERP, or generates public announcements shouldn't have full autonomy from day one in production, no matter how well it behaved in testing. The human-in-the-loop pattern isn't a temporary limitation while "the model improves" — it's a permanent governance control for high-impact actions, exactly like a dual-signature approval process in a traditional financial system.
LangGraph provides the `interrupt()` function, which pauses graph execution inside a node, persists the state via the configured checkpointer, and returns control to the process that invoked the graph:
When `interrupt()` runs, the graph stops completely at that point. The `app.invoke()` call that triggered it returns with an interrupt-type object instead of the final result, signaling that human input is needed to continue.
Execution resumes with a `Command` object, passing the same original `thread_id` so the checkpointer can recover the exact state where it paused:
Note that the second `invoke()` doesn't repeat the original input: LangGraph rebuilds the state from the checkpoint and continues from the exact point of interruption, without re-running the previous nodes.
For cases where the pause point is always the same node (for example, always before running a tool that writes to an external system), you can declare it at compile time instead of inside the node's logic:
This automatically pauses before `execute_transfer` runs, without needing an explicit call to `interrupt()` inside that function — useful when the control point is structural and doesn't depend on a condition evaluated at runtime.
A frequent case isn't just approve or reject, but the human correcting a parameter before continuing — for example, adjusting the amount of the transfer proposed by the agent. This is solved by updating the state directly via the checkpointer before resuming:
`update_state()` modifies the persisted checkpoint without running any node, which lets the human approval interface also be an editing interface, not just a binary yes/no button.
In real deployments, the approval flow lives outside the agent's process: a backend that exposes pending interrupts (querying `app.get_state(config)` to list paused threads) and an interface — admin panel, Slack channel, ticket — where a human operator reviews the full context before deciding. The architecture recommendation is to never couple this wait's timeout to the agent's process: the checkpointer persists state indefinitely until someone resumes it, so an approval can take minutes or days without the system losing context or consuming compute resources while it waits.
Carlos Montiel is an enterprise AI solutions architect. He implements LLMs, Agents, RAG, and orchestrators for companies across Guatemala and Latin America. Reach out for a consultation.
Contact Carlos Montiel