Files
langgraph/libs
Sydney RunkleandGitHub 4eb124e83d [breaking]: Improve interrupt behavior when stream_mode='values' (#4374)
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']}
```
2025-04-24 08:21:28 -07:00
..
2025-04-23 07:48:01 -07:00
2025-04-22 17:24:54 -07:00
2025-03-24 09:03:23 -07:00