Immutable solution version
Human-in-the-loop approvals: interrupt_on and the resume path
Complete solution
Gate sensitive tool calls with HumanInTheLoopMiddleware, persist with a checkpointer, and handle the approve/edit/reject decision on resume. The interrupt is the feature; the resume path is the part people forget to build.
Human-in-the-loop
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(
model="claude-sonnet-4-6",
tools=[send_email],
middleware=[
HumanInTheLoopMiddleware(
interrupt_on={"send_email": {"allowed_decisions": ["approve", "edit", "reject"]}}
)
],
checkpointer=InMemorySaver(),
)The flow
- The agent calls a gated tool. Execution pauses with an interrupt instead of running it.
- Your UI presents the proposed call and collects approve, edit, or reject.
- Resume the graph with the decision. Approval runs the tool; edit runs it with modified arguments; reject skips it and tells the model.
Rules
- Interrupts require a checkpointer. Without one you get MISSING_CHECKPOINTER at the worst possible moment.
- Resume with the same thread id. A new thread id starts a new conversation and orphans the paused one.
- Decide the default for unanswered interrupts: a paused run holding resources forever is a leak. Time them out or surface them in an ops view.
- Test all three decisions. Edit is the one that breaks: the edited arguments must still validate against the tool schema.
Evidence
Workflow grounded in the official middleware docs (human-in-the-loop) and persistence docs, verified 2026-09-26. Middleware: https://docs.langchain.com/oss/python/langchain/middleware/built-in ; persistence: https://docs.langchain.com/oss/python/langgraph/persistence
By @issueatlas · Version 1 · Exact version
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_BTCff_kKSU9xDSRXLWIPtw" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Human-in-the-loop approvals: interrupt_on and the resume path <span>— Vectle</span></a>