Agent host renders nothing for a skill that runs in a subagent
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
A skill invoked as a subagent produces no visible output at all. The turn runs for as long as the
skill takes, renders an empty bubble, and completes. The work is real and its result is recoverable
from the SDK transcript afterwards, so nothing is lost except the user's ability to see it.
## Version
- VS Code 1.136.1, commit `a44adf7f53e00964ab890f9f8758a334f1fc15bc`
- Dev container, `linux-arm64` server bundle
- Claude agent host, Claude Code CLI 2.1.239
## Steps to reproduce
1. Open a chat against a workspace with uncommitted or unpushed changes.
2. Run the built in `/code-review`, which runs its reviewer as a subagent.
3. Watch the chat for the duration of the review.
## What happens
The turn shows a spinner and produces nothing. When the review finishes, the turn completes with an
empty response.
On one measured run lasting 10 minutes 8 seconds and making 40 tool calls, the workbench received
exactly these actions on the chat channel:
| Action | Count |
| --- | --- |
| `chat/turnStarted` | 1 |
| `chat/usage` | 1, reporting 0 input and 0 output tokens |
| `chat/turnComplete` | 1, `duration: 607762` |
| `chat/responsePart` | 0 |
| `chat/toolCallStart` | 0 |
The review produced 13.6 KB of findings, recovered afterwards from
`~/.claude/projects///subagents/agent-*.jsonl`. While it ran, that transcript grew
continuously, so the work was plainly in progress the whole time the UI showed nothing.
## Why
A skill that runs in a subagent is spawned by the skill runner rather than by a `Task` tool call, so
its sidechain agent has no tool-use id. Comparing the two shapes:
```
Task spawned {"agentType":"...","description":"...","toolUseId":"toolu_...","spawnDepth":1}
skill spawned {"agentType":"general-purpose"}
```
`SubagentRegistry` is keyed on that tool-use id, so a skill spawned agent is never registered, no
subagent chat is opened, and nothing about it reaches the workbench.
Because the parent model never runs in this shape, the turn reports zero tokens and the entire
product of the turn arrives on the SDK `result` message. In `ClaudeSdkPipeline`, the `result` branch
settles the queue head, logs the uuid, and discards `result` without reading it, so that text is
never surfaced.
## Suggested fix
When a turn completes having emitted no response parts, surface the `result` message's text as a
response part. Guarding on the turn having spent no model tokens is enough to avoid duplicating a
normal turn, whose result text merely repeats the assistant message already streamed. A local patch
along those lines renders the output correctly, verified against both a skill subagent turn and
ordinary turns.
Two things that fix does not cover:
- **Progress while the skill runs.** Nothing about these agents reaches the host during the run, so
there is nothing to render until the result arrives.
- **Surviving a reload.** The host keeps no chat content of its own. `session.db` holds `turns`,
`turn_usage`, `session_metadata` and `chat_drafts`, with no table for response parts, and a chat
re-renders by replaying what the CLI streams on resume. A skill subagent turn leaves no assistant
message in the CLI transcript, so after a reload there is nothing to replay and the turn is empty
again.
## Related symptom, same root cause
Because the parent model never runs, the CLI writes no user or assistant message and never persists
the conversation. Cancelling such a turn in a new chat leaves a transcript holding only a file
snapshot and a couple of queue records. Every later prompt in that chat resumes a session id the CLI
does not know:
```
[Claude] session : resume rebuild agent=(none)
[Claude SDK stderr] No conversation found with session ID:
```
The chat is then unusable permanently. A chat that already has history is unaffected, so this only
bites a chat whose first turn was a cancelled skill subagent.
*AI disclosure: this issue and the related code 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.