Skip to content

fix(sdk): fetch subagent history#2191

Open
Christian Bromann (christian-bromann) wants to merge 4 commits intomainfrom
cb/subagent-state-history
Open

fix(sdk): fetch subagent history#2191
Christian Bromann (christian-bromann) wants to merge 4 commits intomainfrom
cb/subagent-state-history

Conversation

@christian-bromann
Copy link
Member

@christian-bromann Christian Bromann (christian-bromann) commented Mar 16, 2026

Restores subagent conversation history (messages, tool calls) after page reload in deep-agent UIs. Previously, reloading a page that had completed a deep-agent run would correctly show the subagent pipeline cards (researcher, data-analyst, content-writer), but each card would be empty — no internal messages or tool calls visible, even though the same content was visible during the live stream.

Problem

Three separate issues combined to cause the failure:

1. Wrong source for messages in buildExecution
SubagentManager.buildExecution always called getMessagesForSubagent(base.id), which reads from the live-streaming message chunk buffer. For subagents reconstructed after a page reload this buffer is empty, so it returned [] and unconditionally overwrote base.messages — even after updateSubagentFromSubgraphState had successfully populated it from the checkpoint.

2. Subgraph getStateHistory threw instead of falling back
When the SDK queried POST /threads/{id}/history with checkpoint_ns: "tools:{uuid}", LangGraph's getStateHistory tried to find a statically-registered Pregel subgraph named "tools". Tool-call subgraphs are created dynamically at runtime (not registered statically), so it threw "Subgraph with namespace 'tools' not found". The fix makes getStateHistory (and getState) fall back to direct checkpointer access when no static subgraph matches the namespace — consistent with how tool-call subgraphs actually store their checkpoints.

3. AbortController / React Strict Mode cleanup race
The useEffect that calls fetchSubagentHistory had no cleanup function. In React Strict Mode (and when reactive dependencies like isLoading toggle), effects re-run immediately — meaning a second fetchSubagentHistory call would start before the first completed. By adding an AbortController returned from the cleanup, the previous in-flight HTTP request is cancelled on re-run. Crucially, the abort check was placed only on the HTTP request itself: if the fetch already completed before cleanup, the result is still applied (cancellation only prevents the network round-trip, not the state update of a completed response).

Changes

libs/sdk/src/ui/subagents.ts

  • buildExecution: Fall back to base.messages when the streaming message manager is empty. This ensures checkpoint-restored messages are visible in the UI.
  • updateSubagentFromSubgraphState: New method that accepts restored messages from a subgraph checkpoint and sets them on the base, guarded against overwriting live streaming data.

libs/sdk/src/ui/manager.ts

  • fetchSubagentHistory: New async method on StreamManager. After reconstructSubagents, fetches each subagent's checkpoint history using the UUID-based checkpoint_ns stored in the tool message's additional_kwargs.subgraph_checkpoint_ns. Accepts an AbortSignal to cancel in-flight requests when effects re-run.

libs/langgraph-core/src/pregel/index.ts

  • getState / getStateHistory: When no static subgraph matches the namespace (e.g. dynamically-created tool-call subgraphs), fall back to direct checkpointer access instead of throwing. This makes subgraph history fetchable via the existing /threads/{id}/history endpoint.

Framework SDKs (React, Vue, Angular, Svelte)

All four framework hooks now:

  1. Call fetchSubagentHistory after reconstructSubagents, passing the client.threads and an AbortSignal.
  2. Return a cleanup that aborts the controller — cancelling the HTTP request if the effect re-runs before the fetch completes.
Framework Mechanism
React (sdk-react, sdk/react) useEffect cleanup return value
Vue (sdk-vue) watch onCleanup parameter
Angular (sdk-angular) effect onCleanup parameter
Svelte (sdk-svelte) Explicit fetchController variable, aborted in onDestroy

How it works end-to-end

During a live stream (no change): subagent messages flow through SSE events with a namespaced checkpoint_ns (e.g. tools:a1b2c3d4-...). Deepagents stores this namespace in the task ToolMessage's additional_kwargs.subgraph_checkpoint_ns. The streaming message buffer populates buildExecution as before.

After page reload:

  1. The main thread state is fetched (existing behavior) — tool messages now carry subgraph_checkpoint_ns.
  2. reconstructSubagents creates subagent stubs from the main thread's messages (tool call args, final result, status).
  3. fetchSubagentHistory uses the stored checkpoint_ns to call POST /threads/{id}/history with { checkpoint: { checkpoint_ns: "tools:{uuid}" }, limit: 1 } for each subagent.
  4. The response contains the subagent's full message history (human prompt → internal LLM calls → tool calls → final response).
  5. updateSubagentFromSubgraphState sets these on the base object. buildExecution picks them up via the base.messages fallback, populating the UI.

Requires companion change in deepagents

The subgraph_checkpoint_ns field in each task ToolMessage requires a matching change in the deepagents library: the task tool captures config.configurable.checkpoint_ns (the UUID-based namespace injected by LangGraph's algo.ts) and stores it in returnCommandWithStateUpdate. See deepagentsjs PR #312.

@changeset-bot
Copy link

changeset-bot bot commented Mar 16, 2026

⚠️ No Changeset found

Latest commit: 1addd91

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 16, 2026

Open in StackBlitz

@langchain/langgraph-checkpoint

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-checkpoint@2191

@langchain/langgraph-checkpoint-mongodb

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-checkpoint-mongodb@2191

@langchain/langgraph-checkpoint-postgres

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-checkpoint-postgres@2191

@langchain/langgraph-checkpoint-redis

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-checkpoint-redis@2191

@langchain/langgraph-checkpoint-sqlite

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-checkpoint-sqlite@2191

@langchain/langgraph-checkpoint-validation

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-checkpoint-validation@2191

create-langgraph

npm i https://pkg.pr.new/langchain-ai/langgraphjs/create-langgraph@2191

@langchain/langgraph-api

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-api@2191

@langchain/langgraph-cli

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-cli@2191

@langchain/langgraph

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph@2191

@langchain/langgraph-cua

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-cua@2191

@langchain/langgraph-supervisor

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-supervisor@2191

@langchain/langgraph-swarm

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-swarm@2191

@langchain/langgraph-ui

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-ui@2191

@langchain/langgraph-sdk

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/langgraph-sdk@2191

@langchain/angular

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/angular@2191

@langchain/react

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/react@2191

@langchain/svelte

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/svelte@2191

@langchain/vue

npm i https://pkg.pr.new/langchain-ai/langgraphjs/@langchain/vue@2191

commit: 1addd91

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant