Problem
Over ACP, subagent work is invisible: the adapter drops every non-main-agent event at the isFromMainAgent guard in packages/acp-adapter/src/session.ts (runTurnBody). An ACP client sees the parent Agent tool call and then nothing until it completes — no spawn signal, no per-tool progress, no completion summary. In the TUI the same information is rendered live from subagent.* events (src/tui/controllers/subagent-event-handler.ts).
Related: #2131 (subagents as first-class observable sessions), #2163 (agent-initiated turns never emit session/update).
Proposal
Forward the existing internal events (subagent.spawned/started/suspended/completed/failed — packages/protocol/src/events.ts) as ordinary tool_call / tool_call_update session updates, with the linkage in _meta.kimiCode.subagent:
spawned → tool_call with toolCallId: subagent:<subagentId> and _meta.kimiCode.subagent: {event, subagentId, subagentName, parentToolCallId, description?, swarmIndex?, runInBackground}.
started/suspended/completed/failed → tool_call_update against that card; completion carries resultSummary/usage/contextTokens, suspension reason, failure error.
- The subagent's own
assistant.delta / thinking.delta / tool.call.* frames are forwarded (guard relaxed) with _meta.kimiCode.subagentId so clients can nest them under the subagent's card.
- Capability advertised as
agentCapabilities._meta.kimiCode.subagentEvents.
Why standard frames + _meta instead of a custom sessionUpdate kind: v1 SDKs parse SessionUpdate as a closed union and silently drop unknown kinds, and the v2 enum-extension draft reserves non-underscore discriminator values for ACP. This is the same pattern claude-agent-acp uses for subagent progress (namespaced _meta on tool calls), and it stays compatible with every existing client — they see a flat but complete tool stream.
The shape also lines up with the direction of the open subagent RFD in the spec repo (agentclientprotocol/agent-client-protocol#855: tool calls with subagent linkage metadata), so a future migration to whatever that RFD stabilizes is a mapping change, not a redesign.
I have this implemented and tested in my fork (happy to open a PR immediately): ~350 lines with tests, additive-only diff.
Problem
Over ACP, subagent work is invisible: the adapter drops every non-main-agent event at the
isFromMainAgentguard inpackages/acp-adapter/src/session.ts(runTurnBody). An ACP client sees the parentAgenttool call and then nothing until it completes — no spawn signal, no per-tool progress, no completion summary. In the TUI the same information is rendered live fromsubagent.*events (src/tui/controllers/subagent-event-handler.ts).Related: #2131 (subagents as first-class observable sessions), #2163 (agent-initiated turns never emit session/update).
Proposal
Forward the existing internal events (
subagent.spawned/started/suspended/completed/failed—packages/protocol/src/events.ts) as ordinarytool_call/tool_call_updatesession updates, with the linkage in_meta.kimiCode.subagent:spawned→tool_callwithtoolCallId: subagent:<subagentId>and_meta.kimiCode.subagent: {event, subagentId, subagentName, parentToolCallId, description?, swarmIndex?, runInBackground}.started/suspended/completed/failed→tool_call_updateagainst that card; completion carriesresultSummary/usage/contextTokens, suspensionreason, failureerror.assistant.delta/thinking.delta/tool.call.*frames are forwarded (guard relaxed) with_meta.kimiCode.subagentIdso clients can nest them under the subagent's card.agentCapabilities._meta.kimiCode.subagentEvents.Why standard frames +
_metainstead of a customsessionUpdatekind: v1 SDKs parseSessionUpdateas a closed union and silently drop unknown kinds, and the v2 enum-extension draft reserves non-underscore discriminator values for ACP. This is the same pattern claude-agent-acp uses for subagent progress (namespaced_metaon tool calls), and it stays compatible with every existing client — they see a flat but complete tool stream.The shape also lines up with the direction of the open subagent RFD in the spec repo (agentclientprotocol/agent-client-protocol#855: tool calls with subagent linkage metadata), so a future migration to whatever that RFD stabilizes is a mapping change, not a redesign.
I have this implemented and tested in my fork (happy to open a PR immediately): ~350 lines with tests, additive-only diff.