Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(langgraph): Add interrupt schema to library #2947

Merged
merged 7 commits into from
Jan 15, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions libs/langgraph/langgraph/prebuilt/interrupt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from typing import (

Check notice on line 1 in libs/langgraph/langgraph/prebuilt/interrupt.py

View workflow job for this annotation

GitHub Actions / benchmark

Benchmark results

......................................... fanout_to_subgraph_10x: Mean +- std dev: 61.4 ms +- 1.4 ms ......................................... fanout_to_subgraph_10x_sync: Mean +- std dev: 53.4 ms +- 0.7 ms ......................................... fanout_to_subgraph_10x_checkpoint: Mean +- std dev: 74.5 ms +- 1.2 ms ......................................... fanout_to_subgraph_10x_checkpoint_sync: Mean +- std dev: 96.1 ms +- 2.3 ms ......................................... fanout_to_subgraph_100x: Mean +- std dev: 616 ms +- 27 ms ......................................... fanout_to_subgraph_100x_sync: Mean +- std dev: 518 ms +- 11 ms ......................................... fanout_to_subgraph_100x_checkpoint: Mean +- std dev: 770 ms +- 16 ms ......................................... fanout_to_subgraph_100x_checkpoint_sync: Mean +- std dev: 966 ms +- 18 ms ......................................... react_agent_10x: Mean +- std dev: 30.8 ms +- 0.7 ms ......................................... react_agent_10x_sync: Mean +- std dev: 23.0 ms +- 0.3 ms ......................................... react_agent_10x_checkpoint: Mean +- std dev: 38.2 ms +- 0.9 ms ......................................... react_agent_10x_checkpoint_sync: Mean +- std dev: 36.8 ms +- 0.4 ms ......................................... react_agent_100x: Mean +- std dev: 344 ms +- 6 ms ......................................... react_agent_100x_sync: Mean +- std dev: 274 ms +- 2 ms ......................................... react_agent_100x_checkpoint: Mean +- std dev: 644 ms +- 8 ms ......................................... react_agent_100x_checkpoint_sync: Mean +- std dev: 627 ms +- 7 ms ......................................... wide_state_25x300: Mean +- std dev: 23.3 ms +- 0.5 ms ......................................... wide_state_25x300_sync: Mean +- std dev: 15.3 ms +- 0.1 ms ......................................... wide_state_25x300_checkpoint: Mean +- std dev: 249 ms +- 13 ms ......................................... wide_state_25x300_checkpoint_sync: Mean +- std dev: 246 ms +- 13 ms ......................................... wide_state_15x600: Mean +- std dev: 27.3 ms +- 0.6 ms ......................................... wide_state_15x600_sync: Mean +- std dev: 17.8 ms +- 0.2 ms ......................................... wide_state_15x600_checkpoint: Mean +- std dev: 430 ms +- 14 ms ......................................... wide_state_15x600_checkpoint_sync: Mean +- std dev: 426 ms +- 13 ms ......................................... wide_state_9x1200: Mean +- std dev: 27.3 ms +- 0.6 ms ......................................... wide_state_9x1200_sync: Mean +- std dev: 17.8 ms +- 0.2 ms ......................................... wide_state_9x1200_checkpoint: Mean +- std dev: 280 ms +- 14 ms ......................................... wide_state_9x1200_checkpoint_sync: Mean +- std dev: 276 ms +- 13 ms

Check notice on line 1 in libs/langgraph/langgraph/prebuilt/interrupt.py

View workflow job for this annotation

GitHub Actions / benchmark

Comparison against main

+-----------------------------------------+---------+-----------------------+ | Benchmark | main | changes | +=========================================+=========+=======================+ | wide_state_9x1200_checkpoint | 294 ms | 280 ms: 1.05x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_checkpoint | 258 ms | 249 ms: 1.04x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_sync | 18.4 ms | 17.8 ms: 1.04x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_sync | 15.8 ms | 15.3 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300 | 24.0 ms | 23.3 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600 | 28.1 ms | 27.3 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_sync | 18.3 ms | 17.8 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_checkpoint_sync | 284 ms | 276 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200 | 28.0 ms | 27.3 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300_checkpoint_sync | 253 ms | 246 ms: 1.03x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_checkpoint | 437 ms | 430 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_sync | 527 ms | 518 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_checkpoint_sync | 431 ms | 426 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x_checkpoint | 75.3 ms | 74.5 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint_sync | 633 ms | 627 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint_sync | 973 ms | 966 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_10x | 61.7 ms | 61.4 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_sync | 22.8 ms | 23.0 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint_sync | 36.3 ms | 36.8 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_sync | 270 ms | 274 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x | 339 ms | 344 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | Geometric mean | (ref) | 1.01x faster | +-----------------------------------------+---------+-----------------------+ Benchmark hidden because not significant (7): fanout_to_subgraph_10x_sync, fanout_to_subgraph_100x_checkpoint, react_agent_10x_checkpoint, fanout_to_subgraph_10x_checkpoint_sync, react_agent_100x_checkpoint, fanout_to_subgraph_100x, react_agent_10x
Literal,
Optional,
Union,
bracesproul marked this conversation as resolved.
Show resolved Hide resolved
)

