diff --git a/.github/workflows/size.yml b/.github/workflows/size.yml
new file mode 100644
index 000000000..4d3497508
--- /dev/null
+++ b/.github/workflows/size.yml
@@ -0,0 +1,28 @@
+name: Check File Size
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+ workflow_dispatch:
+
+jobs:
+ file-size-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Get changed files
+ id: changed-files
+ uses: tj-actions/changed-files@v44
+ - name: Filter by size
+ run: |
+ large_added_files=$(find ${{ steps.changed-files.outputs.added_files }} -maxdepth 0 -size +1M)
+ if [ -n "$large_added_files" ]; then
+ echo "Large files added: $large_added_files"
+ echo "# Large files added:" >> $GITHUB_STEP_SUMMARY
+ echo "$large_added_files" >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
diff --git a/docs/docs/cloud/deployment/graph_rebuild.md b/docs/docs/cloud/deployment/graph_rebuild.md
new file mode 100644
index 000000000..c7853b30a
--- /dev/null
+++ b/docs/docs/cloud/deployment/graph_rebuild.md
@@ -0,0 +1,146 @@
+# Rebuild Graph at Runtime
+
+You might need to rebuild your graph with a different configuration for a new run. For example, you might need to use a different graph state or graph structure depending on the config. This guide shows how you can do this.
+
+!!! note "Note"
+ In most cases, customizing behavior based on the config should be handled by a single graph where each node can read a config and change its behavior based on it
+
+## Prerequisites
+
+Make sure to check out [this how-to guide](./setup.md) on setting up your app for deployment first.
+
+## Define graphs
+
+Let's say you have an app with a simple graph that calls an LLM and returns the response to the user. The app file directory looks like the following:
+
+```
+my-app/
+|-- requirements.txt
+|-- .env
+|-- openai_agent.py # code for your graph
+```
+
+where the graph is defined in `openai_agent.py`.
+
+### No rebuild
+
+In the standard LangGraph API configuration, the server uses the compiled graph instance that's defined at the top level of `openai_agent.py`, which looks like the following:
+
+```python
+from langchain_openai import ChatOpenAI
+from langgraph.graph import END, MessageGraph
+
+model = ChatOpenAI(temperature=0)
+
+graph_workflow = MessageGraph()
+
+graph_workflow.add_node("agent", model)
+graph_workflow.add_edge("agent", END)
+graph_workflow.set_entry_point("agent")
+
+agent = graph_workflow.compile()
+```
+
+To make the server aware of your graph, you need to specify a path to the variable that contains the `CompiledStateGraph` instance in your LangGraph API configuration (`langgraph.json`), e.g.:
+
+```
+{
+ "dependencies": ["."],
+ "graphs": {
+ "openai_agent": "./openai_agent.py:agent",
+ },
+ "env": "./.env"
+}
+```
+
+### Rebuild
+
+To make your graph rebuild on each new run with custom configuration, you need to rewrite `openai_agent.py` to instead provide a _function_ that takes a config and returns a graph (or compiled graph) instance. Let's say we want to return our existing graph for user ID '1', and a tool-calling agent for other users. We can modify `openai_agent.py` as follows:
+
+```python
+from typing import Annotated, TypedDict
+from langchain_openai import ChatOpenAI
+from langgraph.graph import END, MessageGraph
+from langgraph.graph.state import StateGraph
+from langgraph.graph.message import add_messages
+from langgraph.prebuilt import ToolNode
+from langchain_core.tools import tool
+from langchain_core.messages import BaseMessage
+from langchain_core.runnables import RunnableConfig
+
+
+class State(TypedDict):
+ messages: Annotated[list[BaseMessage], add_messages]
+
+
+model = ChatOpenAI(temperature=0)
+
+def make_default_graph():
+ """Make a simple LLM agent"""
+ graph_workflow = StateGraph(State)
+ def call_model(state):
+ return {"messages": [model.invoke(state["messages"])]}
+
+ graph_workflow.add_node("agent", call_model)
+ graph_workflow.add_edge("agent", END)
+ graph_workflow.set_entry_point("agent")
+
+ agent = graph_workflow.compile()
+ return agent
+
+
+def make_alternative_graph():
+ """Make a tool-calling agent"""
+
+ @tool
+ def add(a: float, b: float):
+ """Adds two numbers."""
+ return a + b
+
+ tool_node = ToolNode([add])
+ model_with_tools = model.bind_tools([add])
+ def call_model(state):
+ return {"messages": [model_with_tools.invoke(state["messages"])]}
+
+ def should_continue(state: State):
+ if state["messages"][-1].tool_calls:
+ return "tools"
+ else:
+ return END
+
+ graph_workflow = StateGraph(State)
+
+ graph_workflow.add_node("agent", call_model)
+ graph_workflow.add_node("tools", tool_node)
+ graph_workflow.add_edge("tools", "agent")
+ graph_workflow.set_entry_point("agent")
+ graph_workflow.add_conditional_edges("agent", should_continue)
+
+ agent = graph_workflow.compile()
+ return agent
+
+
+# this is the graph making function that will decide which graph to
+# build based on the provided config
+def make_graph(config: RunnableConfig):
+ user_id = config.get("configurable", {}).get("user_id")
+ # route to different graph state / structure based on the user ID
+ if user_id == "1":
+ return make_default_graph()
+ else:
+ return make_alternative_graph()
+```
+
+Finally, you need to specify the path to your graph-making function (`make_graph`) in `langgraph.json`:
+
+```
+{
+ "dependencies": ["."],
+ "graphs": {
+ "openai_agent": "./openai_agent.py:make_graph",
+ },
+ "env": "./.env"
+}
+```
+
+See more info on LangGraph API configuration file [here](../reference/cli.md#configuration-file)
\ No newline at end of file
diff --git a/docs/docs/cloud/deployment/setup.md b/docs/docs/cloud/deployment/setup.md
index 0ab7900d0..1aa7da3f8 100644
--- a/docs/docs/cloud/deployment/setup.md
+++ b/docs/docs/cloud/deployment/setup.md
@@ -88,7 +88,7 @@ agent = graph_workflow.compile()
```
!!! warning "Assign `CompiledGraph` to Variable"
- The build process for LangGraph Cloud requires that the `CompiledGraph` object be assigned to a variable at the top-level of a Python module.
+ The build process for LangGraph Cloud requires that the `CompiledGraph` object be assigned to a variable at the top-level of a Python module (alternatively, you can provide [a function that creates a graph](./graph_rebuild.md)).
Example file directory:
```
diff --git a/docs/docs/cloud/reference/cli.md b/docs/docs/cloud/reference/cli.md
index 5e77ad113..ee481ea20 100644
--- a/docs/docs/cloud/reference/cli.md
+++ b/docs/docs/cloud/reference/cli.md
@@ -13,7 +13,7 @@ The LangGraph CLI requires a JSON configuration file with the following keys:
| Key | Description |
| --- | ----------- |
| `dependencies` | **Required**. Array of dependencies for LangGraph Cloud API server. Dependencies can be one of the following: (1) `"."`, which will look for local Python packages, (2) `pyproject.toml`, `setup.py` or `requirements.txt` in the app directory `"./local_package"`, or (3) a package name. |
-| `graphs` | **Required**. Mapping from graph ID to path where the compiled graph is defined. Example: `./your_package/your_file.py:variable`, where `variable` is an instance of `langgraph.graph.graph.CompiledGraph`. |
+| `graphs` | **Required**. Mapping from graph ID to path where the compiled graph or a function that makes a graph is defined. Example:
- `./your_package/your_file.py:variable`, where `variable` is an instance of `langgraph.graph.state.CompiledStateGraph`
- `./your_package/your_file.py:make_graph`, where `make_graph` is a function that takes a config dictionary (`langchain_core.runnables.RunnableConfig`) and creates an instance of `langgraph.graph.state.StateGraph` / `langgraph.graph.state.CompiledStateGraph`.
|
| `env` | Path to `.env` file or a mapping from environment variable to its value. |
| `python_version` | `3.11` or `3.12`. Defaults to `3.11`. |
| `pip_config_file`| Path to `pip` config file. |
@@ -49,7 +49,7 @@ Example:
"."
],
"graphs": {
- "my_graph_id": "./your_package/your_file.py:variable"
+ "my_graph_id": "./your_package/your_file.py:make_graph"
},
"env": {
"OPENAI_API_KEY": "secret-key"
diff --git a/docs/docs/how-tos/index.md b/docs/docs/how-tos/index.md
index b1783e492..b5cedfc97 100644
--- a/docs/docs/how-tos/index.md
+++ b/docs/docs/how-tos/index.md
@@ -61,6 +61,13 @@ These guides show how to use different streaming modes.
- [How to pass graph state to tools](pass-run-time-values-to-tools.ipynb)
- [How to pass config to tools](pass-config-to-tools.ipynb)
+## State Management
+
+- [Use Pydantic model as state](state-model.ipynb)
+- [Use a context object in state](state-context-key.ipynb)
+- [Have a separate input and output schema](input_output_schema.ipynb)
+- [Pass private state between nodes inside the graph](pass_private_state.ipynb)
+
## Other
- [How to run graph asynchronously](async.ipynb)
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 083661975..a3bfb34e7 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -192,6 +192,7 @@ nav:
- Deployment:
- Setup App: "cloud/deployment/setup.md"
- Setup App (pyproject.toml): "cloud/deployment/setup_pyproject.md"
+ - Rebuild Graph at Runtime: "cloud/deployment/graph_rebuild.md"
- Test App Locally: "cloud/deployment/test_locally.md"
- Deploy to Cloud: "cloud/deployment/cloud.md"
- Self-Host: "cloud/deployment/self_hosted.md"
diff --git a/examples/chatbot-simulation-evaluation/img/virtual_user_diagram.png b/examples/chatbot-simulation-evaluation/img/virtual_user_diagram.png
index a0cefb06b..716257274 100644
Binary files a/examples/chatbot-simulation-evaluation/img/virtual_user_diagram.png and b/examples/chatbot-simulation-evaluation/img/virtual_user_diagram.png differ
diff --git a/examples/chatbots/imgs/prompt-generator.png b/examples/chatbots/imgs/prompt-generator.png
index 6bcc7083f..9f547f2f9 100644
Binary files a/examples/chatbots/imgs/prompt-generator.png and b/examples/chatbots/imgs/prompt-generator.png differ
diff --git a/examples/cloud_examples/img/webhook_results.png b/examples/cloud_examples/img/webhook_results.png
index c0fea310a..c0df3e3e7 100644
Binary files a/examples/cloud_examples/img/webhook_results.png and b/examples/cloud_examples/img/webhook_results.png differ
diff --git a/examples/cloud_examples/langgraph_to_langgraph_cloud.ipynb b/examples/cloud_examples/langgraph_to_langgraph_cloud.ipynb
index 20011991b..41a174f33 100644
--- a/examples/cloud_examples/langgraph_to_langgraph_cloud.ipynb
+++ b/examples/cloud_examples/langgraph_to_langgraph_cloud.ipynb
@@ -50,7 +50,7 @@
"metadata": {},
"outputs": [
{
- "name": "stdin",
+ "name": "stdout",
"output_type": "stream",
"text": [
"OPENAI_API_KEY: ········\n"
@@ -991,7 +991,7 @@
"id": "08996d90-a3ff-4655-9763-1dd4971344d4",
"metadata": {},
"source": [
- "### With LangGraph Clound"
+ "### With LangGraph Cloud"
]
},
{
diff --git a/examples/customer-support/img/customer-support-bot-4.png b/examples/customer-support/img/customer-support-bot-4.png
index 021d8996c..f00a923ec 100644
Binary files a/examples/customer-support/img/customer-support-bot-4.png and b/examples/customer-support/img/customer-support-bot-4.png differ
diff --git a/examples/customer-support/img/part-1-diagram.png b/examples/customer-support/img/part-1-diagram.png
index b7d5e105e..2b4d68013 100644
Binary files a/examples/customer-support/img/part-1-diagram.png and b/examples/customer-support/img/part-1-diagram.png differ
diff --git a/examples/customer-support/img/part-2-diagram.png b/examples/customer-support/img/part-2-diagram.png
index 1659030bc..cf7fbee5d 100644
Binary files a/examples/customer-support/img/part-2-diagram.png and b/examples/customer-support/img/part-2-diagram.png differ
diff --git a/examples/customer-support/img/part-3-diagram.png b/examples/customer-support/img/part-3-diagram.png
index 7b9dbc067..f31ed7730 100644
Binary files a/examples/customer-support/img/part-3-diagram.png and b/examples/customer-support/img/part-3-diagram.png differ
diff --git a/examples/customer-support/img/part-4-diagram.png b/examples/customer-support/img/part-4-diagram.png
index d5d2e2e89..4449e1bb8 100644
Binary files a/examples/customer-support/img/part-4-diagram.png and b/examples/customer-support/img/part-4-diagram.png differ
diff --git a/examples/lats/img/lats.png b/examples/lats/img/lats.png
index 79e96a304..f9a2f6e39 100644
Binary files a/examples/lats/img/lats.png and b/examples/lats/img/lats.png differ
diff --git a/examples/lats/img/tree.png b/examples/lats/img/tree.png
index 6b3dd0c02..ef4b4ddcd 100644
Binary files a/examples/lats/img/tree.png and b/examples/lats/img/tree.png differ
diff --git a/examples/llm-compiler/img/diagram.png b/examples/llm-compiler/img/diagram.png
index 01655a5ec..0bcf9f685 100644
Binary files a/examples/llm-compiler/img/diagram.png and b/examples/llm-compiler/img/diagram.png differ
diff --git a/examples/llm-compiler/img/llm-compiler.png b/examples/llm-compiler/img/llm-compiler.png
index 3c9ec7a57..eb08c72b7 100644
Binary files a/examples/llm-compiler/img/llm-compiler.png and b/examples/llm-compiler/img/llm-compiler.png differ
diff --git a/examples/multi_agent/img/hierarchical-diagram.png b/examples/multi_agent/img/hierarchical-diagram.png
index b3fa81275..48c2eb627 100644
Binary files a/examples/multi_agent/img/hierarchical-diagram.png and b/examples/multi_agent/img/hierarchical-diagram.png differ
diff --git a/examples/multi_agent/img/simple_multi_agent_diagram.png b/examples/multi_agent/img/simple_multi_agent_diagram.png
index 3da47ba9b..b82be5ce9 100644
Binary files a/examples/multi_agent/img/simple_multi_agent_diagram.png and b/examples/multi_agent/img/simple_multi_agent_diagram.png differ
diff --git a/examples/multi_agent/img/supervisor-diagram.png b/examples/multi_agent/img/supervisor-diagram.png
index 84497aa4c..f3e92ba40 100644
Binary files a/examples/multi_agent/img/supervisor-diagram.png and b/examples/multi_agent/img/supervisor-diagram.png differ
diff --git a/examples/plan-and-execute/img/plan-and-execute.png b/examples/plan-and-execute/img/plan-and-execute.png
index 829f2aee8..fc068a8ba 100644
Binary files a/examples/plan-and-execute/img/plan-and-execute.png and b/examples/plan-and-execute/img/plan-and-execute.png differ
diff --git a/examples/reflection/img/reflection.png b/examples/reflection/img/reflection.png
index b3fdc455f..fecdc8734 100644
Binary files a/examples/reflection/img/reflection.png and b/examples/reflection/img/reflection.png differ
diff --git a/examples/reflexion/img/reflexion.png b/examples/reflexion/img/reflexion.png
index 929be2e64..bf319d021 100644
Binary files a/examples/reflexion/img/reflexion.png and b/examples/reflexion/img/reflexion.png differ
diff --git a/examples/rewoo/img/rewoo-paper-workflow.png b/examples/rewoo/img/rewoo-paper-workflow.png
index cdfc7261f..598d694c2 100644
Binary files a/examples/rewoo/img/rewoo-paper-workflow.png and b/examples/rewoo/img/rewoo-paper-workflow.png differ
diff --git a/examples/rewoo/img/rewoo.png b/examples/rewoo/img/rewoo.png
index 48af25d57..af295a3a6 100644
Binary files a/examples/rewoo/img/rewoo.png and b/examples/rewoo/img/rewoo.png differ
diff --git a/examples/storm/img/storm.png b/examples/storm/img/storm.png
index 696592181..bca442f5e 100644
Binary files a/examples/storm/img/storm.png and b/examples/storm/img/storm.png differ
diff --git a/examples/subgraph.ipynb b/examples/subgraph.ipynb
index cbc582165..a2b4bec3a 100644
--- a/examples/subgraph.ipynb
+++ b/examples/subgraph.ipynb
@@ -11,7 +11,7 @@
"source": [
"# How to create subgraphs\n",
"\n",
- "For more complex systems, sub-graphs are a useful design principle. Sub-graphs allow you to create and manage different states in different parts of your graph. This allows you build things like [multi-agent teams](./multi_agent/hierarchical_agent_teams.ipynb), where each team can track its own separate state.\n",
+ "For more complex systems, sub-graphs are a useful design principle. Sub-graphs allow you to create and manage different states in different parts of your graph. This allows you build things like [multi-agent teams](https://langchain-ai.github.io/langgraph/tutorials/multi_agent/hierarchical_agent_teams/), where each team can track its own separate state.\n",
"\n",
""
]
diff --git a/examples/tutorials/tnt-llm/img/tnt_llm.png b/examples/tutorials/tnt-llm/img/tnt_llm.png
index dbe96813e..c452ab789 100644
Binary files a/examples/tutorials/tnt-llm/img/tnt_llm.png and b/examples/tutorials/tnt-llm/img/tnt_llm.png differ
diff --git a/examples/usaco/img/benchmark.png b/examples/usaco/img/benchmark.png
index a6199631a..f0b9169a9 100644
Binary files a/examples/usaco/img/benchmark.png and b/examples/usaco/img/benchmark.png differ
diff --git a/examples/usaco/img/diagram-part-1.png b/examples/usaco/img/diagram-part-1.png
index f002232c6..e2a373479 100644
Binary files a/examples/usaco/img/diagram-part-1.png and b/examples/usaco/img/diagram-part-1.png differ
diff --git a/examples/usaco/img/diagram-part-2.png b/examples/usaco/img/diagram-part-2.png
index 0bb6ca168..54e9e2ac8 100644
Binary files a/examples/usaco/img/diagram-part-2.png and b/examples/usaco/img/diagram-part-2.png differ
diff --git a/examples/usaco/img/diagram.png b/examples/usaco/img/diagram.png
index 125f8cdbe..90091aa88 100644
Binary files a/examples/usaco/img/diagram.png and b/examples/usaco/img/diagram.png differ
diff --git a/examples/usaco/img/usaco.png b/examples/usaco/img/usaco.png
index b15be575e..47dfd393c 100644
Binary files a/examples/usaco/img/usaco.png and b/examples/usaco/img/usaco.png differ
diff --git a/examples/web-navigation/img/web-voyager.excalidraw.png b/examples/web-navigation/img/web-voyager.excalidraw.png
index 54563b056..32fa6555e 100644
Binary files a/examples/web-navigation/img/web-voyager.excalidraw.png and b/examples/web-navigation/img/web-voyager.excalidraw.png differ
diff --git a/libs/langgraph/langgraph/pregel/__init__.py b/libs/langgraph/langgraph/pregel/__init__.py
index c0edcacc3..c990b4dc6 100644
--- a/libs/langgraph/langgraph/pregel/__init__.py
+++ b/libs/langgraph/langgraph/pregel/__init__.py
@@ -722,8 +722,10 @@ class Pregel(
if config and config.get("configurable", {}).get(CONFIG_KEY_READ) is not None:
# if being called as a node in another graph, always use values mode
stream_mode = ["values"]
- if config is not None and config.get("configurable", {}).get(
- CONFIG_KEY_CHECKPOINTER
+ if (
+ config is not None
+ and config.get("configurable", {}).get(CONFIG_KEY_CHECKPOINTER)
+ and (interrupt_after or interrupt_before)
):
checkpointer: Optional[BaseCheckpointSaver] = config["configurable"][
CONFIG_KEY_CHECKPOINTER
diff --git a/libs/langgraph/langgraph/pregel/algo.py b/libs/langgraph/langgraph/pregel/algo.py
index 13ce7e183..d94d4e166 100644
--- a/libs/langgraph/langgraph/pregel/algo.py
+++ b/libs/langgraph/langgraph/pregel/algo.py
@@ -257,6 +257,9 @@ def prepare_next_tasks(
if not isinstance(packet, Send):
logger.warn(f"Ignoring invalid packet type {type(packet)} in pending sends")
continue
+ if packet.node not in processes:
+ logger.warn(f"Ignoring unknown node name {packet.node} in pending sends")
+ continue
if for_execution:
proc = processes[packet.node]
if node := proc.get_node():
diff --git a/libs/langgraph/langgraph/pregel/loop.py b/libs/langgraph/langgraph/pregel/loop.py
index ae2ba2edf..8373a1fba 100644
--- a/libs/langgraph/langgraph/pregel/loop.py
+++ b/libs/langgraph/langgraph/pregel/loop.py
@@ -102,6 +102,7 @@ class PregelLoop:
checkpoint_pending_writes: List[PendingWrite]
step: int
+ stop: int
status: Literal[
"pending", "done", "interrupt_before", "interrupt_after", "out_of_steps"
]
@@ -203,7 +204,7 @@ class PregelLoop:
return False
# check if iteration limit is reached
- if self.step > self.config["recursion_limit"]:
+ if self.step > self.stop:
self.status = "out_of_steps"
return False
@@ -419,6 +420,7 @@ class SyncPregelLoop(PregelLoop, ContextManager):
)
self.status = "pending"
self.step = self.checkpoint_metadata["step"] + 1
+ self.stop = self.step + self.config["recursion_limit"] + 1
return self
@@ -497,6 +499,7 @@ class AsyncPregelLoop(PregelLoop, AsyncContextManager):
)
self.status = "pending"
self.step = self.checkpoint_metadata["step"] + 1
+ self.stop = self.step + self.config["recursion_limit"] + 1
return self
diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml
index a856e7f69..d0246b257 100644
--- a/libs/langgraph/pyproject.toml
+++ b/libs/langgraph/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "langgraph"
-version = "0.1.12"
+version = "0.1.14"
description = "Building stateful, multi-actor applications with LLMs"
authors = []
license = "MIT"
diff --git a/libs/langgraph/tests/memory_assert.py b/libs/langgraph/tests/memory_assert.py
index c0ede2f20..09c9e52af 100644
--- a/libs/langgraph/tests/memory_assert.py
+++ b/libs/langgraph/tests/memory_assert.py
@@ -7,6 +7,7 @@ from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.base import (
Checkpoint,
CheckpointMetadata,
+ CheckpointTuple,
SerializerProtocol,
copy_checkpoint,
)
@@ -119,3 +120,11 @@ class MemorySaverAssertCheckpointMetadata(MemorySaver):
return await asyncio.get_running_loop().run_in_executor(
None, self.put, config, checkpoint, metadata
)
+
+
+class MemorySaverNoPending(MemorySaver):
+ def get_tuple(self, config: RunnableConfig) -> Optional[CheckpointTuple]:
+ result = super().get_tuple(config)
+ if result:
+ return CheckpointTuple(result.config, result.checkpoint, result.metadata)
+ return result
diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py
index db902eca0..2a701f034 100644
--- a/libs/langgraph/tests/test_pregel.py
+++ b/libs/langgraph/tests/test_pregel.py
@@ -66,6 +66,7 @@ from tests.any_str import AnyStr
from tests.memory_assert import (
MemorySaverAssertCheckpointMetadata,
MemorySaverAssertImmutable,
+ MemorySaverNoPending,
NoopSerializer,
)
@@ -1149,10 +1150,32 @@ def test_cond_edge_after_send() -> None:
builder.add_conditional_edges("1", send_for_fun)
builder.add_conditional_edges("2", route_to_three)
graph = builder.compile()
-
assert graph.invoke(["0"]) == ["0", "1", "2", "3"]
+async def test_checkpointer_null_pending_writes() -> None:
+ class Node:
+ def __init__(self, name: str):
+ self.name = name
+ setattr(self, "__name__", name)
+
+ def __call__(self, state):
+ return [self.name]
+
+ builder = StateGraph(Annotated[list, operator.add])
+ builder.add_node(Node("1"))
+ builder.add_edge(START, "1")
+ graph = builder.compile(checkpointer=MemorySaverNoPending())
+ assert graph.invoke([], {"configurable": {"thread_id": "foo"}}) == ["1"]
+ assert graph.invoke([], {"configurable": {"thread_id": "foo"}}) == ["1"] * 2
+ assert (await graph.ainvoke([], {"configurable": {"thread_id": "foo"}})) == [
+ "1"
+ ] * 3
+ assert (await graph.ainvoke([], {"configurable": {"thread_id": "foo"}})) == [
+ "1"
+ ] * 4
+
+
def test_invoke_checkpoint_sqlite(mocker: MockerFixture) -> None:
adder = mocker.Mock(side_effect=lambda x: x["total"] + x["input"])
@@ -8570,6 +8593,7 @@ def test_nested_graph_interrupts_parallel(checkpointer: BaseCheckpointSaver) ->
checkpointer.__exit__(None, None, None)
+@pytest.mark.skip
@pytest.mark.parametrize(
"checkpointer",
[
diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py
index c3f8bb3bf..84d597c43 100644
--- a/libs/langgraph/tests/test_pregel_async.py
+++ b/libs/langgraph/tests/test_pregel_async.py
@@ -7099,6 +7099,7 @@ async def test_nested_graph_interrupts_parallel(
await checkpointer.__aexit__(None, None, None)
+@pytest.mark.skip
@pytest.mark.parametrize(
"checkpointer",
[