[FEATURE] Subagents inherit session effort; per-model modelSettings effort does not reach them, multiplying cost in xhigh sessions
Preflight Checklist
- [x] I have searched existing requests. Related requests exist and are linked in Additional Context. This one is filed separately because it covers a different problem: the interaction between session-inherited subagent effort and the per-model
modelSettingseffort defaults added in v2.1.251, and the cost multiplication that results. - [x] This is a single feature request: make subagent effort resolve per model (or per dispatch) instead of inheriting the parent session's level.
Problem Statement
Subagents always inherit the parent session's effort level. The sub-agents docs, "Supported frontmatter fields", effort row: "Overrides the session effort level. Default: inherits from session." The only override is effort: frontmatter on a custom agent definition. The built-in agents (general-purpose, Explore, Plan, claude) have no definition file the user can edit, and the Agent tool has a model parameter but no effort parameter (#77298).
This produces two problems.
1. Cost multiplication in high-effort sessions. An orchestrator running at xhigh dispatches every subagent at xhigh. The model parameter lets the orchestrator route a lookup, a rename, or a one-assertion fix to Sonnet or Haiku, but the effort stays pinned to the session's top level. A fan-out of five to twenty subagents multiplies that. Part of the point of delegating small work is that it runs cheaper than the orchestrator, and effort inheritance removes half of that saving. A user who sets xhigh on their main model and lets Claude fan out subagents gets an army of xhigh workers without a visible signal that this happened. This is a plausible contributor to the recurring "Claude Code burns through my usage" reports.
2. Per-model modelSettings defaults are misleading. Since v2.1.251, /effort saves a per-model level under modelSettings.<model>.effortLevel (settings-reference: "Save an effort level for each model you use"). A user who saves high for Opus reads that key as "Opus runs at high" and expects an Opus subagent to run at high. It does not. Measured below: with Opus saved at high and the session on Fable at xhigh, a subagent dispatched with model: opus ran at xhigh. The global effortLevel key is ignored the same way. So the per-model key governs only the main conversation when that model is the session model, while its name and its docs read as if it governs the model wherever it runs. Nothing in the Agent tool result or /tasks shows the subagent's effort (#85416), so the only signal is token spend.
Measurement
Claude Code 2.1.263, macOS 15.7.9. Settings:
"effortLevel": "high",
"modelSettings": {
"claude-fable-5-1": { "effortLevel": "xhigh" },
"claude-opus-5": { "effortLevel": "high" }
}
Session model: claude-fable-5-1[1m], effort xhigh. No files in ~/.claude/agents/. From that session, two Agent tool calls with subagent_type: Explore and a one-word prompt ("Reply with exactly one word: DONE"), one with model: opus and one with model: sonnet. Each made one API call.
Claude Code writes an effort field on every assistant entry in the transcript JSONL, for the main session at ~/.claude/projects/<project>/<session>.jsonl and for each subagent at ~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl. Reading that field:
| Request | message.model | transcript effort | level saved for that model |
|---|---|---|---|
| main session | claude-fable-5-1 | xhigh | xhigh (modelSettings) |
| subagent, model: opus | claude-opus-5 | xhigh | high (modelSettings) |
| subagent, model: sonnet | claude-sonnet-5 | xhigh | high (global effortLevel, no per-model entry) |
Both subagents ran at the parent session's xhigh. Neither modelSettings[<subagent model>] nor effortLevel applied.
Proposed Solution
Either or both of:
A. Resolve subagent effort per model. When a subagent runs on model X and no effort: frontmatter or per-call override applies, resolve its effort from modelSettings[X].effortLevel, then effortLevel, then the model's default. Do not inherit the parent session's resolved level. This makes the per-model key mean what its name says, and it lets /effort on a model govern that model everywhere it runs.
B. Add a per-dispatch or subagent-scoped override. An effort parameter on the Agent tool next to model (#77298), and/or a subagent-scoped default such as CLAUDE_CODE_SUBAGENT_EFFORT or a settings key (#79135). The orchestrator can then say "Sonnet at medium" for a lookup and "Sonnet at high" for a review, the same way it already picks the model.
In both cases: state in the modelSettings and effort frontmatter docs which levels apply to subagents, and show the resolved effort on every subagent's /tasks row, not only when the definition sets one (#85416, #84047).
Alternative Solutions
- Author custom agent definitions with
model:pluseffort:frontmatter, one file per model-and-effort pair. This works but forks the built-in agents, cannot reach the file-less built-ins, and turns a cost dial into a fleet of near-duplicate agent files. #79866 covers the same friction for plugin-shipped agents. - Lower the session effort. This defeats the purpose of running the orchestrator at high effort.
Priority
High. It is a silent cost multiplier that scales with fan-out width, and the new per-model settings surface makes users believe it is already solved.
Feature Category
Subagents / Agent tool / effort configuration
Use Case Example
Session: Fable 5.1 at xhigh, saved under modelSettings. Opus saved at high. Sonnet has no per-model entry, global effortLevel is high. Haiku has no effort support.
The orchestrator dispatches, in one turn:
- three
Exploreagents withmodel: haikufor file lookups - one
general-purposeagent withmodel: sonnetto implement a small change - one
general-purposeagent withmodel: opusto review it
Expected: the lookups run cheap, the Sonnet agent runs at high (global effortLevel), the Opus agent runs at high (its saved level), or each runs at a level the orchestrator names per dispatch.
Actual, measured above: the Haiku agents ignore effort, the Sonnet and Opus agents run at xhigh. Nothing in the Agent tool result or /tasks shows that.
Additional Context
Related open issues:
- #77298 — add a per-call
effortparameter to the Agent tool - #79135 — subagent-scoped effort default (
CLAUDE_CODE_SUBAGENT_EFFORT, settings key) - #79866 — configure a subagent's model and effort from settings without forking its prompt
- #85416 — subagent effort level is unobservable
- #92002 — frontmatter
effortsilently capped when extended thinking is disabled - #84047 — show model and effort for each running agent
- #91415 — docs: subagent frontmatter
effortfield undocumented (the field is now in the frontmatter table)
Closed precedents: #25669, #39220, #43083, #64706, #67647, #72596.
Docs cited:
code.claude.com/docs/en/sub-agents, "Supported frontmatter fields",effortrowcode.claude.com/docs/en/settings-reference,modelSettingsandeffortLevelentriescode.claude.com/docs/en/model-config, "Adjust effort level", precedence list
Environment: Claude Code 2.1.263, macOS 15.7.9.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