anthropics / anthropics/claude-code

[BUG] Initial agent-type listing never emitted on turn 1 of a session created by plan approval with "clear context"

Open
#94,776 0 comments 1 reaction 0 assignees View on GitHub
area:agents area:core bug has repro platform:windows
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

### Preflight Checklist

- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code

### What's Wrong?

In a session that is **created by approving a plan with the "clear context" option** (`showClearContextOnPlanAccept: true`), the harness never emits the initial `agent_listing_delta` attachment on turn 1. The model receives the `Agent` tool schema but no `subagent_type` values, while the tool's own description says:

> Available agent types are listed in `` messages in the conversation.

That reminder is not in the conversation. The model has a tool whose required `subagent_type` parameter has no documented values, so it stops delegating and silently does the work inline instead.

The listing is only emitted many turns later, once the session reaches a turn where the Agent tool is back in the request tool list. In my sample that was between the 2nd and the 49th subsequent turn, 3 to 24 minutes after session start. Worst observed case: **126 consecutive assistant turns with no agent listing at all**.

Restarting "fixes" it only because a fresh session's first turn is an ordinary prompt with an unscoped tool list, so the generator runs and emits the listing immediately. That discards exactly the context the "clear context" option was meant to optimise.

#### Turn 1 of an affected session

```
mode
permission-mode
file-history-snapshot
attachment hook_success
attachment hook_system_message
attachment hook_additional_context
user
attachment instructions
attachment session_context
attachment date
attachment remote_session_change
attachment prompt_snapshot
last-prompt
```

No `environment`, no `model`, no `deferred_tools_delta`, no `skill_listing`, no `agent_listing_delta`.

An ordinary session (typed prompt, or `--continue` / `--resume`) emits the full bundle on turn 1 including `agent_listing_delta` with `isInitial: true`, within seconds.

The full environment bundle does arrive on turn 2 of the affected session. By then a skill that declares `allowed-tools` in its frontmatter is active, the request tool list is scoped, and `agent_listing_delta` is **still** not emitted.

#### Mechanism

The generator of the "Available agent types for the Agent tool:" reminder (2.1.273 build, minified names given only as pointers) is:

```js
async function Fon(e, n) {
if (!e.options.tools.some(U => $t(U, bt))) return [] // bt === "Agent"
...
let y = new Set
for (let U of n ?? []) { // n = message history
if (U.type !== "attachment") continue
if (U.attachment.type !== "agent_listing_delta") continue
for (let fe of hl(U.attachment.addedTypes)) y.add(fe)
for (let fe of hl(U.attachment.removedTypes)) y.delete(fe)
}
let M = h.filter(U => !y.has(U.agentType))
...
if (M.length === 0 && L.length === 0) return []
return [{ type: "agent_listing_delta", ..., isInitial: y.size === 0 }]
}
```

Three properties combine into the defect:

1. **The first guard is a silent `return []`.** If `Agent` is not in `options.tools` when attachments are computed, the listing is never produced for that turn: no warning, no retry marker, nothing in the session record.
2. **Attachments are only computed when a new user message is created**, not inside the tool-use loop. A single prompt driving a long autonomous run gets exactly one chance.
3. **The "already announced" state is reconstructed by scanning message history** for prior `agent_listing_delta` attachments rather than being session state, and nothing re-triggers announcement when the Agent tool re-enters the tool list.

Note the asymmetry with the deferred-tool path, which explicitly carries its discovered-tool set across a compaction boundary (`compact_boundary.preCompactDiscoveredTools`). The agent listing has no equivalent carry-over or re-emission path.

#### Secondary observation (2.1.268, not reproduced on 2.1.273)

On the older build, in three sessions the model called the tool and got:

```
Error: No such tool available: Agent. Agent is disabled for this session, in subagents as well as here.
```

That classifier fires when the tool resolves in the global registry but is not in the tool list sent with that request. Every occurrence happened while a skill declaring `allowed-tools` was active, and `Agent` was explicitly listed in that skill's `allowed-tools`.

The allowed-tools resolver has a branch that makes this silent:

```js
if (Gt === bt) { // allowed-tools entry is "Agent"
if (Ot) { /* parse allowedAgentTypes from "Agent(a,b)" */ }
if (!s && !De.has(bt)) { Ve.push(xt); continue } // pushed to validTools, NOT resolvedTools
}
```

