Skip to content

feat(ag-ui): scriptable provideFakeAgent() and a duplicate-AgentRef warning - #1053

Merged
blove merged 2 commits into
mainfrom
blove/ag-ui-fake-agent-script
Sep 8, 2026
Merged

feat(ag-ui): scriptable provideFakeAgent() and a duplicate-AgentRef warning#1053
blove merged 2 commits into
mainfrom
blove/ag-ui-fake-agent-script

Conversation

@blove

@blove blove commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Closes two AG-UI library follow-ups.

1. Development warning when several AgentRefs share an injector

The ref form of provideAgent(ref, …) aliases the shared AGENT token, so N refs registered at one injector level leave the ref-less injectAgent() pointing at the Nth with no signal at all.

Each ref-form call now also contributes its debug name to an internal multi token. The first agent built at that level reads that list and, under isDevMode() only, emits a single console.warn naming every ref registered there and the one the bare injectAgent() resolves. Multi providers do not merge across injectors, so refs at different levels (application config vs. a component's providers) neither collide nor warn. Nothing about resolution changes: each ref still gets its own agent and its own config evaluation.

2. provideFakeAgent() accepts script

FakeAgent's script option was constructor-only and unreachable through provideFakeAgent(), which took the shared FakeAgentConfig from @threadplane/chat/testing (tokens / reasoningTokens / delayMs). It now takes AgUiFakeAgentConfig — that shared config plus the AG-UI-only script — and forwards it to the constructor, so tool calls, shared state, custom events, and interrupts are all scriptable through DI. The script shape is exported as FakeAgentScript. The shared config type in libs/chat is untouched.

Also confirmed while here: FakeAgent does wrap a scripted batch in RUN_STARTED / RUN_FINISHED as the docs claim (existing spec), and the { toolMessageFor } branch does fire on the follow-up run — a new spec drives that through the real path, clientTools.resolve() adding the tool message and starting the continuation.

Specs

  • libs/ag-ui/src/lib/provide-agent.duplicate-ref-warning.spec.ts (new): two refs at one level warn exactly once, the message names both refs, both agents stay distinct, the bare token still resolves the last one; a single ref does not warn; refs at different injector levels do not warn. Failed before the change (0 warnings), passes after.
  • libs/ag-ui/src/lib/testing/provide-fake-agent.spec.ts: provideFakeAgent({ script }) reduces a scripted tool call into toolCalls(), state and custom events into state() / customEvents(), a CUSTOM on_interrupt into interrupt(), and runs the { toolMessageFor } branch on the continuation that clientTools.resolve() starts.
  • libs/ag-ui/src/lib/testing/provide-fake-agent.type-spec.ts (new): the script property is part of the accepted config. This is the compile-level guard — the runtime already passed the property through structurally, and the old signature was what rejected it. Verified failing before the change with TS2353: 'script' does not exist in type 'FakeAgentConfig'.

Docs

  • ag-ui/api/provide-agent.mdx and ag-ui/concepts/architecture.mdx: the last-ref-wins rule now also describes the development warning, with the message text.
  • ag-ui/api/fake-agent.mdx, ag-ui/guides/fake-agent.mdx, ag-ui/guides/testing.mdx: no longer say script is constructor-only or that provideFakeAgent() cannot emit TOOL_CALL_*, STATE_*, or CUSTOM. Each carries a fence that was run as a spec before being pasted in.
  • apps/website/content/docs/ag-ui/api/api-docs.json regenerated.

Verification

  • npx nx run-many -t lint,test,build --projects=ag-ui — green (0 lint errors, 275 tests in 14 files).
  • npx vitest run --root apps/website — 1326 tests in 131 files, green.
  • GROWTH_FORM_POLICY=growth_v1 npx nx build website — green.

Note: nx run ag-ui:type-tests is red on origin/main in this environment for reasons unrelated to this branch (TS5101 on the config's deprecated baseUrl, plus TS6059 rootDir errors on every cross-library import). The new type-spec was checked with tsc --ignoreDeprecations 6.0 and reports no errors of its own.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadplane Ready Ready Preview Sep 7, 2026 9:55pm UTC

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

blove and others added 2 commits September 7, 2026 14:47
…ctor

The ref form of provideAgent() aliases the shared AGENT token, so N refs at
one injector level leave the ref-less injectAgent() pointing at the Nth with
no signal. Each ref-form call now also contributes its debug name to an
internal multi token; the first agent built at that level reads the list and,
in development mode only, emits a single console.warn naming every ref and the
one the bare injectAgent() resolves. Multi providers do not merge across
injectors, so refs at different levels neither collide nor warn.

Behavior is otherwise unchanged: each ref still gets its own agent and its own
config evaluation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
FakeAgent's script option was constructor-only and unreachable through
provideFakeAgent(), which accepted the shared FakeAgentConfig from
@threadplane/chat/testing (tokens, reasoningTokens, delayMs). provideFakeAgent()
now takes AgUiFakeAgentConfig — that shared config plus the AG-UI-only script —
and passes it to the constructor, so tool calls, state, custom events, and
interrupts are all scriptable through DI. The script shape is exported as
FakeAgentScript. The shared config type in libs/chat is untouched.

Docs updated: the api and guide pages no longer say script is constructor-only
or that provideFakeAgent() cannot emit TOOL_CALL_*, STATE_* or CUSTOM, and each
carries a fence that runs. api-docs regenerated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@blove
blove force-pushed the blove/ag-ui-fake-agent-script branch from dd34e91 to 5a81590 Compare September 7, 2026 21:47
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove merged commit 11506fb into main Sep 8, 2026
76 checks passed
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