from typing_extensions import TypedDict


class HumanInterruptConfig(TypedDict):
"""Configuration that defines what actions are allowed for a human interrupt.

This controls the available interaction options when the graph is paused for human input.

Attributes:
allow_ignore: Whether the human can choose to ignore/skip the current step
allow_respond: Whether the human can provide a text response/feedback
allow_edit: Whether the human can edit the provided content/state
allow_accept: Whether the human can accept/approve the current state
"""

allow_ignore: bool
allow_respond: bool
allow_edit: bool
bracesproul marked this conversation as resolved.
Show resolved Hide resolved
allow_accept: bool


class ActionRequest(TypedDict):
"""Represents a request for human action within the graph execution.

Contains the action type and any associated arguments needed for the action.

Attributes:
action: The type or name of action being requested (e.g., "Approve XYZ action")
args: Key-value pairs of arguments needed for the action
"""

action: str
args: dict
bracesproul marked this conversation as resolved.
Show resolved Hide resolved


class HumanInterrupt(TypedDict):
bracesproul marked this conversation as resolved.
Show resolved Hide resolved
"""Represents an interrupt triggered by the graph that requires human intervention.

This is passed to the `interrupt` function when execution is paused for human input.

Attributes:
action_request: The specific action being requested from the human
config: Configuration defining what actions are allowed
description: Optional detailed description of what input is needed

Example:
```python
# Extract a tool call from the state and create an interrupt request
request = HumanInterrupt(
action_request=ActionRequest(
action="run_command", # The action being requested
args={"command": "ls", "args": ["-l"]} # Arguments for the action
),
config=HumanInterruptConfig(
allow_ignore=True, # Allow skipping this step
allow_respond=True, # Allow text feedback
allow_edit=False, # Don't allow editing
allow_accept=True # Allow direct acceptance
),
description="Please review the command before execution"
)
# Send the interrupt request and get the response
response = interrupt([request])[0]
```
"""

action_request: ActionRequest
config: HumanInterruptConfig
description: Optional[str]


class HumanResponse(TypedDict):
"""The response provided by a human to an interrupt, which is returned when graph execution resumes.

Attributes:
type: The type of response:
- "accept": Approves the current state without changes
bracesproul marked this conversation as resolved.
Show resolved Hide resolved
- "ignore": Skips/ignores the current step
bracesproul marked this conversation as resolved.
Show resolved Hide resolved
- "response": Provides text feedback or instructions
- "edit": Modifies the current state/content
arg: The response payload:
- None: For ignore/accept actions
- str: For text responses
- ActionRequest: For edit actions with updated content
"""

type: Literal["accept", "ignore", "response", "edit"]
args: Union[None, str, ActionRequest]
Loading