A declared-but-unresolved `Agent` entry is counted as **valid** and skipped. Not reported as invalid, not reported as unavailable, no diagnostic. Possibly relevant: the `Agent` tool carries `aliases: ["Task"]`, and the deny path expands aliases while the allow path does not appear to.

I include this because it shares the root consequence: `Fon()` bails on exactly this condition, permanently for that turn.

### What Should Happen?

1. A session created by the plan-approval handoff should receive the full environment attachment bundle on turn 1, the same as an ordinary first prompt. This alone fixes the reported symptom.
2. The agent listing should re-emit when the Agent tool re-enters `options.tools` after being absent, instead of waiting for the next user message. "Listing announced" should be tracked as session state alongside the history scan, so a context rewrite cannot leave the model permanently without it.
3. A declared-but-unresolved `Agent` entry in `allowed-tools` should be reported rather than silently classified valid, and alias expansion should be consistent between the allow and deny paths.
4. The `Fon()` early return should emit a debug-log line naming the reason. Today this failure leaves no trace at all.

### Error Messages/Logs

```shell
# Secondary observation only (2.1.268), surfaced to the model as a tool_use_error:
Error: No such tool available: Agent. Agent is disabled for this session, in subagents as well as here.

# The primary symptom produces NO error output of any kind.
# It is only visible by inspecting the session transcript for a missing
# agent_listing_delta attachment on turn 1.
```

### Steps to Reproduce

1. Set `showClearContextOnPlanAccept: true` in settings.
2. Enter plan mode, produce a plan, approve it choosing a "clear context" option.
3. In the resulting session, have the first assistant action invoke a skill whose frontmatter declares `allowed-tools` including `Agent`.
4. Inspect the session transcript in `~/.claude/projects//.jsonl`:
- turn 1 has no `agent_listing_delta` attachment
- the first one appears many turns later, with `isInitial: true`

Control: start a session with an ordinary typed prompt, or with `--continue` / `--resume`. The listing lands on turn 1 within seconds, every time.

### Claude Model

Opus

### Is this a regression?

I don't know

### Claude Code Version

2.1.273 (Claude Code)

### Platform

Anthropic API

### Operating System

Windows

### Terminal/Shell

VS Code integrated terminal

### Additional Information

**Evidence.** 19 sessions started by the plan-approval handoff, across two builds:

| build | handoff sessions | listing present on turn 1 | first listing at transcript line | delay |
|---|---|---|---|---|
| 2.1.268 | 11 | 0 / 11 | 27 to 1139 | 3 to 24 min |
| 2.1.273 | 8 | 0 / 8 | 58 to 132 | minutes |

Control group: every session started by an ordinary typed prompt or `--continue` / `--resume` received `agent_listing_delta` with `isInitial: true` on turn 1, at transcript line 13 to 19, within seconds. Correlation with the handoff start is 1.0 in both directions across the sample.

The agent registry itself is healthy: every session announces the same 25 to 29 agent types once it announces anything, and no session ever emitted a `removedTypes` event.

**Ruled out.**

- *Tool search deferral.* `Agent` is in the never-defer set, and across 52 sessions with tool search active it never appeared in a deferred tool list or in `deferred_tools_delta.addedNames`.
- *Agent discovery from disk or plugins.* Every session that announces anything announces the full set. No `removedTypes` events anywhere.
- *Subagent depth limit.* `gv()` clamps its feature-flag value to `>= 1` and defaults to 3; the main loop runs at depth 0.
- *Permission rules.* No `deny`, no `ask`, no `disallowedTools`; both `Agent` and `Task` are in `permissions.allow`.

**Environment details.** Interactive attended session, `permissions.defaultMode: auto`, tool search in default mode, several MCP servers and plugins installed, Git Bash on Windows 11.

**Possibly related but distinct:** #92001, #93171, #80260 all concern agents missing from the registry. This report is about the registry being correct while the *listing attachment* is never delivered.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reproducing the plan-approval handoff with showClearContextOnPlanAccept enabled, then inspect the session transcript under ~/.claude/projects//.jsonl for the missing agent_listing_delta attachment. Trace the Fon() generator and its Agent-tool guard. Done means the first turn receives the listing and it is re-emitted when Agent returns to the tool list, with diagnostics for unresolved allowed-tools entries.

Written by the indexing model from the issue text.

Assessment

Domain
ai, cli, tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.