diff --git a/docs/docs/concepts/double_texting.md b/docs/docs/concepts/double_texting.md index 1a197ccf3..6906a9e4d 100644 --- a/docs/docs/concepts/double_texting.md +++ b/docs/docs/concepts/double_texting.md @@ -15,10 +15,12 @@ If you do not want to use LangGraph Platform, we describe the options we have im ![](img/double_texting.png) ## Reject + This is the simplest option, this just rejects any follow up runs and does not allow double texting. See the [how-to guide](../cloud/how-tos/reject_concurrent.md) for configuring the reject double text option. ## Enqueue + This is a relatively simple option which continues the first run until it completes the whole run, then sends the new input as a separate run. See the [how-to guide](../cloud/how-tos/enqueue_concurrent.md) for configuring the enqueue double text option. @@ -35,10 +37,6 @@ See the [how-to guide](../cloud/how-tos/interrupt_concurrent.md) for configuring ## Rollback -This option rolls back all work done up until that point. -It then sends the user input in, basically as if it just followed the original run input. - -This may create some weird states - for example, you may have two `User` messages in a row, with no `Asssitant` message in between them. -You will need to make sure the LLM you are calling can handle that, or combine those into a single `User` message. +This option interrupts the current execution AND rolls back all work done up until that point, including the original run input. It then sends the new user input in, basically as if it was the original input. See the [how-to guide](../cloud/how-tos/rollback_concurrent.md) for configuring the rollback double text option. diff --git a/docs/docs/concepts/img/double_texting.png b/docs/docs/concepts/img/double_texting.png index f2291612c..a16a58ce2 100644 Binary files a/docs/docs/concepts/img/double_texting.png and b/docs/docs/concepts/img/double_texting.png differ diff --git a/libs/checkpoint/pyproject.toml b/libs/checkpoint/pyproject.toml index 09fba4e25..e36b20f16 100644 --- a/libs/checkpoint/pyproject.toml +++ b/libs/checkpoint/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph-checkpoint" -version = "2.0.3" +version = "2.0.4" description = "Library with base interfaces for LangGraph checkpoint savers." authors = [] license = "MIT" diff --git a/libs/langgraph/langgraph/pregel/__init__.py b/libs/langgraph/langgraph/pregel/__init__.py index 48306f842..c8812f1c8 100644 --- a/libs/langgraph/langgraph/pregel/__init__.py +++ b/libs/langgraph/langgraph/pregel/__init__.py @@ -1753,6 +1753,7 @@ class Pregel(PregelProtocol): interrupt_before=interrupt_before_, interrupt_after=interrupt_after_, manager=run_manager, + debug=debug, ) as loop: # create runner runner = PregelRunner( diff --git a/libs/langgraph/langgraph/pregel/io.py b/libs/langgraph/langgraph/pregel/io.py index 7c26731f1..6695e1ce0 100644 --- a/libs/langgraph/langgraph/pregel/io.py +++ b/libs/langgraph/langgraph/pregel/io.py @@ -69,19 +69,11 @@ def map_command( ) -> Iterator[tuple[str, str, Any]]: """Map input chunk to a sequence of pending writes in the form (channel, value).""" if cmd.send: - if isinstance(cmd.send, (tuple, list)) and all( - isinstance(x, Send) - or isinstance(x, (list, tuple)) - and len(x) == 2 - and isinstance(x[0], str) - for x in cmd.send - ): + if isinstance(cmd.send, (tuple, list)): sends = cmd.send else: sends = [cmd.send] for send in sends: - if isinstance(send, tuple) and len(send) == 2 and isinstance(send[0], str): - send = Send(*send) if not isinstance(send, Send): raise TypeError( f"In Command.send, expected Send, got {type(send).__name__}" diff --git a/libs/langgraph/poetry.lock b/libs/langgraph/poetry.lock index db2b60544..d337af2bc 100644 --- a/libs/langgraph/poetry.lock +++ b/libs/langgraph/poetry.lock @@ -1359,7 +1359,7 @@ typing-extensions = ">=4.7" [[package]] name = "langgraph-checkpoint" -version = "2.0.2" +version = "2.0.4" description = "Library with base interfaces for LangGraph checkpoint savers." optional = false python-versions = "^3.9.0,<4.0" @@ -1429,7 +1429,7 @@ url = "../checkpoint-sqlite" [[package]] name = "langgraph-sdk" -version = "0.1.35" +version = "0.1.36" description = "SDK for interacting with LangGraph API" optional = false python-versions = "^3.9.0,<4.0" @@ -3425,4 +3425,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<4.0" -content-hash = "f0b7800f90041227ba4d7b72482c70fabdbacc95e8a3a784fdebc88721728a91" +content-hash = "9bf5668d3f70f3b77457906732404a6401583a5966f70a72ef10a68f2a5b27ad" diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index 00c42fce5..4bdef858a 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph" -version = "0.2.46" +version = "0.2.48" description = "Building stateful, multi-actor applications with LLMs" authors = [] license = "MIT" @@ -10,7 +10,7 @@ repository = "https://www.github.com/langchain-ai/langgraph" [tool.poetry.dependencies] python = ">=3.9.0,<4.0" langchain-core = ">=0.2.43,<0.4.0,!=0.3.0,!=0.3.1,!=0.3.2,!=0.3.3,!=0.3.4,!=0.3.5,!=0.3.6,!=0.3.7,!=0.3.8,!=0.3.9,!=0.3.10,!=0.3.11,!=0.3.12,!=0.3.13,!=0.3.14" -langgraph-checkpoint = "^2.0.0" +langgraph-checkpoint = "^2.0.4" langgraph-sdk = "^0.1.32" [tool.poetry.group.dev.dependencies] diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index a057d452f..6a3bb6c9c 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -36,6 +36,7 @@ from langgraph_sdk.schema import ( AssistantVersion, CancelAction, Checkpoint, + Command, Config, Cron, DisconnectMode, @@ -1174,6 +1175,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, stream_mode: Union[StreamMode, Sequence[StreamMode]] = "values", stream_subgraphs: bool = False, metadata: Optional[dict] = None, @@ -1197,6 +1199,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, stream_mode: Union[StreamMode, Sequence[StreamMode]] = "values", stream_subgraphs: bool = False, metadata: Optional[dict] = None, @@ -1217,6 +1220,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, stream_mode: Union[StreamMode, Sequence[StreamMode]] = "values", stream_subgraphs: bool = False, metadata: Optional[dict] = None, @@ -1241,6 +1245,7 @@ class RunsClient: assistant_id: The assistant ID or graph name to stream from. If using graph name, will default to first assistant created from that graph. input: The input to the graph. + command: A command to execute. Cannot be combined with input. stream_mode: The stream mode(s) to use. stream_subgraphs: Whether to stream output from subgraphs. metadata: Metadata to assign to the run. @@ -1291,6 +1296,7 @@ class RunsClient: """ # noqa: E501 payload = { "input": input, + "command": command, "config": config, "metadata": metadata, "stream_mode": stream_mode, @@ -1324,6 +1330,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, stream_mode: Union[StreamMode, Sequence[StreamMode]] = "values", stream_subgraphs: bool = False, metadata: Optional[dict] = None, @@ -1343,6 +1350,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, stream_mode: Union[StreamMode, Sequence[StreamMode]] = "values", stream_subgraphs: bool = False, metadata: Optional[dict] = None, @@ -1363,6 +1371,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, stream_mode: Union[StreamMode, Sequence[StreamMode]] = "values", stream_subgraphs: bool = False, metadata: Optional[dict] = None, @@ -1385,6 +1394,7 @@ class RunsClient: assistant_id: The assistant ID or graph name to stream from. If using graph name, will default to first assistant created from that graph. input: The input to the graph. + command: A command to execute. Cannot be combined with input. stream_mode: The stream mode(s) to use. stream_subgraphs: Whether to stream output from subgraphs. metadata: Metadata to assign to the run. @@ -1471,6 +1481,7 @@ class RunsClient: """ # noqa: E501 payload = { "input": input, + "command": command, "stream_mode": stream_mode, "stream_subgraphs": stream_subgraphs, "config": config, @@ -1508,6 +1519,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, metadata: Optional[dict] = None, config: Optional[Config] = None, checkpoint: Optional[Checkpoint] = None, @@ -1529,6 +1541,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, metadata: Optional[dict] = None, config: Optional[Config] = None, interrupt_before: Optional[Union[All, Sequence[str]]] = None, @@ -1547,6 +1560,7 @@ class RunsClient: assistant_id: str, *, input: Optional[dict] = None, + command: Optional[Command] = None, metadata: Optional[dict] = None, config: Optional[Config] = None, checkpoint: Optional[Checkpoint] = None, @@ -1569,6 +1583,7 @@ class RunsClient: assistant_id: The assistant ID or graph name to run. If using graph name, will default to first assistant created from that graph. input: The input to the graph. + command: A command to execute. Cannot be combined with input. metadata: Metadata to assign to the run. config: The configuration for the assistant. checkpoint: The checkpoint to resume from. @@ -1635,6 +1650,7 @@ class RunsClient: """ # noqa: E501 payload = { "input": input, + "command": command, "config": config, "metadata": metadata, "assistant_id": assistant_id, diff --git a/libs/sdk-py/langgraph_sdk/schema.py b/libs/sdk-py/langgraph_sdk/schema.py index 9583a1c1b..5264ce709 100644 --- a/libs/sdk-py/langgraph_sdk/schema.py +++ b/libs/sdk-py/langgraph_sdk/schema.py @@ -339,3 +339,14 @@ class StreamPart(NamedTuple): """The type of event for this stream part.""" data: dict """The data payload associated with the event.""" + + +class Send(TypedDict): + node: str + input: Optional[dict[str, Any]] + + +class Command(TypedDict, total=False): + send: Union[Send, Sequence[Send]] + update: dict[str, Any] + resume: Any diff --git a/libs/sdk-py/pyproject.toml b/libs/sdk-py/pyproject.toml index dcd74f43a..393750ba6 100644 --- a/libs/sdk-py/pyproject.toml +++ b/libs/sdk-py/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph-sdk" -version = "0.1.35" +version = "0.1.36" description = "SDK for interacting with LangGraph API" authors = [] license = "MIT"