interrupt() and Command({ resume })
Your todoist bridge is half-manual for one reason: destructive actions (close, graduate) are held in a needs-review.md file because nothing can safely gate them. This module makes those actions pause the graph and wait for your decision. The gap that keeps the bridge from being autonomous closes here.
interrupt() pauses a running graph and hands control back to the caller. Inside a node you call it with a payload; the graph stops, surfaces that payload, and waits. You resume by invoking again with a Command({ resume }).
import { interrupt, Command } from "@langchain/langgraph";
const approveNode = (state) => {
const answer = interrupt({
action: "close",
taskId: state.taskId,
title: state.title,
});
// execution suspends HERE. `answer` is filled in on resume.
if (answer === "approve") return { decision: "close" };
return { decision: "skip" };
};const result = await graph.invoke(inputs, config);
if (result.__interrupt__) {
// show result.__interrupt__ payload to the human, get a decision
await graph.invoke(new Command({ resume: "approve" }), config);
}Try it yourself
Why interrupt needs a checkpointer
Answer by walking what happens at resume time, not only at the moment of the pause.
What breaks if you call interrupt() on a graph with no checkpointer?
Reveal answer
With no checkpointer, there is nowhere to persist the graph's state at the moment of the pause. When you later try to resume with Command({resume}), there's no saved snapshot to resume into -- the pause would effectively lose all context and you couldn't continue from where you left off; you'd have to start over.