Skip to content

ACP: subagent work is invisible — forward subagent lifecycle and streams over session updates #2482

Description

@esempe

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/failedpackages/protocol/src/events.ts) as ordinary tool_call / tool_call_update session updates, with the linkage in _meta.kimiCode.subagent:

  • spawnedtool_call with toolCallId: subagent:<subagentId> and _meta.kimiCode.subagent: {event, subagentId, subagentName, parentToolCallId, description?, swarmIndex?, runInBackground}.
  • started/suspended/completed/failedtool_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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions