Forked Skill subagents are invisible: no correlation handle from the tool call to the agent id
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
A slash command that forks (`/code-review`, and any skill with forked execution) runs its work in a real subagent with its own transcript, but the agent host does not recognise it as a subagent. The work is unreachable from the UI: no subagent chat channel, no card, no way to open it.
The visible symptom is a chat that narrates over content the user was never shown. In the run below the assistant wrote "F2 confirmed", "F6 is outside the review scope" and "Eight confirmed by reading the code", all referring to a numbered findings list produced inside the subagent. The user sees the reactions and never the findings.
## What actually happens
The parent makes an ordinary tool call:
```json
{"type":"tool_use","id":"toolu_01QTjtpnWxdA33bwrFPVsVP9","name":"Skill",
"input":{"skill":"code-review"},"caller":{"type":"direct"}}
```
That fork produced a subagent transcript of 590,596 bytes next to the parent session, with metadata carrying no tool-use id:
```json
{"agentType":"general-purpose","spawnDepth":1}
```
Its records are `isSidechain: true` and share the parent's `sessionId`. The parent transcript contains **zero** `isSidechain` records, so none of that work is inlined into the parent stream. The parent references the agent exactly once, in the structured result of the tool call:
```json
"toolUseResult":{"success":true,"commandName":"code-review","status":"forked",
"agentId":"ac3a4fb7183a061ed","result":"..."}
```
and the tool result text begins `Skill "code-review" completed (forked execution).`
## Why nothing surfaces it
`SUBAGENT_TOOL_NAMES` in `claudeSubagentRegistry.ts` is `new Set(['Task', 'Agent'])`, so a `Skill` call never reaches `recordSpawn` and no subagent channel is created.
Adding `Skill` to that set is not sufficient on its own, and would make things worse: it would create a subagent entry that can never be resolved, because none of the three lookup strategies can map this tool call to its agent id.
- `TextSuffixStrategy` scans the result text for the synthetic `agentId: ` suffix the SDK appends to `Task` and `Agent` results. A forked `Skill` result does not carry it (verified against an 11,942 character result).
- `PromptMatchStrategy` compares the subagent's first user message to the parent tool call's prompt. A `Skill` call's input is `{"skill":"code-review"}` and has no prompt to match on.
- `NativeStrategy.lookup` returns `undefined`; it is a placeholder.
Enumeration is not the problem. `IClaudeAgentSdkService.listSubagents` and `getSubagentMessages` already find this agent. The missing piece is a correlation handle from the tool call to the agent id, and the one that exists (`toolUseResult.agentId`) is a CLI transcript enrichment that `SessionMessage` does not expose:
```ts
export declare type SessionMessage = {
type: 'user' | 'assistant' | 'system';
uuid: string;
session_id: string;
message: unknown;
parent_tool_use_id: string | null;
parent_agent_id: string | null;
};
```
## What would fix it
Either would be enough, and the first is the smaller change:
1. Append the same synthetic `agentId: ` suffix to forked `Skill` results that `Task` and `Agent` results already carry. `TextSuffixStrategy` then resolves them with no change to its logic, and `Skill` can join `SUBAGENT_TOOL_NAMES`.
2. Expose the agent id on the tool result reaching the host (or on `SessionMessage`), and add a strategy that reads it.
Environment: agent host in a dev container, `@anthropic-ai/claude-agent-sdk` 0.3.239.
## Unrelated observation from the same logs
During these runs the host repeatedly discards SDK messages of type `command_lifecycle` for having no turn id. That type appears in neither `sdk.d.ts` nor `agentSdkTypes.d.ts` at 0.3.239, and nothing in the agent host references it, so it looks like an untyped message the host has no handling for. Mentioning it here rather than opening a second issue, since it shows up on exactly the same code path.
*AI disclosure: this issue and the related investigation were written with the assistance of AI.*
### Public patches and patcher scripts
[Public patch catalog and patcher scripts](https://github.com/RyanEwen/vscode-patches/blob/main/CATALOG.md) · [Source patch index](https://github.com/RyanEwen/vscode-patches/blob/main/SOURCE-PATCHES.md). The [public collection](https://github.com/RyanEwen/vscode-patches) includes the maintained patchers, rollback instructions, regression scripts, and historical snapshots. Build restrictions and exact installer coverage are documented there.
Contributor guide
Assessment
This issue has not been assessed yet.