ai newsDo., 5. Nov.
EilmeldungOpenAI’s Patch the Planet Brings AI-Assisted Patching to Open Source Security

Your Claude Code Subagents Inherit Your Effort Level. 2.1.316 Lets You Set Them Lower

Book: Observability for LLM Applications Also by me: Thinking in Go (2-book series) — Complete Guide to Go Programming + Hexagonal Architecture in Go My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools Me: xgabriel.com | GitHub Three Explore s

dev.toDonnerstag 02:01 · 05.11.9 Min. Lesezeit
Bild: dev.to

Posted on Nov 5 • Edited on Nov 5 • AI-assisted

Three Explore subagents sent out at high to find every caller of the one function you're refactoring. Until Claude Code 2.1.316, that is what a high session got you: a subagent with no effort of its own inherited the session's, unless Claude named a level when it spawned it.

The changelog entry for 2.1.316, dated October 31, 2026, reads: "Added CLAUDE_CODE_SUBAGENT_EFFORT to set the effort level subagents run at when nothing else names one, instead of inheriting the session's."

The official docs stop there. The environment variable reference doesn't list the variable yet, so everything below about its behaviour comes from that entry plus the documented effort rules around it. What it saves depends on your repo, and the transcripts overcount if you sum them naively.

Effort controls adaptive reasoning. The model configuration docs put it plainly: "Lower effort is faster and cheaper for straightforward tasks, while higher effort provides deeper reasoning for complex problems." The levels run low, medium, high, xhigh, max, depending on the model. Opus 5.5, Sonnet 5.5 and Haiku 5.5 default to medium when nothing sets a level. Thinking tokens are billed as output tokens, so effort shows up directly in the bill.

"When nothing else names one" is doing the work here. Three things already name an effort for a subagent, per the subagents docs:

So if you export CLAUDE_CODE_EFFORT_LEVEL, that is something naming a level, and the new variable has nothing left to decide. Unset it for this experiment.

Explore is where this lands. The docs describe the built-in Explore subagent as read-only (Write and Edit are denied), used for "file discovery, code search, codebase exploration", running on the main conversation's model. They list no effort level for it, so unless Claude passes one at spawn time, Explore is exactly the "nothing else names one" case. Effort and model are separate knobs: CLAUDE_CODE_SUBAGENT_MODEL on its own doesn't change the model Explore and Plan run on, per the same page.

The session keeps its effort. Subagents with nothing else set get their own.

Check your version first. You need 2.1.316 or later:

claude --version claude update Enter fullscreen mode Exit fullscreen mode Then give each run its own folder, so neither one sees the other's session history or files:

cd ~/code/app git worktree add -b effort/inherit../app-inherit git worktree add -b effort/low../app-low Enter fullscreen mode Exit fullscreen mode Pick a task that makes Claude explore and doesn't need edits. Asking it to find something you can check yourself works well, because it gives you a ground truth for the quality check later:

TASK = 'Use Explore subagents to find every place this repo reads an environment variable. List each one as file:line and the variable name. Do not edit anything.' Enter fullscreen mode Exit fullscreen mode Write down the answer key now, with plain git grep. Adapt the pattern to your stack:

git grep -n -E 'process\.env|os\.Getenv|getenv\(' \ > ~/env-reads-baseline.txt wc -l ~/env-reads-baseline.txt Enter fullscreen mode Exit fullscreen mode Run it twice and read the totals Pin the model and the session effort in both runs, so the only difference is the subagents' effort. With --output-format json, the headless docs say the payload includes total_cost_usd and a per-model cost breakdown. The cost tracking guide adds that total_cost_usd counts subagent requests alongside the main loop.

cd ~/code/app-inherit claude -p " $TASK " --model opus --effort high \ --max-budget-usd 3 --output-format json \ > ~/effort-inherit.json cd ~/code/app-low CLAUDE_CODE_SUBAGENT_EFFORT = low \ claude -p " $TASK " --model opus --effort high \ --max-budget-usd 3 --output-format json \ > ~/effort-low.json Enter fullscreen mode Exit fullscreen mode --max-budget-usd is a guard: subagent spend counts toward the cap, and spend can pass it, so leave headroom. Since v2.1.302, a claude -p run starts in Manual mode when nothing sets a permission mode, and a call that needs approval is denied with nobody there to give it. For a read-only comparison, that is what you want.

for f in ~/effort-inherit.json ~/effort-low.json; do echo " $f " jq '{cost:.total_cost_usd, models: (.modelUsage | map_values({costUSD, outputTokens}))}' " $f " done Enter fullscreen mode Exit fullscreen mode Those dollar figures are client-side estimates computed from token counts at list price, not your bill. On a Pro, Max or Ultra plan the dollar amount isn't what you pay at all, but the token counts still tell you which run drew more of your limits.

One pair of runs is an anecdote. Claude decides how many Explore agents to start and how thorough each should be (quick, medium or very thorough, per the docs), so the same prompt can fan out differently twice. Run each side three times, alternate which goes first, and compare the medians.

The totals tell you whether the low run was cheaper. The transcripts tell you how much of it was the subagents. Subagent transcripts live under ~/.claude/projects/{project}/{sessionId}/subagents/, one agent-{agentId}.jsonl per subagent.

