Compare commits

..
Author SHA1 Message Date
Tat Dat Duong 5b45bbc1ba feat(sdk): bump to 0.0.46 2025-02-25 18:28:22 +01:00
22 changed files with 54 additions and 281 deletions
+4 -7
View File
@@ -2,13 +2,13 @@
packages:
- name: "trustcall"
repo: "hinthornw/trustcall"
description: "Tenacious tool calling built on LangGraph."
description: "Tenacious tool calling built on LangGraph"
- name: "breeze-agent"
repo: "andrestorres123/breeze-agent"
description: "A streamlined research system built inspired on STORM and built on LangGraph."
description: "A streamlined research system built inspired on STORM and built on LangGraph"
- name: "langgraph-supervisor"
repo: "langchain-ai/langgraph-supervisor-py"
description: "Build supervisor multi-agent systems with LangGraph."
repo: "langchain-ai/langgraph-supervisor"
description: "Build supervisor multi-agent systems with LangGraph"
- name: "langmem"
repo: "langchain-ai/langmem"
description: "Build agents that learn and adapt from interactions over time."
@@ -18,6 +18,3 @@ packages:
- name: "open-deep-research"
repo: "langchain-ai/open_deep_research"
description: "Open source assistant for iterative web research and report writing."
- name: "langgraph-swarm"
repo: "langchain-ai/langgraph-swarm-py"
description: "Build swarm-style multi-agent systems using LangGraph."
-1
View File
@@ -9,7 +9,6 @@ This list of companies using LangGraph and their success stories is compiled fro
| [AppFolio](https://www.appfolio.com/) | Real Estate | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-appfolio/) |
| [Athena Intelligence](https://www.athenaintel.com/) | Software & Technology (GenAI Native) | Research & summarization | [Case study, 2024](https://blog.langchain.dev/customers-athena-intelligence/) |
| [Captide](https://www.captide.co/) | Software & Technology (GenAI Native) | Data extraction | [Case study, 2025](https://blog.langchain.dev/how-captide-is-redefining-equity-research-with-agentic-workflows-built-on-langgraph-and-langsmith/) |
| [Cisco Outshift](https://outshift.cisco.com/) | Software & Technology | DevOps | [Blog post, 2025](https://outshift.cisco.com/blog/build-react-agent-application-for-devops-tasks-using-rest-apis) |
| [Elastic](https://www.elastic.co/) | Software & Technology | Copilot for domain-specific task | [Blog post, 2025](https://www.elastic.co/blog/elastic-security-generative-ai-features) |
| [GitLab](https://about.gitlab.com/) | Software & Technology | Code generation | [Duo workflow docs](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/duo_workflow/) |
| [Infor](https://infor.com/) | Software & Technology | GenAI embedded product experiences; customer support; copilot | [Case study, 2025](https://blog.langchain.dev/customers-infor/) |
-6
View File
@@ -2,12 +2,6 @@
The LangGraph Cloud Server supports specific environment variables for configuring a deployment.
## `DD_API_KEY`
Specify `DD_API_KEY` (your [Datadog API Key](https://docs.datadoghq.com/account_management/api-app-keys/)) to automatically enable Datadog tracing for the deployment. Specify other [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) to configure the tracing instrumentation.
If `DD_API_KEY` is specified, the application process is wrapped in the [`ddtrace-run` command](https://ddtrace.readthedocs.io/en/stable/installation_quickstart.html). Other `DD_*` environment variables (e.g. `DD_SITE`, `DD_ENV`, `DD_SERVICE`, `DD_TRACE_ENABLED`) are typically needed to properly configure the tracing instrumentation. See [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) for more details.
## `LANGCHAIN_TRACING_SAMPLING_RATE`
Sampling rate for traces sent to LangSmith. Valid values: Any float between `0` and `1`.
-6
View File
@@ -62,9 +62,3 @@ Yes! You can use LangGraph with any LLMs. The main reason we use LLMs that suppo
## Does LangGraph work with OSS LLMs?
Yes! LangGraph is totally ambivalent to what LLMs are used under the hood. The main reason we use closed LLMs in most of the tutorials is that they seamlessly support tool calling, while OSS LLMs often don't. But tool calling is not necessary (see [this section](#does-langgraph-work-with-llms-that-dont-support-tool-calling)) so you can totally use LangGraph with OSS LLMs.
## Can I use LangGraph Studio without logging to LangSmith
Yes! You can use the [development version of LangGraph Server](../tutorials/langgraph-platform/local-server.md) to run the backend locally.
This will connect to the studio frontend hosted as part of LangSmith.
If you set an environment variable of `LANGSMITH_TRACING=false` then no traces will be sent to LangSmith.
+1 -1
View File
@@ -71,7 +71,7 @@ If you navigate to `localhost:2024/hello` in your browser (2024 is the default d
## Deploying
You can deploy this app as-is to the managed langgraph cloud or to your self-hosted platform.
You can deploy this app as-is to the managed langgraph cloud or to your self-hsoted platform.
## Next steps
+28 -25
View File
@@ -169,15 +169,15 @@ files = [
[[package]]
name = "anthropic"
version = "0.47.2"
version = "0.45.2"
description = "The official Python library for the anthropic API"
optional = false
python-versions = ">=3.8"
groups = ["test"]
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
files = [
{file = "anthropic-0.47.2-py3-none-any.whl", hash = "sha256:61b712a56308fce69f04d92ba0230ab2bc187b5bce17811d400843a8976bb67f"},
{file = "anthropic-0.47.2.tar.gz", hash = "sha256:452f4ca0c56ffab8b6ce9928bf8470650f88106a7001b250895eb65c54cfa44c"},
{file = "anthropic-0.45.2-py3-none-any.whl", hash = "sha256:ecd746f7274451dfcb7e1180571ead624c7e1195d1d46cb7c70143d2aedb4d35"},
{file = "anthropic-0.45.2.tar.gz", hash = "sha256:32a18b9ecd12c91b2be4cae6ca2ab46a06937b5aa01b21308d97a6d29794fb5e"},
]
[package.dependencies]
@@ -1299,7 +1299,7 @@ version = "0.7.1"
description = "XML bomb protection for Python stdlib modules"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
groups = ["docs"]
groups = ["docs", "test"]
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
files = [
{file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
@@ -3288,20 +3288,21 @@ together = ["langchain-together"]
[[package]]
name = "langchain-anthropic"
version = "0.3.8"
version = "0.2.4"
description = "An integration package connecting AnthropicMessages and LangChain"
optional = false
python-versions = "<4.0,>=3.9"
groups = ["test"]
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
files = [
{file = "langchain_anthropic-0.3.8-py3-none-any.whl", hash = "sha256:05a70f51500d3c4e0f3e463730e193a25b6244e06b3bda3d7b2ec21d83d081ae"},
{file = "langchain_anthropic-0.3.8.tar.gz", hash = "sha256:1932977b8105744739ffdcb39861b041b73ae93846d0896a775fcea9a29e4b2b"},
{file = "langchain_anthropic-0.2.4-py3-none-any.whl", hash = "sha256:bcb6c2d0df4a67aff52816621079d6e743b260911caccf313a72b33b7edece6f"},
{file = "langchain_anthropic-0.2.4.tar.gz", hash = "sha256:0382d4c7b5236839b703f7b72b3e06de4bb5be99104b193f719adbe34c49562b"},
]
[package.dependencies]
anthropic = ">=0.47.0,<1"
langchain-core = ">=0.3.39,<1.0.0"
anthropic = ">=0.30.0,<1"
defusedxml = ">=0.7.1,<0.8.0"
langchain-core = ">=0.3.15,<0.4.0"
pydantic = ">=2.7.4,<3.0.0"
[[package]]
@@ -3356,15 +3357,15 @@ tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10"
[[package]]
name = "langchain-core"
version = "0.3.40"
version = "0.3.34"
description = "Building applications with LLMs through composability"
optional = false
python-versions = "<4.0,>=3.9"
groups = ["docs", "test"]
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
files = [
{file = "langchain_core-0.3.40-py3-none-any.whl", hash = "sha256:9f31358741f10a13db8531e8288b8a5ae91904018c5c2e6f739d6645a98fca03"},
{file = "langchain_core-0.3.40.tar.gz", hash = "sha256:893a238b38491967c804662c1ec7c3e6ebaf223d1125331249c3cf3862ff2746"},
{file = "langchain_core-0.3.34-py3-none-any.whl", hash = "sha256:a057ebeddd2158d3be14bde341b25640ddf958b6989bd6e47160396f5a8202ae"},
{file = "langchain_core-0.3.34.tar.gz", hash = "sha256:26504cf1e8e6c310adad907b890d4e3c147581cfa7434114f6dc1134fe4bc6d3"},
]
[package.dependencies]
@@ -3473,19 +3474,19 @@ ollama = ">=0.4.4,<1"
[[package]]
name = "langchain-openai"
version = "0.3.7"
version = "0.3.4"
description = "An integration package connecting OpenAI and LangChain"
optional = false
python-versions = "<4.0,>=3.9"
groups = ["test"]
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
files = [
{file = "langchain_openai-0.3.7-py3-none-any.whl", hash = "sha256:0aefc7bdf8e7398d41e09c4313cace816df6438f2aa93d34f79523487310f0da"},
{file = "langchain_openai-0.3.7.tar.gz", hash = "sha256:b8b51a3aaa1cc3bda060651ea41145f7728219e8a7150b5404fb1e8446de9cef"},
{file = "langchain_openai-0.3.4-py3-none-any.whl", hash = "sha256:58d0c014620eb92f4f46ff9daf584c2a7794896b1379eb85ad7be8d9f3493b61"},
{file = "langchain_openai-0.3.4.tar.gz", hash = "sha256:c6645745a1d1bf19f21ea6fa473a746bd464053ff57ce563215e6165a0c4b9f1"},
]
[package.dependencies]
langchain-core = ">=0.3.39,<1.0.0"
langchain-core = ">=0.3.34,<1.0.0"
openai = ">=1.58.1,<2.0.0"
tiktoken = ">=0.7,<1"
@@ -3507,7 +3508,7 @@ langchain-core = ">=0.3.34,<1.0.0"
[[package]]
name = "langgraph"
version = "0.2.74"
version = "0.2.71"
description = "Building stateful, multi-actor applications with LLMs"
optional = false
python-versions = ">=3.9.0,<4.0"
@@ -3527,7 +3528,7 @@ url = "../libs/langgraph"
[[package]]
name = "langgraph-checkpoint"
version = "2.0.16"
version = "2.0.13"
description = "Library with base interfaces for LangGraph checkpoint savers."
optional = false
python-versions = "^3.9.0,<4.0"
@@ -3565,7 +3566,7 @@ pymongo = ">=4.9.0,<4.10.0"
[[package]]
name = "langgraph-checkpoint-postgres"
version = "2.0.15"
version = "2.0.14"
description = "Library with a Postgres implementation of LangGraph checkpoint saver."
optional = false
python-versions = "^3.9.0,<4.0"
@@ -3575,7 +3576,7 @@ files = []
develop = true
[package.dependencies]
langgraph-checkpoint = "^2.0.15"
langgraph-checkpoint = "^2.0.10"
orjson = ">=3.10.1"
psycopg = "^3.2.0"
psycopg-pool = "^3.2.0"
@@ -3586,7 +3587,7 @@ url = "../libs/checkpoint-postgres"
[[package]]
name = "langgraph-checkpoint-sqlite"
version = "2.0.5"
version = "2.0.4"
description = "Library with a SQLite implementation of LangGraph checkpoint saver."
optional = false
python-versions = "^3.9.0"
@@ -3596,8 +3597,8 @@ files = []
develop = true
[package.dependencies]
aiosqlite = ">=0.20,<0.22"
langgraph-checkpoint = "^2.0.15"
aiosqlite = "^0.20.0"
langgraph-checkpoint = "^2.0.10"
[package.source]
type = "directory"
@@ -3605,7 +3606,7 @@ url = "../libs/checkpoint-sqlite"
[[package]]
name = "langgraph-sdk"
version = "0.1.53"
version = "0.1.51"
description = "SDK for interacting with LangGraph API"
optional = false
python-versions = "^3.9.0,<4.0"
@@ -5938,6 +5939,7 @@ python-versions = ">=3.8"
groups = ["test"]
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
files = [
{file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"},
{file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"},
]
@@ -5950,6 +5952,7 @@ python-versions = ">=3.8"
groups = ["test"]
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
files = [
{file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"},
{file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"},
]
@@ -8631,4 +8634,4 @@ type = ["pytest-mypy"]
[metadata]
lock-version = "2.1"
python-versions = "^3.10"
content-hash = "6dce741bb0e3d73af45d234fb1605d97f1bbf23c2e71e0a456cc6987d67554e7"
content-hash = "06debb82135affdb2baf1fdcc028c062c236121508d787588cd0de1db2da11e4"
+2 -2
View File
@@ -40,8 +40,8 @@ langchain-cohere = "^0.4.2"
[tool.poetry.group.test.dependencies]
langchain = "^0.3.8"
langchain-openai = "^0.3.7"
langchain-anthropic = "^0.3.8"
langchain-openai = "^0.3.0"
langchain-anthropic = "^0.2.1"
langchain-nomic = "^0.1.3"
langchain-fireworks = "^0.2.0"
langchain-community = "^0.3.0"
+8 -8
View File
@@ -1,23 +1,23 @@
# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand.
[[package]]
name = "aiosqlite"
version = "0.21.0"
version = "0.20.0"
description = "asyncio bridge to the standard sqlite3 module"
optional = false
python-versions = ">=3.9"
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "aiosqlite-0.21.0-py3-none-any.whl", hash = "sha256:2549cf4057f95f53dcba16f2b64e8e2791d7e1adedb13197dd8ed77bb226d7d0"},
{file = "aiosqlite-0.21.0.tar.gz", hash = "sha256:131bb8056daa3bc875608c631c678cda73922a2d4ba8aec373b19f18c17e7aa3"},
{file = "aiosqlite-0.20.0-py3-none-any.whl", hash = "sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6"},
{file = "aiosqlite-0.20.0.tar.gz", hash = "sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7"},
]
[package.dependencies]
typing_extensions = ">=4.0"
[package.extras]
dev = ["attribution (==1.7.1)", "black (==24.3.0)", "build (>=1.2)", "coverage[toml] (==7.6.10)", "flake8 (==7.0.0)", "flake8-bugbear (==24.12.12)", "flit (==3.10.1)", "mypy (==1.14.1)", "ufmt (==2.5.1)", "usort (==1.0.8.post1)"]
docs = ["sphinx (==8.1.3)", "sphinx-mdinclude (==0.6.1)"]
dev = ["attribution (==1.7.0)", "black (==24.2.0)", "coverage[toml] (==7.4.1)", "flake8 (==7.0.0)", "flake8-bugbear (==24.2.6)", "flit (==3.9.0)", "mypy (==1.8.0)", "ufmt (==2.3.0)", "usort (==1.0.8.post1)"]
docs = ["sphinx (==7.2.6)", "sphinx-mdinclude (==0.5.3)"]
[[package]]
name = "annotated-types"
@@ -1043,4 +1043,4 @@ watchmedo = ["PyYAML (>=3.10)"]
[metadata]
lock-version = "2.1"
python-versions = "^3.9.0"
content-hash = "21896b8d3d283d95bc3988aa93f06faf5c47dadc2a8822e5a35672b9cb054693"
content-hash = "e6d3ca9bce723c05f4c5ae9dc4bee872f7581b7763680b34112f1d280f5a9b0a"
+1 -1
View File
@@ -11,7 +11,7 @@ packages = [{ include = "langgraph" }]
[tool.poetry.dependencies]
python = "^3.9.0"
langgraph-checkpoint = "^2.0.15"
aiosqlite = ">=0.20,<0.22"
aiosqlite = "^0.20.0"
[tool.poetry.group.dev.dependencies]
ruff = "^0.6.2"
@@ -127,16 +127,6 @@ class StreamMessagesHandler(BaseCallbackHandler, _StreamingCallbackHandler):
tuple(cast(str, metadata["langgraph_checkpoint_ns"]).split(NS_SEP)),
metadata,
)
if isinstance(inputs, dict):
for key, value in inputs.items():
if isinstance(value, BaseMessage):
if value.id is not None:
self.seen.add(value.id)
elif isinstance(value, Sequence) and not isinstance(value, str):
for item in value:
if isinstance(item, BaseMessage):
if item.id is not None:
self.seen.add(item.id)
def on_chain_end(
self,
+5 -17
View File
@@ -32,17 +32,11 @@ def validate_graph(
for chan in subscribed_channels:
if chan not in channels:
raise ValueError(
f"Subscribed channel '{chan}' not "
f"in known channels: '{repr(sorted(channels))[:100]}'"
)
raise ValueError(f"Subscribed channel '{chan}' not in 'channels'")
if isinstance(input_channels, str):
if input_channels not in channels:
raise ValueError(
f"Input channel '{input_channels}' not "
f"in known channels: '{repr(sorted(channels))[:100]}'"
)
raise ValueError(f"Input channel '{input_channels}' not in 'channels'")
if input_channels not in subscribed_channels:
raise ValueError(
f"Input channel {input_channels} is not subscribed to by any node"
@@ -50,13 +44,10 @@ def validate_graph(
else:
for chan in input_channels:
if chan not in channels:
raise ValueError(
f"Input channel '{chan}' not in '{repr(sorted(channels))[:100]}'"
)
raise ValueError(f"Input channel '{chan}' not in 'channels'")
if all(chan not in subscribed_channels for chan in input_channels):
raise ValueError(
f"None of the input channels {input_channels} "
f"are subscribed to by any node"
f"None of the input channels {input_channels} are subscribed to by any node"
)
all_output_channels = set[str]()
@@ -71,10 +62,7 @@ def validate_graph(
for chan in all_output_channels:
if chan not in channels:
raise ValueError(
f"Output channel '{chan}' not "
f"in known channels: '{repr(sorted(channels))[:100]}'"
)
raise ValueError(f"Output channel '{chan}' not in 'channels'")
if interrupt_after_nodes != "*":
for n in interrupt_after_nodes:
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "langgraph"
version = "0.2.75"
version = "0.2.74"
description = "Building stateful, multi-actor applications with LLMs"
authors = []
license = "MIT"
-98
View File
@@ -6588,101 +6588,3 @@ def test_get_stream_writer() -> None:
},
),
]
def test_stream_messages_dedupe_inputs() -> None:
from langchain_core.messages import AIMessage
def call_model(state):
return {"messages": AIMessage("hi", id="1")}
def route(state):
return Command(goto="node_2", graph=Command.PARENT)
subgraph = (
StateGraph(MessagesState)
.add_node(call_model)
.add_node(route)
.add_edge(START, "call_model")
.add_edge("call_model", "route")
.compile()
)
graph = (
StateGraph(MessagesState)
.add_node("node_1", subgraph)
.add_node("node_2", lambda state: state)
.add_edge(START, "node_1")
.compile()
)
chunks = [
chunk
for ns, chunk in graph.stream(
{"messages": "hi"}, stream_mode="messages", subgraphs=True
)
]
assert len(chunks) == 1
assert chunks[0][0] == AIMessage("hi", id="1")
assert chunks[0][1]["langgraph_node"] == "call_model"
@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC)
def test_stream_messages_dedupe_state(
request: pytest.FixtureRequest, checkpointer_name: str
) -> None:
from langchain_core.messages import AIMessage
checkpointer = request.getfixturevalue(f"checkpointer_{checkpointer_name}")
to_emit = [AIMessage("bye", id="1"), AIMessage("bye again", id="2")]
def call_model(state):
return {"messages": to_emit.pop(0)}
def route(state):
return Command(goto="node_2", graph=Command.PARENT)
subgraph = (
StateGraph(MessagesState)
.add_node(call_model)
.add_node(route)
.add_edge(START, "call_model")
.add_edge("call_model", "route")
.compile()
)
graph = (
StateGraph(MessagesState)
.add_node("node_1", subgraph)
.add_node("node_2", lambda state: state)
.add_edge(START, "node_1")
.compile(checkpointer=checkpointer)
)
thread1 = {"configurable": {"thread_id": "1"}}
chunks = [
chunk
for ns, chunk in graph.stream(
{"messages": "hi"}, thread1, stream_mode="messages", subgraphs=True
)
]
assert len(chunks) == 1
assert chunks[0][0] == AIMessage("bye", id="1")
assert chunks[0][1]["langgraph_node"] == "call_model"
chunks = [
chunk
for ns, chunk in graph.stream(
{"messages": "hi again"},
thread1,
stream_mode="messages",
subgraphs=True,
)
]
assert len(chunks) == 1
assert chunks[0][0] == AIMessage("bye again", id="2")
assert chunks[0][1]["langgraph_node"] == "call_model"
+3 -97
View File
@@ -7282,7 +7282,9 @@ async def test_multiple_subgraphs_mixed_state_graph(
@NEEDS_CONTEXTVARS
@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC)
async def test_multiple_subgraphs_checkpointer(checkpointer_name: str) -> None:
async def test_multiple_subgraphs_checkpointer(
request: pytest.FixtureRequest, checkpointer_name: str
) -> None:
async with awith_checkpointer(checkpointer_name) as checkpointer:
class SubgraphState(TypedDict):
@@ -7511,99 +7513,3 @@ async def test_tags_stream_mode_messages() -> None:
},
)
]
async def test_stream_messages_dedupe_inputs() -> None:
from langchain_core.messages import AIMessage
async def call_model(state):
return {"messages": AIMessage("hi", id="1")}
async def route(state):
return Command(goto="node_2", graph=Command.PARENT)
subgraph = (
StateGraph(MessagesState)
.add_node(call_model)
.add_node(route)
.add_edge(START, "call_model")
.add_edge("call_model", "route")
.compile()
)
graph = (
StateGraph(MessagesState)
.add_node("node_1", subgraph)
.add_node("node_2", lambda state: state)
.add_edge(START, "node_1")
.compile()
)
chunks = [
chunk
async for ns, chunk in graph.astream(
{"messages": "hi"}, stream_mode="messages", subgraphs=True
)
]
assert len(chunks) == 1
assert chunks[0][0] == AIMessage("hi", id="1")
assert chunks[0][1]["langgraph_node"] == "call_model"
@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC)
async def test_stream_messages_dedupe_state(checkpointer_name: str) -> None:
async with awith_checkpointer(checkpointer_name) as checkpointer:
from langchain_core.messages import AIMessage
to_emit = [AIMessage("bye", id="1"), AIMessage("bye again", id="2")]
async def call_model(state):
return {"messages": to_emit.pop(0)}
async def route(state):
return Command(goto="node_2", graph=Command.PARENT)
subgraph = (
StateGraph(MessagesState)
.add_node(call_model)
.add_node(route)
.add_edge(START, "call_model")
.add_edge("call_model", "route")
.compile()
)
graph = (
StateGraph(MessagesState)
.add_node("node_1", subgraph)
.add_node("node_2", lambda state: state)
.add_edge(START, "node_1")
.compile(checkpointer=checkpointer)
)
thread1 = {"configurable": {"thread_id": "1"}}
chunks = [
chunk
async for ns, chunk in graph.astream(
{"messages": "hi"}, thread1, stream_mode="messages", subgraphs=True
)
]
assert len(chunks) == 1
assert chunks[0][0] == AIMessage("bye", id="1")
assert chunks[0][1]["langgraph_node"] == "call_model"
chunks = [
chunk
async for ns, chunk in graph.astream(
{"messages": "hi again"},
thread1,
stream_mode="messages",
subgraphs=True,
)
]
assert len(chunks) == 1
assert chunks[0][0] == AIMessage("bye again", id="2")
assert chunks[0][1]["langgraph_node"] == "call_model"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@langchain/langgraph-sdk",
"version": "0.0.45",
"version": "0.0.46",
"description": "Client library for interacting with the LangGraph API",
"type": "module",
"packageManager": "yarn@1.22.19",