To review, edit, and approve tool calls in an agent or workflow, use LangGraph’s human-in-the-loop features.

Dynamic interrupts

from langgraph_sdk import get_client
# highlight-next-line
from langgraph_sdk.schema import Command
client = get_client(url=<DEPLOYMENT_URL>)

# Using the graph deployed with the name "agent"
assistant_id = "agent"

# create a thread
thread = await client.threads.create()
thread_id = thread["thread_id"]

# Run the graph until the interrupt is hit.
result = await client.runs.wait(
    thread_id,
    assistant_id,
    input={"some_text": "original text"}   # (1)!
)

print(result['__interrupt__']) # (2)!
# > [
# >     {
# >         'value': {'text_to_revise': 'original text'},
# >         'resumable': True,
# >         'ns': ['human_node:fc722478-2f21-0578-c572-d9fc4dd07c3b'],
# >         'when': 'during'
# >     }
# > ]


# Resume the graph
print(await client.runs.wait(
    thread_id,
    assistant_id,
    # highlight-next-line
    command=Command(resume="Edited text")   # (3)!
))
# > {'some_text': 'Edited text'}
  1. The graph is invoked with some initial state.
  2. When the graph hits the interrupt, it returns an interrupt object with the payload and metadata.
  3. The graph is resumed with a Command(resume=...), injecting the human’s input and continuing execution.

Static interrupts

Static interrupts (also known as static breakpoints) are triggered either before or after a node executes.
Static interrupts are not recommended for human-in-the-loop workflows. They are best used for debugging and testing.
You can set static interrupts by specifying interrupt_before and interrupt_after at compile time:
# highlight-next-line
graph = graph_builder.compile( # (1)!
    # highlight-next-line
    interrupt_before=["node_a"], # (2)!
    # highlight-next-line
    interrupt_after=["node_b", "node_c"], # (3)!
)
  1. The breakpoints are set during compile time.
  2. interrupt_before specifies the nodes where execution should pause before the node is executed.
  3. interrupt_after specifies the nodes where execution should pause after the node is executed.
Alternatively, you can set static interrupts at run time:
# highlight-next-line
await client.runs.wait( # (1)!
    thread_id,
    assistant_id,
    inputs=inputs,
    # highlight-next-line
    interrupt_before=["node_a"], # (2)!
    # highlight-next-line
    interrupt_after=["node_b", "node_c"] # (3)!
)
  1. client.runs.wait is called with the interrupt_before and interrupt_after parameters. This is a run-time configuration and can be changed for every invocation.
  2. interrupt_before specifies the nodes where execution should pause before the node is executed.
  3. interrupt_after specifies the nodes where execution should pause after the node is executed.
The following example shows how to add static interrupts:
from langgraph_sdk import get_client
client = get_client(url=<DEPLOYMENT_URL>)

# Using the graph deployed with the name "agent"
assistant_id = "agent"

# create a thread
thread = await client.threads.create()
thread_id = thread["thread_id"]

# Run the graph until the breakpoint
result = await client.runs.wait(
    thread_id,
    assistant_id,
    input=inputs   # (1)!
)

# Resume the graph
await client.runs.wait(
    thread_id,
    assistant_id,
    input=None   # (2)!
)
  1. The graph is run until the first breakpoint is hit.
  2. The graph is resumed by passing in None for the input. This will run the graph until the next breakpoint is hit.

Learn more