LangGraph · eight nodes · interrupt before anything sends

Back-office Agent

Eight nodes, one interrupt(). 10 of 10 scenarios pass, and a rejection never reaches send.

status public · gate testedrole designed + built end to end
interactive · click and scroll itlive
The eight-node graph drawn from the code, all ten eval scenarios with their verdicts, and one real run parked at interrupt() with the approve-and-resume leg beside it.
8 nodeswith conditional routing off a classification. Four terminals, and every send path passes awaiting_approval first.
10 of 10scenarios pass in the committed eval run, the agent's full output recorded per row. interrupt()parks the graph at awaiting_approval with the draft prepared and nothing sent.
0 replaysapproval resumes from the checkpoint instead of re-running the task, and a rejection routes back to drafting.
What it solves

Approval implemented as an instruction is a request the model can route around. As a graph node it is a place execution physically stops, and the checkpointer means stopping costs nothing: the work already done survives until a person decides.

Who it serves

Anyone automating correspondence where the wrong send is expensive.

Who it is for

Teams who want the pause to be structural rather than polite.

How it works
  1. Classify the taskReply needed, calendar, spam, or urgent escalation. Routing branches on the answer instead of one path handling everything.
  2. Fetch contextPulls grounded context for the draft, injectable so the graph can be tested without depending on the retrieval service.
  3. Draft, then stopinterrupt() at awaiting_approval. The draft exists, nothing has been sent, and the graph is parked in a checkpoint.
  4. Resume or rejectApproval resumes from the checkpoint to sent. Rejection routes back to drafting and never reaches send.
Built with
TypeScript LangGraph MemorySaver checkpointer Anthropic promptfoo