anthropics / anthropics/claude-code
[Bug] CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS is skipped when ultracode is active — a Workflow ran 7 agents under a cap of 3 (2.1.261)
- Lingua principale
- Python
- Stelle
- 145k
- Fork
- 23.1k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
Measured 2026-09-05 on one Linux host. Everything below is reproducible with the commands shown. Related but distinct: #80082 (docs omitted the cap) and #90483 (Workflow concurrency derives from CPU count) — this report is about the guard being *skipped*, not undocumented.
## Summary
The subagent launch guard in Claude Code 2.1.261 returns early, without checking the concurrency cap, when the session is in ultracode. `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` therefore never gated the primary executor that ultracode uses (the Workflow tool's agents), and a session with the cap set to 3 ran seven subagents at once. The documentation states the exemption in one sentence; the impact — the cap does not apply to the one mode designed to fan out — is not stated.
## Environment
| | |
|---|---|
| Claude Code | `2.1.261` (`BUILD_TIME 2026-09-04T16:49:50Z`, `GIT_SHA 1349cf9c224caea8b7721f717418645e28ebacb8`); binary `~/.local/share/claude/versions/2.1.261`, sha256 prefix `4ae40dd1784e8575` |
| OS | Linux 6.8.0-90-generic, x86_64, 48 CPUs |
| Settings | `~/.claude/settings.json` `env.CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS = "3"`, `CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH = "1"`, `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS = "1"` |
| Effort | `/effort` → "Set effort level to ultracode (this session only): xhigh + dynamic workflow orchestration" |
## Observation 1 — the launch guard, from the binary
```
strings -n 8 ~/.local/share/claude/versions/2.1.261 \
| grep -o 'tn=()=>{let as=N7n();if(t.taskRegistry.getConcurrentSubagents(){let as=N7n();
if(t.taskRegistry.getConcurrentSubagents()/`.) The Workflow runtime's own concurrency is `min(16, availableParallelism() − 2)` — 16 on this host — and that, not the env var, bounded the run.
Also measured in the same session family: the guard's message never appeared in any transcript; `SubagentStart` hook events fire for these agents with `agent_type: "workflow-subagent"`.
## Expected vs actual
- Expected: with `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS=3`, no more than 3 subagents run at once, for any executor, or the documentation states plainly that ultracode is the exception and how to cap it.
- Actual: under ultracode the cap is skipped in code; the Workflow tool runs up to 16 agents concurrently; the only mention is one sentence in the sub-agents page.
## Impact
Operators who set the env var to bound cost and host load (and audit it after the fact) have no bound in the mode designed to fan out. A cap that exempts its heaviest producer is not a cap.
## Workaround that works (measured)
A `SubagentStart` hook that counts live agents and exits 2 when the count would exceed the cap. `SubagentStart` fires for the Agent tool, for Workflow-spawned agents and for `SendMessage` resumes, carries `agent_id`, and exit 2 prevents the spawn. Measured: 28 Agent dispatches in one message under a hook cap of 2 → never more than 2 running, 11 refused before spawn, the rest ran as slots freed.
## Suggested fixes (any one)
1. Apply the cap to Workflow-spawned agents and resumes; drop the ultracode early return, or
2. Make the exemption opt-in (`CLAUDE_CODE_ULTRACODE_IGNORES_CONCURRENCY_CAP=1`) and default to enforced, or
3. Expose the Workflow runtime's concurrency (`min(16, cpus−2)`) as a setting and document that `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` does not bound it.
Whichever is chosen: state the behaviour in the `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` documentation itself, next to the variable.
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Direzione di ricerca
Start with the reproduction commands and the versioned binary at ~/.local/share/claude/versions/2.1.261, then compare the guard behavior with the sub-agents documentation at code.claude.com/docs/en/sub-agents. Review workflows/wf_c7fc31c7-66a.json and subagents/workflows/wf_c7fc31c7-66a/journal.jsonl while checking the reported concurrency and hook observations. Done means the selected behavior is verified for Workflow agents and resumes, with the CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS documentation stating the resulting rule.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Ambito
- cli, documentation, tooling
- Tipo di issue
- Bug
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Attiva
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 35/100