Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: langchain-ai/langgraph
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.2.5
Choose a base ref
...
head repository: langchain-ai/langgraph
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1.2.6
Choose a head ref
  • 9 commits
  • 49 files changed
  • 7 contributors

Commits on Jun 12, 2026

  1. 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 />
    
    
    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tornado&package-manager=uv&previous-version=6.5.5&new-version=6.5.6)](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>
    dependabot[bot] authored Jun 12, 2026
    Configuration menu
    Copy the full SHA
    4cf120d View commit details
    Browse the repository at this point in the history
  2. docs: standardize package README.md structure (#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.
    mdrxy authored Jun 12, 2026
    Configuration menu
    Copy the full SHA
    8558481 View commit details
    Browse the repository at this point in the history

Commits on Jun 13, 2026

  1. 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.
    mdrxy authored Jun 13, 2026
    Configuration menu
    Copy the full SHA
    9732084 View commit details
    Browse the repository at this point in the history

Commits on Jun 16, 2026

  1. 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]>
    cwlbraa authored Jun 16, 2026
    Configuration menu
    Copy the full SHA
    916025d View commit details
    Browse the repository at this point in the history
  2. release(cli): 0.4.30 (#8101)

    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.
    cwlbraa authored Jun 16, 2026
    Configuration menu
    Copy the full SHA
    1a9baae View commit details
    Browse the repository at this point in the history

Commits on Jun 17, 2026

  1. 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]>
    3 people authored Jun 17, 2026
    Configuration menu
    Copy the full SHA
    9af2521 View commit details
    Browse the repository at this point in the history
  2. 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]>
    3 people authored Jun 17, 2026
    Configuration menu
    Copy the full SHA
    79befe6 View commit details
    Browse the repository at this point in the history
  3. 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
    longquanzheng authored Jun 17, 2026
    Configuration menu
    Copy the full SHA
    9100f2c View commit details
    Browse the repository at this point in the history

Commits on Jun 18, 2026

  1. Configuration menu
    Copy the full SHA
    ce6c8b2 View commit details
    Browse the repository at this point in the history
Loading