Don't sum every usage object in those files. One API response that contains several content blocks is written as several assistant entries that share one message.id and carry the same usage. A maintainer confirmed in issue #87303 that this is intended: "Consumers are expected to count each message.id once". The reporter's sample overcounted cache writes by 1.92x when summed naively. The cost tracking guide also warns that per-step output_tokens is a placeholder, so take output totals from the run's JSON above, not from the transcripts. I wrote up the full set of traps in a separate post on summing transcript usage.

This shell function counts each response once, across every subagent file of one session, and reports the input and cache tokens:

sub_usage () { find ~/.claude/projects -path "*/ $1 /subagents/*" \ -name 'agent-*.jsonl' -exec cat {} + | jq -cR 'fromjson? // empty | select(.type == "assistant") | select(.message.id and.message.usage) | {id:.message.id, u:.message.usage}' | jq -s 'unique_by(.id) | map(.u) | { responses: length, input: (map(.input_tokens // 0) | add), cache_write: (map(.cache_creation_input_tokens // 0) | add), cache_read: (map(.cache_read_input_tokens // 0) | add) }' } sub_usage " $( jq -r.session_id ~/effort-inherit.json ) " sub_usage " $( jq -r.session_id ~/effort-low.json ) " Enter fullscreen mode Exit fullscreen mode fromjson? // empty skips a line that doesn't parse instead of stopping, and entries with no message.id are dropped rather than lumped together. Count how many subagents each run started, too. If the low run started fewer, part of any difference is fan-out, not effort:

SID = $( jq -r.session_id ~/effort-low.json ) find ~/.claude/projects -path "*/ $SID /subagents/*" \ -name 'agent-*.jsonl' | wc -l Enter fullscreen mode Exit fullscreen mode Then check quality against the answer key. Pull the file:line pairs out of each answer and count what each run missed from the baseline:

cut -d: -f1,2 ~/env-reads-baseline.txt | sort -u \ > ~/key.txt for a in inherit low; do jq -r.result ~/effort- $a.json | grep -oE '[A-Za-z0-9_./-]+:[0-9]+' | sort -u \ > ~/ans- $a.txt echo " $a missed: $( comm -23 ~/key.txt ~/ans- $a.txt | wc -l ) " done Enter fullscreen mode Exit fullscreen mode The match only works when the answer uses the same repo-relative paths git grep prints, so skim comm -23 ~/key.txt ~/ans-low.txt before you trust the count. A cheaper run that missed four of thirty env reads did not save you anything. If low drops results on your repo, try medium before giving up on the setting.

I build Hermes IDE, so weigh this section with that in mind. The headless runs above are the measurement. Hermes is for watching the interactive version, where you see the agents work as they go.

Press ⌘N (Ctrl+Shift+N on Windows and Linux) twice and start two Claude Code tasks on the same repo. Each gets its own hermes/ branch and worktree. Set the model chip to Opus and the effort chip to high in both. Give both the same cheap first task, such as "Summarize README.md in two sentences", then split the panes so they sit side by side. The sidebar shows each session's spend: the cost the agent reports, or an estimate from its transcript marked as estimated, with token totals.

Hermes 2.3.4: two real agent sessions in split panes, each in its own hermes/ worktree, with status, context use, cost and branch per session in the sidebar.

Find the second task's folder with git worktree list and create.claude/settings.local.json in it:

{ "env": { "CLAUDE_CODE_SUBAGENT_EFFORT": "low" } } Enter fullscreen mode Exit fullscreen mode The env var docs say a saved env block applies to a running session, but I haven't checked whether this particular variable is re-read mid-session, so don't rely on it. Quit Claude Code in the second pane and run claude -c --model opus --effort high in its worktree, which continues the same conversation with the same main-session settings. Now paste $TASK into both panes and watch them fan out. When both finish, run /usage in each pane for Claude Code's own session totals.

If low holds up on your repo, keep it. To make it the default for every new Hermes task in that repo, put the same settings.local.json in your main checkout and have the worktree recipe copy it into each new worktree before the agent starts:

#.hermes/worktree.toml copy = [ ".claude/settings.local.json" ] Enter fullscreen mode Exit fullscreen mode The recipe's copy only takes files git ignores, and refuses the whole recipe otherwise. git check-ignore -v.claude/settings.local.json prints the matching ignore rule if it is covered. The main-session part of the setup (agent, model, effort, account) goes in a Hermes preset, so the rest of the combination is one pick in the launcher.

The ⌘N New task sheet in Hermes 2.3.4: agent, project, worktree, approval mode, model and effort chips, and the "Hermes will run" preview of the claude command.

A subagent that needs to think, a code reviewer for example, can keep its own effort: high in its frontmatter. That names a level, so the variable leaves it alone, and only the agents with nothing set drop to low.

Running the same task twice and checking both the bill and the answer is a small eval, and that habit is what keeps LLM features honest once they're in production. Observability for LLM Applications covers the full version of it: tracing each request, tying cost to the step that spent it, and catching quality regressions before your users do.

Hermes IDE is free to download for macOS, Windows and Linux, source-available under BSL 1.1, and on GitHub.

Quelle: dev.to (dev.to). Original öffnen