fix(langgraph, ag-ui): give each AgentRef its own agent instead of aliasing one token - #1000
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
blove
enabled auto-merge (squash)
September 4, 2026 21:42
Contributor
Contributor
…iasing one token Two provideAgent(ref, ...) calls in one providers array silently returned the same agent, built from the last config. AGENT and AGENT_CONFIG are module-scope tokens, so a second call re-registers both (last wins) and every ref.token was useExisting: AGENT, so all refs aliased that single winner. No error, no warning. Both adapters had the identical shape; both are fixed. Each ref now gets a per-call private config token and its own factory. The alias direction is load-bearing: the ref path aliases AGENT to ref.token rather than providing a second independent factory, which is what keeps single-ref behaviour byte-identical — one instance, one config-factory evaluation. With several refs the bare injectAgent() necessarily stays last-wins, and the doc comment now says so. Includes the api-docs regeneration for the changed doc comments. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
blove
force-pushed
the
blove/langgraph-agent-ref-isolation
branch
from
September 4, 2026 21:52
be60797 to
8538c51
Compare
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two
provideAgent(ref, …)calls in one providers array silently returned the same agent, built from the last config. No error, no warning — you simply got the wrong agent.AGENTandAGENT_CONFIGare module-scope tokens, so a second call re-registers both (last wins) and everyref.tokenwasuseExisting: AGENT, so all refs aliased that single winner. Both@threadplane/langgraphand@threadplane/ag-uihad the identical shape; both are fixed.We found this building the homepage hero, which needs a replay agent and a live agent side by side and had to work around it with one child
EnvironmentInjectorper agent. Any consumer with two agents in one injector hits it.The fix
Each ref now gets a per-call private config token and its own factory, so N refs coexist at one injector level. The factory body was extracted so both paths share it.
The alias direction is deliberate and load-bearing: the ref path aliases
AGENT → useExisting ref.token, rather than providing a second independent factory. That is what keeps single-ref behaviour byte-identical —injectAgent()andinjectAgent(ref)still return the same instance and the config factory still evaluates once. The naive "provide both separately" fix would have quietly double-instantiated for every existing single-ref consumer.With multiple refs the bare
injectAgent()necessarily stays last-wins, since one token can only mean one thing. That is now stated explicitly in the doc comment instead of being implicit, along with a two-agent example.Tests
New isolation blocks in both adapters assert two refs yield distinct instances and that each got its own config, on something observable rather than object identity: in langgraph a
submit()on A lands only in A's transport; in ag-ui, which exposes no source handle, a stubbedfetchproves each agent hit its own URL. Also covered: single-ref identity,AGENT_CONFIGstill resolving, and the lazy factory form still evaluating inside an injection context (asserted by call count before and after injection), which the hero and the demo shell both depend on.Mutation-checked: reverting each fix turns exactly the isolation test red in both packages.
Verification
langgraph 403 tests, ag-ui 261, both green;
langgraph,ag-uiandchatgreen together;examples-chat-angulargreen apart from one pre-existing router flake confirmed identical on a clean baseline; 0 lint errors; both packages build. No new public exports, so no API-docs regeneration.For the reviewer
Provider array order changed in the ref path —
ref.tokennow precedesAGENT. Existing specs that index into the returned array only do so for the no-ref form, which is unchanged, but a consumer indexing a ref call's array would notice.The hero's
scopedAgent()workaround still works and is untouched. It can be removed once this ships; deliberately left for a separate change.🤖 Generated with Claude Code