Repository navigation
feat: report RFD delegations as linked session messages - #1405
Merged
Merged
Conversation
For a client on the subagents RFD, session messages replace the Agent/Task call that launches a child, which its parent is no longer shown: - The launch's prompt goes to both transcripts, as the parent's outgoing view and the child's incoming one. Both views carry the launch's tool use id and name each other with the draft RFD's recipientMessageId and senderMessageId. - A foreground child's answer, from the launch's result, is the child's session message to the parent. In Claude Code's hand-back mode, the child's SubagentHandback call is that message instead, in both transcripts and linked the same way; the launch's result then only says where the report went. - A launch whose child is never exposed, and a failed hand-back, are shown as tool calls after all. The runtime tracks hidden launches by id, since the adapter's own report that closes an unfinished call has no tool name. Replay reports the same messages from the child's transcript. SendMessage calls stay tool calls.
benbrandt
marked this pull request as ready for review
October 23, 2026 11:12
benbrandt
pushed a commit
that referenced
this pull request
Oct 23, 2026
🤖 I have created a release *beep* *boop* --- ## [0.95.0](v0.94.0...v0.95.0) (2026-10-23) ### Features * end a turn at its result for AIR clients with backgroundSubagents ([#1262](#1262)) ([9b3a5c8](9b3a5c8)) * report read-only subagent configuration ([#1417](#1417)) ([6ab670b](6ab670b)) * report RFD delegations as linked session messages ([#1405](#1405)) ([59e292e](59e292e)) * serve experimental ACP v2 ([#1400](#1400)) ([4d378f9](4d378f9)) * show messages typed in other Remote Control clients ([#1371](#1371)) ([5b11f47](5b11f47)) * update to Claude Code 2.1.309 ([#1413](#1413)) ([a1521b6](a1521b6)) ### Bug Fixes * bump fast-uri from 3.1.8 to 3.1.9 ([#1410](#1410)) ([0fe22ae](0fe22ae)) * bump postcss from 8.5.30 to 8.5.31 in the minor group ([#1403](#1403)) ([ecaa2c9](ecaa2c9)) * bump the minor group across 1 directory with 2 updates ([#1416](#1416)) ([f7d6030](f7d6030)) * IJAI-3744 keep a session running while its background tasks are open ([#1399](#1399)) ([e9f986b](e9f986b)) * publish the session title as soon as the CLI has it ([#1406](#1406)) ([50cd76e](50cd76e)) * publish turns that Claude Code starts after end_turn as an async task in v1 ([#1390](#1390)) ([a1d0eee](a1d0eee)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: acp-release-bot[bot] <246668977+acp-release-bot[bot]@users.noreply.github.com>
buvidk1234
pushed a commit
to buvidk1234/zed
that referenced
this pull request
Oct 24, 2026
ACP subagents now get the same inline card as native subagents. The anchor is the parent's outgoing session message to the subagent, which claude-agent-acp now reports when it launches one (agentclientprotocol/claude-agent-acp#1405). The card replaces that message's "To …" row. - **One card per subagent for now.** The first message the parent sends to one of its own subagents becomes the card; later messages to the same subagent stay rows. Until session messages can name each other (agentclientprotocol/agent-client-protocol#2465), nothing links a message to its part of the subagent's transcript or to its outcome, so the card covers the whole subagent. claude-agent-acp sends one such message per subagent, at the launch. - **Status** comes from the subagent's reported state: | Reported state | Card | |---|---| | running, requires action | Running | | idle, with no stop reason, `end_turn`, or one this version doesn't know | Completed | | idle, `cancelled` | Canceled | | idle, `error`, `refusal`, `max_tokens`, `max_turn_requests` | Failed, with the error text | | no state yet, `unknown` | Unknown (new status) | - **Title:** the parent's label for the subagent wins over the subagent's own title, as on the permission row. - **Stop** is offered only while the subagent runs and only when its parent advertises `cancel` for it. The subagent's own titlebar now follows the same rule. It also showed a failed or canceled ACP subagent with a green check, because it read the outcome from a native tool call that ACP subagents don't have. - **Expansion** is keyed by a new `SubagentCardId` (a tool call or a session message), so cards no longer need a tool-call ID. - **Thread search** skips a message drawn as a card, since the card doesn't show its text. - **Redraw fix:** `update_subagent_association` only notified the subagent's thread, so views that read the association from the parent's side (the card, the permission row's label) didn't redraw when it changed. It now emits `AcpThreadEvent::SubagentAssociationUpdated`. Release Notes: - N/A
benbrandt
added a commit
that referenced
this pull request
Oct 24, 2026
In the subagents RFD form, a `SendMessage` call to a child now becomes a message between the two sessions, as a launch's prompt already does (#1405). Before, it was a tool call of its sender plus an unlinked message in the child. Every delegation now has a parent-side message, which a client can anchor a per-delegation card on, and both views name each other with `senderMessageId`/`recipientMessageId`. ## Live - The call is held until its final update. The SDK reports that the message resumed a child before it reports the call's result. - **Message reached an announced child:** the sender gets the outgoing view and the child the incoming one (`linkedSessionMessages`). The call's result isn't shown. - **Message reached no announced child**, for example one sent to the parent: the call is shown after all, with its final status (`unexposedControlFallback`). - **Call a permission request already showed:** it keeps its updates, and its message goes only to the child. ## Replay - A child's history replays right after its launch, so a call from a parent to its child is always matched to its delivery first. - The child's view then names the call, and the sender's view goes out where the call sits. - A call the replay reaches before its delivery stays a tool call, unlinked. That can happen with a child's message to a sibling whose history replays later. `publishPrompt`'s `replacesLaunch` option is now `replacesCall`. ## Testing - **Live:** the existing `SendMessage` tests in `native-subagents.test.ts` and `acp-agent.test.ts` now expect both views and check that the call and its completed result are hidden. A new test checks that a call reaching no announced child is shown with its final status. - **Replay:** the existing test expects the linked views in place of `root tool_call toolu_send`. A new test covers a call reached before its delivery, and fails if delivery ignores that the call was already shown. - `npm run check`, `npm run build` and `npm run test:run` (3301 tests) pass locally. Not tried against a real Claude Code run yet.
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.
Summary
For a client on the subagents RFD (every ACP v2 client, and v1 clients that declare
subagents), session messages now replace the Agent/Task call that launches a child. The parent no longer sees that tool call. AIR's form is unchanged.session_messagein both transcripts: the parent's outgoing view and the child's incoming one. Both use the launch's tool use id, and each names the other withrecipientMessageId/senderMessageIdfrom feat(unstable): link session message views and keep identity off chunks agent-client-protocol#2465.session_messageto the parent (<launch id>:reply). It uses the result asAgentReporterrenders it, so the model-facingagentId: …line and<usage>block are gone. A failure or cancellation comes from the child'sidlestop reason, which it already reported. A background launch's result gets no reply.SubagentHandbackcall; the Agent result then only says that the report "was delivered to you as a message". That call is reported as the child's message to the parent, in both transcripts and linked the same way, and the launch's reply is skipped for that run. A failed hand-back delivered nothing, so it stays a tool call of the child.unexposedControlFallback, the formerfailedControlFallback).toolName, so the runtime tracks hidden launches by id to keep that report from reaching the client for a call it never saw.Do not merge before agentclientprotocol/agent-client-protocol#2465 settles the field names: a merge to
mainpublishes a preview right away. Clients on the published schema ignore the two fields (nodeny_unknown_fieldsin the Rust schema; the scenario validation with the SDK's zod schema passes).Testing
npm run build,npm run checkandnpm run test:runpass (57 files, 4 skipped as before).subagent-*.jsonlscenario snapshots changed: the launch's tool-call updates are gone, the parent gets the outgoing view, the child's view carriessenderMessageId, and foreground results became:replymessages. AIR snapshots are unchanged.session/resumewith replay in a fresh process. Live and replay both showed the linked prompt (parent → child), the linked hand-back "PONG" (child → parent), and no Agent tool call.