Subagents & structured-output requests 400 against third-party endpoints requiring a `thinking` field (CC omits `thinking` on those requests)
Subagents (and structured-output requests) fail with 400 against third-party Anthropic-compatible endpoints that require a thinking field — CC omits thinking on those requests
Summary
When Claude Code is pointed at a third-party Anthropic-compatible endpoint via ANTHROPIC_BASE_URL whose model requires a thinking field on every /v1/messages request (Moonshot's kimi-k2.7-code does), the main interactive thread works, but subagents fail immediately with:
API Error: 400 invalid thinking: only type=enabled is allowed for this model
The subagent produces 0 tool uses — its transcript is two lines: the spawn prompt, then the 400. The same failure also hits CC's session-title generation and other structured-output (output_config.format) requests.
Root cause (confirmed by request capture): CC 2.1.181 omits the thinking field on structured-output and certain subagent-spawn requests. The upstream model rejects any /v1/messages request that lacks thinking. No thinking-related env var fixes it, because those requests never pass through CC's thinking-injection path.
Environment
- Claude Code 2.1.181 (native install, Windows 11)
ANTHROPIC_BASE_URL=https://api.moonshot.cn/anthropic(Moonshot, Anthropic-compatible)- Model:
kimi-k2.7-codeviaANTHROPIC_MODELandANTHROPIC_DEFAULT_{OPUS,SONNET,HAIKU}_MODEL - This is a "firstParty"-classified provider (custom base URL, no
CLAUDE_CODE_USE_BEDROCK/VERTEX/...).
Repro
- Configure CC against an Anthropic-compatible endpoint whose model requires
thinkingon every request (Moonshotkimi-k2.7-code). - Start an interactive session — normal chat turns work.
- Trigger a subagent (e.g. a workflow that spawns
Task/Agentsubagents, or anycreate-style skill that fans out). - The subagent dies instantly with
400 invalid thinking: only type=enabled is allowed for this model, 0 tool uses.
Evidence (captured outbound request bodies)
Using a local pass-through proxy as ANTHROPIC_BASE_URL, the actual requests CC sends are:
- Normal chat turn (works):
``json``
{ "model": "kimi-k2.7-code", "thinking": {"type":"adaptive"}, "output_config": {"effort":"max"}, ... }
- Session-title / structured-output request (400s):
``json`
{ "model": "kimi-k2.7-code", "output_config": {"effort":"max","format":{"type":"json_schema", ...}}, ... }
thinking` field at all**.
— note: **no
- Subagent spawn first request (400s): same shape —
thinkingabsent.
Direct tests against the upstream confirm the rule (the model accepts a request iff it carries thinking; the effort value is irrelevant):
| Request body | Upstream response |
|---|---|
| thinking:{type:"enabled",budget_tokens:1024} | ✅ 200 |
| thinking:{type:"adaptive"} (no effort) | ✅ 200 |
| thinking:{type:"adaptive"} + output_config:{effort:"max"} | ✅ 200 |
| output_config:{effort:"max"}, no thinking | ❌ 400 only type=enabled is allowed |
| empty (no thinking, no effort) | ❌ 400 only type=enabled is allowed |
So the upstream's only type=enabled is allowed message is misleading: it actually means "no thinking field was sent." CC's structured-output / subagent requests omit thinking, hence the 400.
Why no env var fixes it
Tested ineffective (the failing requests don't go through the thinking-injection path):
MAX_THINKING_TOKENS=0and=8192CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1(binary shows it's gated to model names containingopus-4-6/sonnet-4-6, so it's a no-op for any other model)ANTHROPIC_DEFAULT_*_MODEL_SUPPORTED_CAPABILITIESset to"",adaptive_thinking,!adaptive_thinking,interleaved_thinking,!effort,!adaptive_thinkingCLAUDE_CODE_DISABLE_THINKING=1(removes thinking from chat turns too → makes the main thread fail the same way)CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
Suggested fix
When the active provider/model requires a thinking field, CC should include thinking on all /v1/messages requests it builds — including structured-output (output_config.format) requests and subagent-spawn requests — not only on regular assistant turns. Even a minimal thinking:{type:"adaptive"} (or {type:"enabled", budget_tokens:N}) on those requests resolves it.
Alternatively, expose a documented per-model override that forces a chosen thinking shape on every request to that model (the existing *_SUPPORTED_CAPABILITIES knob does not currently affect these request paths).
Workaround
A tiny local proxy that injects thinking:{type:"adaptive"} into any /v1/messages request lacking it makes both the main thread and subagents work end-to-end against kimi-k2.7-code.