Repository navigation
Comparing changes
Open a pull request
base repository: langchain-ai/langgraph
base: 1.2.5
head repository: langchain-ai/langgraph
compare: 1.2.6
- 9 commits
- 49 files changed
- 7 contributors
Commits on Jun 12, 2026
-
chore(deps): bump tornado from 6.5.5 to 6.5.6 in /libs/langgraph (#8063)
Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.5.5 to 6.5.6. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst">tornado's changelog</a>.</em></p> <blockquote> <h1>Release notes</h1> <p>.. toctree:: :maxdepth: 2</p> <p>releases/v6.5.7 releases/v6.5.6 releases/v6.5.5 releases/v6.5.4 releases/v6.5.3 releases/v6.5.2 releases/v6.5.1 releases/v6.5.0 releases/v6.4.2 releases/v6.4.1 releases/v6.4.0 releases/v6.3.3 releases/v6.3.2 releases/v6.3.1 releases/v6.3.0 releases/v6.2.0 releases/v6.1.0 releases/v6.0.4 releases/v6.0.3 releases/v6.0.2 releases/v6.0.1 releases/v6.0.0 releases/v5.1.1 releases/v5.1.0 releases/v5.0.2 releases/v5.0.1 releases/v5.0.0 releases/v4.5.3 releases/v4.5.2 releases/v4.5.1 releases/v4.5.0 releases/v4.4.3 releases/v4.4.2 releases/v4.4.1 releases/v4.4.0 releases/v4.3.0 releases/v4.2.1 releases/v4.2.0 releases/v4.1.0 releases/v4.0.2 releases/v4.0.1 releases/v4.0.0 releases/v3.2.2 releases/v3.2.1</p> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/tornadoweb/tornado/commit/aba2569f7ed7a6bdbef816658fb6b7182531b751"><code>aba2569</code></a> Merge pull request <a href="https://redirect.github.com/tornadoweb/tornado/issues/3626">#3626</a> from bdarnell/fixes-656</li> <li><a href="https://github.com/tornadoweb/tornado/commit/a24b260e0d22fd48acea1a2635526c1700e7ac09"><code>a24b260</code></a> httpclient_test: Accept an additional error message variant</li> <li><a href="https://github.com/tornadoweb/tornado/commit/a74240a70268fe5cb40a127951cb21549ab9ff24"><code>a74240a</code></a> Release notes and version bump for 6.5.6.</li> <li><a href="https://github.com/tornadoweb/tornado/commit/e8fc7edb238f1022e39f9d0b9d297fc7c21fb0a5"><code>e8fc7ed</code></a> simple_httpclient: Strip auth headers on cross-origin redirects</li> <li><a href="https://github.com/tornadoweb/tornado/commit/96dc88c2a05705287856b2cd6b4b4034f9a6aaac"><code>96dc88c</code></a> speedups: validate mask length</li> <li><a href="https://github.com/tornadoweb/tornado/commit/ff808b33adc52d89a549376a5e3628e92abbc8ff"><code>ff808b3</code></a> http1connection: Enforce max_body_size in _GzipMessageDelegate</li> <li><a href="https://github.com/tornadoweb/tornado/commit/ede4e37f93c1edbc0bf749e9a57c9db2501cd54b"><code>ede4e37</code></a> auth: Correctly parse check_authentication response</li> <li><a href="https://github.com/tornadoweb/tornado/commit/1c178bef88bbd29907eb94a2a649a4a6675681de"><code>1c178be</code></a> Remove obsolete curl force_timeout workaround</li> <li><a href="https://github.com/tornadoweb/tornado/commit/c99d55bb6cc0c9da2c6696545ed4ee1d20b7fcf0"><code>c99d55b</code></a> Replace deprecated pycurl IOCTLFUNCTION callback with SEEKFUNCTION</li> <li><a href="https://github.com/tornadoweb/tornado/commit/27614316ef8ad125fe18725cf96e384560ba0e14"><code>2761431</code></a> Merge pull request <a href="https://redirect.github.com/tornadoweb/tornado/issues/3587">#3587</a> from bdarnell/fix-link</li> <li>Additional commits viewable in <a href="https://github.com/tornadoweb/tornado/compare/v6.5.5...v6.5.6">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/langchain-ai/langgraph/network/alerts). </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 4cf120d - Browse repository at this point
Copy the full SHA 4cf120dView commit details -
docs: standardize package
README.mdstructure (#8064)Aligns the repository's package READMEs around a shared documentation shape so users see consistent install, positioning, docs, release, and contribution guidance across LangGraph packages.
Configuration menu - View commit details
-
Copy full SHA for 8558481 - Browse repository at this point
Copy the full SHA 8558481View commit details
Commits on Jun 13, 2026
-
ci(deps): pin GitHub Actions to commit SHAs (#8065)
Every third-party GitHub Action in the workflows is now pinned to a full commit SHA instead of a floating major tag, closing a supply-chain gap where a mutable tag like `@v6` could be force-pushed to point at malicious code. Seven actions were already SHA-pinned; this brings the remaining first-party `actions/*` and `astral-sh/setup-uv` references in line. ## Changes - Pinned all previously tag-referenced actions to their current commit SHA with the exact release as a trailing comment (the format Dependabot reads and updates): `actions/checkout` → `v6.0.3`, `actions/setup-python` → `v6.2.0`, `actions/github-script` → `v9.0.0`, `actions/upload-artifact` → `v7.0.1`, `actions/download-artifact` → `v8.0.1`, `actions/cache/{restore,save}` → `v5.0.5`, `actions/configure-pages` → `v6.0.0`, `actions/deploy-pages` → `v5.0.0`, `actions/upload-pages-artifact` → `v5.0.0`, `actions/create-github-app-token` → `v3.2.0`, and `astral-sh/setup-uv` → `v7.6.0`. - Applied across all workflow files plus the `uv_setup` composite action; local same-repo references (`./.github/workflows/_*.yml`, `./.github/actions/uv_setup`) left as path refs since they resolve from the same commit.Configuration menu - View commit details
-
Copy full SHA for 9732084 - Browse repository at this point
Copy the full SHA 9732084View commit details
Commits on Jun 16, 2026
-
feat(cli): support compatible api version ranges (#8023)
Adds `api_version` ranges for LangGraph API base image tags. `~=0.11.0.dev5` resolves to the newest matching compatible image while freezing later dev prereleases until rc/final/patch tags exist; `>~=0.11.0.dev5` uses the same floor but can also float to future stable releases while ignoring future prereleases. Verified with `make format`, `make lint`, and `make test` from `libs/cli`. --------- Signed-off-by: Connor Braa <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for 916025d - Browse repository at this point
Copy the full SHA 916025dView commit details -
Bump langgraph-cli to 0.4.30 to cut a CLI release from 916025d. Also change the in-memory extra to require langgraph-api <0.12.0, excluding 0.12.0.dev releases from normal pip resolution. Refresh uv example lockfiles so they keep langchain-protocol compatible with the stable API image used by CLI integration tests. CI will verify the release change.
Configuration menu - View commit details
-
Copy full SHA for 1a9baae - Browse repository at this point
Copy the full SHA 1a9baaeView commit details
Commits on Jun 17, 2026
-
fix: cancel running subgraphs on v3 stream abort [closes #8029] (#8057)
## Description v3 event streaming's `stream.abort()` (sync and async) only closed the mux and stopped pumping, leaving the underlying `astream`/`stream` generator — and any running subgraphs — alive until they finished, burning resources. The fix closes the underlying graph iterator so `GeneratorExit` propagates into in-flight nodes/subgraphs and cancels them, matching v2's `aclose()` behavior. Fixes #8029. ## Release Note v3 streaming `stream.abort()` now cancels running subgraphs instead of letting them run to completion. ## Test Plan - [x] `TEST="tests/test_pregel_stream_events_v3.py -k abort" make test` (new `test_abort_cancels_running_subgraph` asserts the looping subgraph stops after abort) Made by [Open SWE](https://openswe.vercel.app) --------- Co-authored-by: Nick Hollon <[email protected]> Co-authored-by: open-swe[bot] <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for 9af2521 - Browse repository at this point
Copy the full SHA 9af2521View commit details -
fix: nested subgraph inherits parent checkpoint_ns (regression in 1.2…
….3) (#8053) Closes #8038 ## Description The `ensure_config` merge introduced in #7926 caused a child graph invoked inside a parent node to inherit the parent task's `checkpoint_ns` from the ambient run context (`var_child_runnable_config`), so the child's checkpoints were written under an unreadable namespace and re-ran from scratch each turn (#8038). The first explicitly passed `configurable` that carries a checkpoint coordinate (a `thread_id`, or any `checkpoint_ns`/`checkpoint_id`/`checkpoint_map`) now replaces the ambient one, while subsequent explicit configs still shallow-merge — preserving #7926's `with_config(...)` semantics. ## Contract `ensure_config` merges an explicit `configurable` over the ambient run context (`var_child_runnable_config`) with one rule: **an explicit `configurable` that supplies its own checkpoint coordinate addresses its own checkpoint lineage, so the ambient `configurable` is dropped rather than merged over.** Coordinate keys are `thread_id`, `checkpoint_ns`, `checkpoint_id`, and `checkpoint_map` (grouped as `_CHECKPOINT_COORDINATE_KEYS`). A non-coordinate `configurable` keeps the ambient and shallow-merges over it. Below, each case shows the parent/child graph wiring that triggers it and the resulting namespacing. The child is always a compiled subgraph invoked from inside a parent node. ### 1. Subgraph invoked with no new config → ambient inherited ```python child = StateGraph(ChildState).add_node("n", child_node).add_edge(START, "n").compile(checkpointer=checkpointer) def parent_node(state): child.invoke({}, config=None) # no explicit configurable return {"result": "ok"} parent = StateGraph(ParentState).add_node("p", parent_node).add_edge(START, "p").compile(checkpointer=checkpointer) parent.invoke({"result": ""}, config={"configurable": {"thread_id": "parent"}}) ``` Child inherits the parent task's `checkpoint_ns` (`p:<parent-task>`); its checkpoints are written as a discoverable child of the parent run. Pre-#7926 behavior, unchanged. ### 2. Subgraph invoked with a new thread_id → ambient dropped ```python child = StateGraph(ChildState).add_node("n", child_node).add_edge(START, "n").compile(checkpointer=checkpointer) child_config = {"configurable": {"thread_id": str(uuid4())}} def parent_node(state): child.invoke({}, config=child_config) # explicit new thread_id return {"result": "ok"} parent = StateGraph(ParentState).add_node("p", parent_node).add_edge(START, "p").compile(checkpointer=checkpointer) parent.invoke({"result": ""}, config={"configurable": {"thread_id": "parent"}}) ``` Child starts its own lineage on `child_config`'s thread; `checkpoint_ns == ""`; `child.get_state(child_config)` reads back state across repeated parent turns. Fixes #8038. ### 3. Subgraph invoked with the same thread_id as parent → ambient still dropped ```python child = StateGraph(ChildState).add_node("n", child_node).add_edge(START, "n").compile(checkpointer=checkpointer) def parent_node(state): # reuses the parent's thread_id as the child's own child.invoke({}, config={"configurable": {"thread_id": state["parent_thread"]}}) return {"result": "ok"} parent = StateGraph(ParentState).add_node("p", parent_node).add_edge(START, "p").compile(checkpointer=checkpointer) parent_thread = str(uuid4()) parent.invoke({"parent_thread": parent_thread, "result": ""}, config={"configurable": {"thread_id": parent_thread}}) ``` Child addresses its own root namespace on the shared thread; `checkpoint_ns == ""`. The parent task's `checkpoint_ns` must not leak in, or `child.get_state({"configurable": {"thread_id": parent_thread}})` returns empty state and the child re-runs from scratch each turn. ### 4. Subagent invoked with a non-coordinate key only → ambient inherited ```python child = StateGraph(ChildState).add_node("n", child_node).add_edge(START, "n").compile(checkpointer=checkpointer) def parent_node(state): # ls_agent_type is not a checkpoint coordinate, so ambient is kept child.invoke({}, config={"configurable": {"ls_agent_type": "subagent"}}) return {"result": "ok"} parent = StateGraph(ParentState).add_node("p", parent_node).add_edge(START, "p").compile(checkpointer=checkpointer) parent.invoke({"result": ""}, config={"configurable": {"thread_id": "parent"}}) ``` Child remains a discoverable child of the parent run; ambient `thread_id` and `checkpoint_ns` preserved (deepagents `task` tool pattern). ### 5. with_config(...) + invoke-time thread_id → ambient dropped, then merged ```python # child compiled with a non-coordinate configurable via with_config child = ( StateGraph(ChildState) .add_node("n", child_node) .add_edge(START, "n") .compile(checkpointer=checkpointer) .with_config({"configurable": {"ls_agent_type": "root"}}) ) def parent_node(state): # invoke-time config supplies the thread_id; with_config's ls_agent_type survives child.invoke({}, config={"configurable": {"thread_id": "child"}}) return {"result": "ok"} parent = StateGraph(ParentState).add_node("p", parent_node).add_edge(START, "p").compile(checkpointer=checkpointer) parent.invoke({"result": ""}, config={"configurable": {"thread_id": "parent"}}) ``` First coordinate-bearing config (`thread_id`) drops the ambient; subsequent explicit configs still shallow-merge, so `ls_agent_type` survives alongside `thread_id`. Preserves #7926 `with_config(...)` semantics. ### Regression note Cases 1, 4, and 5 are the pre-#7926 behavior and are preserved unchanged. Cases 2 and 3 fix the regression introduced by #7926: an explicit `thread_id` resets the ambient even when it equals the ambient thread id, because a child reusing the parent's thread id still addresses its own root namespace on that thread, not the parent task's. ## Self-Hosted Release Note Fix regression where a nested subgraph with its own `thread_id` invoked inside a parent node lost its persisted state across turns. ## Test Plan - [x] `pytest tests/test_subgraph_persistence.py -k test_child_with_own_thread_id_keeps_namespace` (case 2) - [x] `pytest tests/test_utils.py -k ensure_config_explicit_configurable_replaces_ambient` (case 2) - [x] `pytest tests/test_utils.py -k ensure_config_ambient_inherited_when_no_explicit_configurable` (case 1) - [x] `pytest tests/test_utils.py -k ensure_config_non_coordinate_config_keeps_ambient_checkpoint_ns` (case 4) - [x] `pytest tests/test_utils.py -k ensure_config_explicit_configurables_still_merge_over_ambient` (case 5) - [x] `pytest tests/test_utils.py -k ensure_config_same_thread_id_still_clears_ambient` (case 3) Made by [Open SWE](https://openswe.vercel.app) --------- Co-authored-by: Nick Hollon <[email protected]> Co-authored-by: open-swe[bot] <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for 79befe6 - Browse repository at this point
Copy the full SHA 79befe6View commit details -
feat: add delta-channel-dump recovery script as examples to dump from…
… Postgres for deltaChannel rollback (#8109) Add a standalone recovery tool at `examples/delta-channel-dump/` for operators rolling back from langgraph >= 1.2 / deepagents 0.6.x to an older runtime that does not understand `EXT_DELTA_SNAPSHOT` msgpack blobs. Without this, channels like `messages` can appear empty after rollback because the old reducer does not decode delta snapshots. `dump.py` connects directly to Postgres, walks the checkpoint parent chain (mirroring `aget_delta_channel_history`), decodes msgpack blobs via `ormsgpack` with a hand-rolled EXT 0–7 hook (no langgraph imports), and emits JSON with per-channel `seed` + oldest-to-newest `writes`. The operator reduces and re-applies via `update_state` manually. ## Scope - Postgres checkpointer only - Deps: `psycopg[binary]`, `ormsgpack` (not added to repo `pyproject.toml` — operator installs at runtime) - No reducer application, no DB writes, no AES/custom encryption support (fails loudly on encrypted blob types) ## How verified - E2E against local Postgres: 15 runs of `delta_channel_messages_freq` (`snapshot_frequency=10`) - Asserted `delta_kind == "snapshot"`, `len(seed) == 10`, `len(writes) == 5`, message ids `ai-0`..`ai-14` - Confirmed portability: fresh venv with only `pip install "psycopg[binary]" ormsgpack` produced identical output
Configuration menu - View commit details
-
Copy full SHA for 9100f2c - Browse repository at this point
Copy the full SHA 9100f2cView commit details
Commits on Jun 18, 2026
-
Configuration menu - View commit details
-
Copy full SHA for ce6c8b2 - Browse repository at this point
Copy the full SHA ce6c8b2View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff 1.2.5...1.2.6