mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-22 15:42:25 +02:00
This PR does a few things:
1. Surfaces interrupts when `stream_mode='values'` (particularly
relevant for `invoke`, where this is the default behavior)
2. Adds an `interrupt_id` property to the `Interrupt` dataclass so that
interrupts can effectively be mapped to resumes
3. Minor docs updates to reflect the new pattern (no need for a special
section on interrupts with `invoke` and `ainvoke`)
* In a different PR (the one with the multiple resume values), as it's
more relevant there: add an `interrupts` property to `StateSnapshot` so
that `interrupts` can easily be iterated over if users are attempting to
map interrupts to resumes.
I **don't** recommend we release this until we have multi-resumes
working.
## Example
We have the following setup where we're sending multiple prompts to the
child graph, which uses `interrupt`:
```py
def child_graph(state):
human_input = interrupt(state["prompt"])
return {
"human_inputs": [human_input],
}
```
<img width="142" alt="Screenshot 2025-04-23 at 10 01 12 AM"
src="https://github.com/user-attachments/assets/c6238bf1-54ad-4e48-ab0b-60a0bfc18485"
/>
Old behavior:
```py
initial_input = {"prompts": ["a", "b"]}
print(parent_graph.invoke(input=initial_input,config=thread_config,stream_mode="values"))
#> {'prompts': ['a', 'b'], 'human_inputs': []}
print(parent_graph.invoke(Command(resume="hello 1"),config=thread_config,stream_mode="values"))
#> {'prompts': ['a', 'b'], 'human_inputs': ['hello 1']}
print(parent_graph.invoke(Command(resume="hello 2"),config=thread_config,stream_mode="values"))
#> {'prompts': ['a', 'b'], 'human_inputs': ['hello 1', 'hello 2']}
```
New behavior:
```py
initial_input = {"prompts": ["a", "b"]}
print(parent_graph.invoke(input=initial_input,config=thread_config,stream_mode="values"))
"""
{
"prompts": ["a", "b"],
"human_inputs": [],
"__interrupt__": [
Interrupt(
value="a",
resumable=True,
ns=["child_graph:38d43a18-a5e7-8ab2-ca83-9d80f6e9ca83"]
),
Interrupt(
value="b",
resumable=True,
ns=["child_graph:dad810e8-738e-9f90-41cd-30c0091eb79b"]
)
]
}
"""
print(parent_graph.invoke(Command(resume="hello 1"),config=thread_config,stream_mode="values"))
"""
{
"prompts": ["a", "b"],
"human_inputs": ["hello 1"],
"__interrupt__": [
Interrupt(
value="b",
resumable=True,
ns=["child_graph:dad810e8-738e-9f90-41cd-30c0091eb79b"]
)
]
}
"""
print(parent_graph.invoke(Command(resume="hello 2"),config=thread_config,stream_mode="values"))
#> {'prompts': ['a', 'b'], 'human_inputs': ['hello 1', 'hello 2']}
```