Compare commits

...
Author SHA1 Message Date
Sydney Runkleandopen-swe[bot] <open-swe@users.noreply.github.com> 1cc5f1fd48 fix(langgraph): use package metadata for API version check
Revert the optional `langgraph_api.__version__` import path in favor of the
cleaner `importlib.metadata.version("langgraph-api")` check for DeltaChannel
API compatibility. This avoids importing the optional API package at compile
time while preserving the same version boundary.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-17 17:11:56 +00:00
Sydney Runkleandopen-swe[bot] <open-swe@users.noreply.github.com> 289b4d4d78 fix(langgraph): read langgraph_api.__version__ for delta support
Use the version constant exported by `langgraph-api` instead of package
metadata for the DeltaChannel API compatibility check. This keeps the check
aligned with the API package itself while still avoiding a hard dependency
when `langgraph-api` is absent.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-17 17:01:34 +00:00
Sydney Runkleandopen-swe[bot] <open-swe@users.noreply.github.com> 30d1571f73 fix(langgraph): require langgraph-api>=0.10.0 for DeltaChannel
Raise for API versions below 0.10.0 so prereleases such as 0.10.0rc1 are
not accepted by the delta-channel compatibility check. Verified against real
langgraph-api releases: 0.9.0 raises and 0.10.0 compiles.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-17 16:50:12 +00:00
Sydney Runkleandopen-swe[bot] <open-swe@users.noreply.github.com> 8cbd400a11 fix(langgraph): require langgraph-api>=0.9.0 for DeltaChannel
Use a `>=` bound (raise below 0.9.0) and simplify the check: drop the
module-level constant and the early-return ladder. Verified end-to-end
against real langgraph-api releases — 0.8.6 raises, 0.10.0 compiles.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-15 11:30:27 +00:00
Sydney Runkleandopen-swe[bot] <open-swe@users.noreply.github.com> 9752282073 fix(langgraph): check langgraph-api version for DeltaChannel support
Replace the checkpointer-capability heuristic with a direct `langgraph-api`
version check: `DeltaChannel` reconstruction needs server-side support added
in `langgraph-api>0.9.0`. `StateGraph.compile` now raises a `RuntimeError`
when a delta-channel graph is compiled under an older API server, and is a
no-op when `langgraph-api` is not installed (local execution).

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-11 21:15:18 +00:00
Sydney Runkleandopen-swe[bot] <open-swe@users.noreply.github.com> 4e4bf1a204 feat(langgraph): warn when checkpointer lacks DeltaChannel support
A graph using `DeltaChannel` reconstructs state via the saver's
`get_delta_channel_history` API (added in `langgraph-checkpoint>=4.1.0`).
Savers from older packages lack it and fail at runtime. `StateGraph.compile`
now warns at compile time so users know to upgrade `langgraph-checkpoint`.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-10 20:55:45 +00:00
2 changed files with 120 additions and 1 deletions
+25 -1
View File
@@ -5,10 +5,11 @@ import logging
import typing
import warnings
from collections import defaultdict
from collections.abc import Awaitable, Callable, Hashable, Sequence
from collections.abc import Awaitable, Callable, Hashable, Mapping, Sequence
from dataclasses import dataclass, is_dataclass
from datetime import timedelta
from functools import partial
from importlib import metadata
from inspect import isclass, isfunction, ismethod, signature
from types import FunctionType
from types import NoneType as NoneType
@@ -29,6 +30,7 @@ from langchain_core.runnables import Runnable, RunnableConfig
from langgraph.cache.base import BaseCache
from langgraph.checkpoint.base import Checkpoint
from langgraph.store.base import BaseStore
from packaging.version import Version
from pydantic import BaseModel, TypeAdapter
from typing_extensions import NotRequired, Required, Self, Unpack, is_typeddict
@@ -120,6 +122,27 @@ def _warn_invalid_state_schema(schema: type[Any] | Any) -> None:
)
def _check_delta_channel_api_support(channels: Mapping[str, Any]) -> None:
"""Raise if a `DeltaChannel` graph runs under an API server too old to support it.
`DeltaChannel` reconstruction needs server-side support added in
`langgraph-api>=0.10.0`, so we raise at compile time when an older API
server is installed. Skipped when `langgraph-api` is absent (local
execution) or the graph has no delta channel.
"""
if not any(isinstance(c, DeltaChannel) for c in channels.values()):
return
try:
api_version = metadata.version("langgraph-api")
except metadata.PackageNotFoundError:
return
if Version(api_version) < Version("0.10.0"):
raise RuntimeError(
f"`DeltaChannel` requires `langgraph-api>=0.10.0`, but {api_version} "
"is installed. Upgrade with `pip install -U langgraph-api`."
)
def _get_node_name(node: StateNode[Any, ContextT]) -> str:
try:
return getattr(node, "__name__", node.__class__.__name__)
@@ -1216,6 +1239,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
CompiledStateGraph: The compiled `StateGraph`.
"""
checkpointer = ensure_valid_checkpointer(checkpointer)
_check_delta_channel_api_support(self.channels)
serde_allowlist: set[tuple[str, ...]] | None = None
if _serde.STRICT_MSGPACK_ENABLED:
@@ -0,0 +1,95 @@
"""Compile-time check that `DeltaChannel` graphs run under a supported API server.
`DeltaChannel` reconstruction relies on server-side support added in
`langgraph-api>=0.10.0`. When running under an older API server, delta channels
fail at runtime, so `StateGraph.compile` raises with an upgrade hint. The check
is skipped when `langgraph-api` is not installed (local execution).
"""
from __future__ import annotations
import warnings
from typing import Annotated
import pytest
from typing_extensions import TypedDict
from langgraph.channels.delta import DeltaChannel
from langgraph.constants import START
from langgraph.graph import StateGraph
from langgraph.graph import state as state_module
from langgraph.graph.message import _messages_delta_reducer
class _DeltaState(TypedDict):
messages: Annotated[
list, DeltaChannel(_messages_delta_reducer, snapshot_frequency=50)
]
class _PlainState(TypedDict):
values: Annotated[list, lambda a, b: (a or []) + (b or [])]
def _delta_graph() -> StateGraph:
return (
StateGraph(_DeltaState)
.add_node("n", lambda s: {"messages": []})
.add_edge(START, "n")
)
@pytest.fixture
def api_version(monkeypatch: pytest.MonkeyPatch):
"""Override the reported `langgraph-api` package version (or simulate absence)."""
def _set(version: str | None) -> None:
def fake_version(name: str) -> str:
if name == "langgraph-api":
if version is None:
raise state_module.metadata.PackageNotFoundError(name)
return version
return state_module.metadata.version(name)
monkeypatch.setattr(state_module.metadata, "version", fake_version)
return _set
def test_delta_graph_raises_for_old_api(api_version) -> None:
api_version("0.9.9")
with pytest.raises(RuntimeError, match="requires `langgraph-api>=0.10.0`"):
_delta_graph().compile()
def test_delta_graph_raises_for_api_release_candidate(api_version) -> None:
api_version("0.10.0rc1")
with pytest.raises(RuntimeError, match="requires `langgraph-api>=0.10.0`"):
_delta_graph().compile()
def test_delta_graph_ok_for_min_api(api_version) -> None:
api_version("0.10.0")
_delta_graph().compile()
def test_delta_graph_ok_for_newer_api(api_version) -> None:
api_version("0.11.2")
_delta_graph().compile()
def test_delta_graph_ok_when_api_not_installed(api_version) -> None:
api_version(None)
_delta_graph().compile()
def test_non_delta_graph_never_raises(api_version) -> None:
api_version("0.1.0")
graph = (
StateGraph(_PlainState)
.add_node("n", lambda s: {"values": []})
.add_edge(START, "n")
)
with warnings.catch_warnings():
warnings.simplefilter("error")
graph.compile()