feat(cockpit): ag-ui subagents demo emits the protocol's SUBAGENT_* events - #962
Merged
Conversation
…* events Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…>=0.1.22 Baseline SSE capture of the ACTIVITY convention (TOOL_CALL_START precedes the first ACTIVITY event; TOOL_CALL_END lands before the tool runs), the serializer probe confirming SubagentStartedEvent camelCases on the wire, and the SDK bump (pyproject + uv.lock + re-exported requirements.txt). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
SubagentStreamHandler drops the text_so_far accumulator: it emits one
message_start {message_id} before the first token and message {message_id,
delta} per token. The task tool emits an error phase (then re-raises) when
the child fails.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… run-wrapping emitter SubagentEmittingAgent wraps LangGraphAgent.run and expands the graph's subagent_activity CUSTOM events 1:N into SUBAGENT_STARTED / attributed TEXT_MESSAGE_START/CONTENT/END / SUBAGENT_FINISHED / SUBAGENT_ERROR (ids <tid>-sub and <tid>-sub-m<n>, tid = the task tool call id). The CUSTOM event is consumed; other CUSTOM events pass through. Replaces the private ACTIVITY_SNAPSHOT/DELTA translator (activity_transform + ActivityEmittingAgent). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…* emitter Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
guide.md describes the standard SUBAGENT_* events and SubagentEmittingAgent (replacing the ACTIVITY walkthrough); the wire-capture doc gains the after-emitter capture (per-token attributed deltas, START -> END -> SUBAGENT_STARTED order measured) and the live browser verification with the running-card screenshot; e2e comments name the new pipeline (assertions unchanged). ag-ui-dev mirror regenerated for the mirrored docs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
… agent class The aggregated ag-ui-dev server emitted `LangGraphAgent(name=..., graph=...)` for every LangGraph topic, but the subagents demo mounts `SubagentEmittingAgent` — a LangGraphAgent subclass that expands the graph's `subagent_activity` CUSTOM events into standard SUBAGENT_* events. The Railway lane therefore served raw CUSTOM events and rendered no subagent cards (the earlier ACTIVITY translator had the same gap). Convention: the topic's own `src/server.py` is the source of truth — no new marker file that could drift from what the demo actually mounts. The generator looks for `agent = <Cls>(` plus a package-relative `from .<module> import <Cls>` line; anything other than the stock `LangGraphAgent` is imported from `deps.<mod>.src.<module>` and constructed with the same name/graph args. An inline `LangGraphAgent(...)` mount keeps the plain wrapper; a subclass that is mounted but not importable from the topic package fails at generation time instead of at container boot. Spec: generator case asserting subagents mounts SubagentEmittingAgent (and interrupts keeps LangGraphAgent), a buildServerPy adapter case, and four detectBridgeAgent parsing cases. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…mittingAgent `npx tsx scripts/generate-ag-ui-deployment-config.ts`. Only server.py changes: one added import and the subagents mount now constructs SubagentEmittingAgent. requirements.txt and deps/ are byte-identical. Boot-checked locally from the deployment root (pip-installed requirements.txt as the Dockerfile does): /ok → 200, /agent/subagents → 401 without X-Internal-Token. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
What changed
The cockpit AG-UI subagents demo (
cockpit/ag-ui/subagents/python) now emits the protocol's standard subagent events instead of the private ACTIVITY convention:SubagentEmittingAgent(src/streaming/subagent_emitting_agent.py) subclasses theag-ui-langgraphbridge and wrapsLangGraphAgent.run(), expanding the graph'ssubagent_activityCUSTOM events 1:N intoSUBAGENT_STARTED→subagentRunId-attributedTEXT_MESSAGE_START/CONTENT/END→SUBAGENT_FINISHED(orSUBAGENT_ERROR). Ids follow the feat(runtimes): strands subagent delegation demo with standard SUBAGENT_* emission #956–feat(runtimes): mastra subagent delegation demo with SUBAGENT_* injection in the bridge #958 convention:<toolCallId>-sub/<toolCallId>-sub-m1,parentToolCallId= thetasktool call id. The CUSTOM event is consumed; other CUSTOM events pass through. Replacesactivity_transform.py+ActivityEmittingAgent(the bridge's_dispatch_eventhook is strictly 1:1 and could not carry the expansion).SubagentStreamHandlerdrops thetext_so_faraccumulator and emitsmessage_start {message_id}once, thenmessage {message_id, delta}per token. Thetasktool emits anerrorphase (then re-raises) when the child fails.ag-ui-protocol>=0.1.22added as a direct dependency (pyproject.toml,uv.lock, re-exportedrequirements.txt) — the first release withsubagent_run_idon every event.deployments/ag-ui-devregenerated (byte-identical mirror; combinedrequirements.txtnow pinsag-ui-protocol==0.1.22).docs/guide.mdrewritten to the standard events +SubagentEmittingAgent; newdocs/wire-capture-subagents.md(baseline, serializer probe, after-emitter capture, browser verification); e2e/component/prompt comments updated.Spec:
docs/superpowers/specs/2026-09-02-agui-demo-subagent-events-design.md. Plan:docs/superpowers/plans/2026-09-02-agui-demo-subagent-events.md(Tasks 0–3; Tasks 4–5 — the examples demo and website docs — follow in separate PRs).Wire capture
cockpit/ag-ui/subagents/python/docs/wire-capture-subagents.mdOrdering finding (design §6): in every delegation round the bridge streams
TOOL_CALL_START→ allTOOL_CALL_ARGS→TOOL_CALL_END→STEP_FINISHED(orchestrator)/STEP_STARTED(tools)before the tool body runs, soSUBAGENT_STARTEDalways follows an already-announced tool call (after-emitter capture: START 7 → END 292 → SUBAGENT_STARTED 306; 1307 → 1586 → 1600; 3037 → 3312 → 3326). TheSUBAGENT_*block nests betweenTOOL_CALL_ENDandTOOL_CALL_RESULT.Streaming finding
Live browser check (real key,
nx serve, Playwright polling every 150ms): the research card mounts onSUBAGENT_STARTEDand its message grows monotonically whilerunning— 22 → 56 → 113 → 147 → 223 → 262 → 299 → 330 → 367 → 401 → 431 → 506 → 540 chars across consecutive samples — reaching 5,336 chars before flipping tocompleteand collapsing. 1,478 attributedTEXT_MESSAGE_CONTENTevents across three delegations, one raw token each (the baseline shipped 2,077ACTIVITY_DELTAs each carrying the full text-so-far). Screenshot:cockpit/ag-ui/subagents/angular/e2e/manual/subagent-card-live.png.Tests
uv run pytest -q(cockpit/ag-ui/subagents/python): 18 passed (4 stream-handler + 14 emitter; the 4 activity-transform tests were deleted with the translator).npx playwright test --config cockpit/ag-ui/subagents/angular/e2e/playwright.config.ts: 1 passed — assertions unchanged (projection-level: name, status,messages()[0].content, card count); aimock fixtures unchanged.SubagentStartedEventreached the wire as{"type":"SUBAGENT_STARTED","subagentRunId":"…-sub","name":"research","parentToolCallId":"…"}with the stock encoder.Deployment generator
scripts/generate-ag-ui-deployment-config.tsemittedLangGraphAgent(name=..., graph=...)for every LangGraph topic, so the aggregated Railway server (deployments/ag-ui-dev/server.py) mounted the stock bridge forsubagentsand served the graph's rawsubagent_activityCUSTOM events — no subagent cards in production (pre-existing; the ACTIVITY translator had the same gap). The generator now reads each LangGraph topic's ownsrc/server.pyforagent = <Cls>(plus a package-relativefrom .<module> import <Cls>and, when<Cls>is aLangGraphAgentsubclass, imports it fromdeps.<mod>.src.<module>and constructs it with the same name/graph args; other topics keep the plain wrapper, and a subclass that is mounted but not importable from the topic package fails at generation time rather than at container boot. No new marker file — the demo's server.py is the single source of truth. Regenerateddeployments/ag-ui-dev/server.py(one import plus thesubagentsmount; requirements.txt and deps/ unchanged), so the Railway lane now runsSubagentEmittingAgent. Boot-checked from the deployment root with the Dockerfile's pip-installed requirements:/ok200,/agent/subagents401 without the internal token. Spec: 18 generator cases pass (6 new),nx test scriptsgreen.🤖 Generated with Claude Code