LangGraphLangGraph 1.2 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
38 small wins to finish your pathNext lesson →

Review and edit an action before it runs

Reviewing and editing is a human-in-the-loop pattern: the graph pauses with a proposed action, and the human resumes with a corrected value that the graph then uses.

Last updated: 27 Sep, 2026 · LangGraph 1.2

The interrupt lesson paused for a yes or no. Often a person wants to change the action, not only approve it, so the value they send back on resume becomes the one the graph uses.

Pausing with a proposed action

The node calls interrupt with the draft it proposes. Whatever the human returns on resume comes back as the value of that call.

python
def review(state):
    approved = interrupt({"proposed": state["draft"]})  # pause, show the draft
    return {"sent": approved}   # use the returned value, edited or not

Resuming with an edited value

Run once to hit the pause, then resume with Command(resume=...) carrying the corrected value. A checkpointer is required so the run can wait.

python
graph.invoke({"draft": "Refund $100", "sent": ""}, cfg)   # stops at the pause
out = graph.invoke(Command(resume="Refund $50"), cfg)     # human edits it
print(out["sent"])

Editing a refund before it is sent

The whole program in one file.

Example
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.types import interrupt, Command
from langgraph.checkpoint.memory import InMemorySaver

class State(TypedDict):
    draft: str
    sent: str

def review(state):
    approved = interrupt({"proposed": state["draft"]})  # pause and show the draft
    return {"sent": approved}                            # use what the human returns

b = StateGraph(State)
b.add_node("review", review)
b.add_edge(START, "review")
b.add_edge("review", END)
graph = b.compile(checkpointer=InMemorySaver())

cfg = {"configurable": {"thread_id": "1"}}
graph.invoke({"draft": "Refund $100", "sent": ""}, cfg)  # runs up to the pause
out = graph.invoke(Command(resume="Refund $50"), cfg)    # human edits, then resume
print(out["sent"])

What the human changed

  • The run paused at interrupt with the proposed draft, "Refund $100".
  • The human resumed with "Refund $50", so interrupt returned that value.
  • The node wrote the edited value to sent, so the graph acted on the correction.

Approve only vs review and edit

Approve or rejectReview and edit
Resume valueTrue or FalseThe corrected value itself
The human canLet it run or stop itChange what runs
Use forA yes or no gateFixing an amount, a recipient, a query

When to let a human edit

  • A money amount, a recipient or a destructive action a person should adjust.
  • A tool call whose arguments a reviewer wants to correct before it runs.
  • A draft reply a human tidies before it is sent.
Watch out. The node must use the returned value, not the original. If it ignores what interrupt returns, the edit is lost and the human's change does nothing.
Try it yourself
  • Resume with the unchanged draft and confirm it sends "Refund $100".
  • Return a dict from the human and read one field of it in the node.
  • Remove the checkpointer and read the error about needing one to pause.

You understood something today that you didn't yesterday.