Subagent auto-compaction uses the main session's context window, so subagents on a smaller-window model are never compacted and die with a 400
Environment
- Claude Code 2.1.220 (also reproduced on 2.1.207 through 2.1.216)
- macOS 15 (darwin 25.5.0), arm64
- Mixed-model setup: coordinator on a 1M-context Claude model, subagents pinned to a third-party model with a 372k window, reached through an Anthropic-compatible gateway
Summary
options.mainLoopModel — the session's model — is what auto-compaction resolves its context window from. A subagent pinned to a different model via model: in its agent definition therefore inherits the coordinator's window rather than its own.
When the coordinator's window is larger than the subagent's, the compaction threshold sits above the subagent's real ceiling and can never be reached. The subagent grows until the upstream rejects the request:
API Error: 400 Your input exceeds the context window of this model.
The whole subagent run is lost — no partial result reaches the caller, and re-running the same task fails identically.
Evidence
1. The coordinator's model decides whether subagents compact
45 days of local transcripts, grouped by session. Subagent model is identical in every row (a 372k-window model); only the coordinator's model differs. Spans Claude Code 2.1.207 → 2.1.216, so the client version is not the variable.
| Coordinator model | subagent transcripts | any compaction | peak tokens |
|---|---|---|---|
| 372k-window model | 11 / 8 | 6 / 1 | 167k / 204k |
| 1M Claude model A | 710 / 527 / 136 | 0 / 0 / 0 | 371.5k |
| 1M Claude model B | 267 / 121 / 110 | 0 / 0 / 0 | 371k |
Peaks in the failing rows pin at ~371.5k, i.e. the subagent model's hard ceiling.
2. When it does compact, it compacts at the coordinator's threshold
In sessions whose coordinator ran the 372k model, subagent compaction fires exactly where a 200k window predicts (window - 13000 = 187000):
compact_boundary trigger=auto preTokens=168139
compact_boundary trigger=auto preTokens=170965
compact_boundary trigger=auto preTokens=174076
compact_boundary trigger=auto preTokens=178187
compact_boundary trigger=auto preTokens=180766
3. Minimal end-to-end reproduction
Coordinator claude-opus-5, subagent pinned to the 372k model, subagent driven past the threshold.
- Without
CLAUDE_CODE_AUTO_COMPACT_WINDOW: subagent never compacts; with enough work it reaches ~372k and returns the 400 above. - With
CLAUDE_CODE_AUTO_COMPACT_WINDOW=100k: subagent compacts (trigger=auto,preTokens=77132) and completes normally, while the coordinator is unaffected in the same run.
That the env var fixes it is itself the evidence that the window — not the model routing — is what is wrong.
Impact
Any mixed-model orchestration where a subagent's model has a smaller context window than the session's. The larger the coordinator's window, the more reliably its subagents die: a 1M coordinator makes a 372k subagent's compaction threshold unreachable by construction. Locally this produced 58 lost subagent runs in 20 days, several after more than an hour of work.
What does not work around it
CLAUDE_CODE_MAX_CONTEXT_TOKENS— only consulted for models whose id does not start withclaude-; the window is taken from the coordinator's model, which does.autoCompactWindowsCache(per-model map in~/.claude.json) — gated on the first-party check, so it has no effect behind a gateway. Writing correct per-model entries changed nothing in our tests.- Subagent frontmatter — the 16 supported fields include no context window, compaction, token budget, or per-agent environment field.
- Agent teams — an in-process teammate shares the lead's
sessionIdand is recorded withisSidechain: true, so it inherits the same window.
The only effective control is CLAUDE_CODE_AUTO_COMPACT_WINDOW, and it is process-global: it is a floor for every model in the process, so protecting the subagents also caps the coordinator. There is no way to express "compact this subagent at its own model's window".
Suggested fix
Resolve the auto-compact window from the model that will actually serve the request — the subagent's own model when one is pinned — instead of options.mainLoopModel. Failing that, expose a per-agent override (for example a contextWindow or autoCompactWindow field in subagent frontmatter) so mixed-model setups can declare the real ceiling.
Notes for maintainers
Values outside [100000, 1000000] are silently discarded, so a misconfigured CLAUDE_CODE_AUTO_COMPACT_WINDOW looks applied but is not. A warning on out-of-range values would have saved several hours of misdiagnosis here.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