[Feature Request] Add per-subagent effort/thinking control to align with Agent SDK
Bug Description
Feature request: per-subagent effort/thinking control — align Claude Code with the Agent SDK
We build a multi-agent plugin (dev-squad) on the Dynamic Workflow tool. It routes ~16 agent roles
per run to different models (haiku/sonnet/opus/fable via agent({model})), but there is NO way to
control reasoning effort per agent or per stage:
- Workflow agent() silently ignores everything except model/schema/phase/label/isolation/agentType.
We probed this empirically: passing effort:'banana' (an invalid enum) completes with no error,
proving effort, thinking, budget_tokens, and output_config are dropped before reaching
the API. Silent acceptance of unknown opts also hides the limitation — an error would be kinder.
- Subagent frontmatter only supports
model: inherit|sonnet|opus|haiku— no effort field either
(same gap as github.com/anthropics/claude-code/issues/25669).
- The session-level /effort setting propagates to all subagents but lands non-uniformly because it
is model-gated (haiku: none; sonnet: xhigh→high silent fallback; opus/fable: full range). So one
session knob cannot express "deep critic, shallow mechanical steps" — the model tier becomes the
only effort lever, which conflates capability, context window, and cost.
The Agent SDK already exposes thinking control when launching agents (options.thinking / adaptive
thinking + output_config.effort on the Messages API). Please align Claude Code's subagent surfaces
with that:
- accept
effort(low/medium/high/xhigh/max) in Workflow agent() opts and in the Agent tool /
subagent frontmatter, with the same documented per-model silent-fallback semantics as /effort;
- or at minimum, error on unknown agent() opts instead of swallowing them.
Concrete impact: in a single /squad run our fable-tier critic (commit gate) and our haiku-tier
mechanical steps are forced to share the session's effort. Running the session at low to save cost
degrades exactly the high-leverage roles; running at high overpays on roles that don't need it.
Per-agent effort would let orchestrators spend reasoning where the leverage is — the same argument
that justified per-agent model selection, which already exists.
Environment Info
- Platform: darwin
- Terminal: vscode
- Version: 2.1.173
- Feedback ID: 5021e3a5-c07b-4800-b4bf-ba3eee8f6185
Errors
[]
4 Comments
Yes!
Code-level root cause (2.1.187), a regression bisection, and the
MAX_THINKING_TOKENSoverride tested — adding to confirm & sharpen this report.effortisn't "dropped before the API" — the thinking resolver structurally ignores itThe per-turn resolver that builds the request's
thinkingfield is:It reads only
options.thinkingConfigandmax_thinking_tokenspermission layers. It never readseffort.effortis plumbed as a separate top-level request field (defaulthigh), and per the binary's embedded API-guide string it's a depth dial that only does anything oncethinkingis already adaptive/enabled ("adaptive thinking is off by default"). Grepping for any code mappingeffort → an enabled thinkingConfigreturns nothing — so effort cannot turn thinking on by itself.The interactive session sets
{type:"adaptive"}at startup. The Task/workflow spawn path threads in a config that resolves to disabled/undefined. And subagent frontmatter exposes onlyeffort, neverthinking/thinkingConfig— so there is no frontmatter (oragent()opt) that can set the one valueyilactually reads. The result: the request carrieseffortbut no enabledthinking, and the model doesn't think.This is a regression, not a never-implemented feature
Workflow
agent()spawns did produce thinking blocks on 2.1.170 (verified in stored transcripts), and produce zero on 2.1.179 and 2.1.187. So it broke somewhere in the 2.1.170 → 2.1.179 window — there's a specific range to bisect.MAX_THINKING_TOKENSdoes NOT reach spawns (tested)yildoes honor amax_thinking_tokenslayer, whichMAX_THINKING_TOKENS(env) feeds. I tested whether that override propagates to a spawned subagent on 2.1.187:So the only architecturally-supported override enables the main loop but is not applied to spawned agents. There is currently no supported way to get a non-fork subagent to think.
Reproduce in one line
Grep any spawned agent's
.jsonlfor"type":"thinking": 0 for Task/workflow spawns at everyeffort(low…xhigh), while forks/teammates inherit the parent's adaptive config and do think. (Detection validated: same grep finds thinking blocks in the main-loop transcript and in fork transcripts on the same build, so 0 isn't a stripping artifact.)What stays inferred
The exact caller assignment that hands the disabled config to the Task/workflow spawn — traced to the spawn site and matched to the observed 0-thinking, but not isolated to a single line.
Related: #43083 (frontmatter
effortno-op on Task spawns), #14321 (enable extended thinking for subagents), #31536 (closed — per-agenteffortLevel, closed once it was realized thinking itself isn't enabled for subagents).Investigated with Claude Code (Opus 4.8) by reading the 2.1.187 bundle + transcript probing. Co-authored-by: Claude <noreply@anthropic.com>
Adding a concrete production repro for this gap, since it maps directly to point 2 above (no per-subagent thinking override in
.claude/agents/*.mdfrontmatter).Setup: a
.claude/agents/deep-research.mdsubagent with frontmatter:No
thinkingfield (there is no such frontmatter key to set).What happened: when the parent interactive session had extended thinking disabled, spawning this subagent failed with:
Per
code.claude.com/docs/en/sub-agents.md(v2.1.198+): subagents inherit the parent session's thinking on/off state and cannot override it. So the subagent's owneffort: xhighcombined with an inheritedthinking: disabledtriggers the model's documented constraint (Opus 5 rejectsthinking:disabledateffort: xhigh/max, legal only athighor below) — even though nothing in the subagent's own definition asked for thinking to be off.This means any agent template pinning
effort: xhigh/maxon an opus-tier model is a landmine that depends entirely on the parent session's thinking state at spawn time — a piece of state the agent author has no visibility into and the harness gives no way to override per-agent. We worked around it on our side by capping affected agents toeffort: high(unconditionally legal regardless of thinking state) and adding a static lint to prevent reintroducing the combination, but that's a capability downgrade, not a fix — the actual fix is what this issue is asking for: a per-subagent way to set/force thinking (or at minimum, a per-agent frontmatter field), so effort and thinking aren't silently coupled to whatever the parent session happens to be in.Both surfaces support per-agent effort now:
--agentsJSON) acceptseffort: low|medium|high|xhigh|max, overriding the session level while that subagent runs. Docs: https://code.claude.com/docs/en/sub-agentsagent(prompt, { effort: 'low' | 'medium' | 'high' | 'xhigh' | 'max' })per call, with the same per-model fallback semantics as/effort.This is in a recent release: https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md. Closing; please reopen if it's not taking effect on your build.
🤖 Generated with Claude Code