anthropics / anthropics/claude-code

[Bug] Subagent spawn depth controlled by undocumented remote feature flag, can change without release

Ouverte
#90,038 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
area:agents enhancement platform:macos
Langage dominant
Python
Étoiles
145k
Forks
23.1k
Métriques de merge des PR
Métriques de PR en attente

Description

### Environment
- CLI 2.1.247, macOS darwin-arm64, Max 20x, main loop Opus 5

### What I found

`CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH` controls how many levels of subagents can spawn beneath a subagent. Reading the resolution logic out of the 2.1.247 binary:

```
e = env.CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH; if (e !== undefined) return e;
...
t.maxSubagentSpawnDepthFromGrowthBook = getFeatureValue_CACHED_MAY_BE_STALE(
"tengu_hazel_trellis", Psn
);
...
var Psn = 3
```

So the order is: environment variable, then a **remotely served GrowthBook feature flag** (`tengu_hazel_trellis`), then a hardcoded fallback of **3**.

Three consequences follow from that:

1. **The effective value can change without a release.** It is a server-side flag, so it is not pinned to a version the user installed and does not appear in any changelog. This is consistent with what was observed from the outside: 2.1.217 behaved as depth 1, 2.1.219 behaved as depth 3. From here that reads like a version change. It may just as easily have been the flag moving.
2. **Nothing in the product shows the active value.** There is no output in `/status`, `/context`, or the session header stating how deep spawning is currently permitted. The value is read through a function whose own name says `CACHED_MAY_BE_STALE`.
3. **It is undocumented.** No shipped documentation on this machine names the variable, and a search of this repo returns zero issues mentioning it. A user cannot look it up, and cannot discover it exists unless they read the binary.

### Why it matters

Depth 3 means a subagent can spawn subagents that spawn subagents. A subagent is already invisible while it runs, and per #82104 there is no live spend readout and no per-agent cap, so a three-level tree is invisible work under invisible work with nothing bounding it. The combination is how 750k tokens land after a kill in that issue, and how the 1.37B tokens of agent re-reads in my comment there accumulate without anyone noticing.

An execution parameter that determines the branching factor of unattended, unmetered work is not a good candidate for a silent remote default.

### Ask

1. **Show the resolved value.** Print the active spawn depth wherever the session reports its configuration, along with where it came from: environment, remote flag, or fallback.
2. **Document the variable**, including that a remote flag can override the fallback.
3. **Default to 1.** Nesting should be opt-in. If depth 3 is intentional, say so somewhere the user can read.
4. Log a line when the remote value differs from the fallback, so a change is at least observable after the fact.

Same reasoning applies to `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS`, which is also environment-then-default and also undocumented.

### Workaround

Set it explicitly, since the environment variable is checked first and wins over the flag:

```json
{ "env": { "CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH": "1",
"CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS": "6" } }
```

That is the only way to know what the value is, because setting it is the only way to stop it being decided elsewhere.

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Piste de recherche

No file paths or tests are named. Start by finding where the CLI resolves CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH and CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS, then where /status, /context, session headers, logging, and shipped docs are produced. Done means the resolved value and source are visible or logged as requested, the variable is documented, and the default behavior is agreed with maintainers.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
cli, documentation, observability
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Active
Clarté
Plutôt claire
Accessibilité débutants
45/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.