[BUG] Agent frontmatter `effort` is ignored on the --agent session-persona path, while `model` from the same block is honored

Status Open
Reported on v2.1.219
Maintainer reply None cached
Activity 1 comment · opened Jul 27, 2026

effort is a documented subagent frontmatter field: "Effort level when this subagent is active. Overrides the session effort level. Default: inherits from session." (sub-agents docs, supported frontmatter fields). The documented precedence is env var > frontmatter > session level > model default (model-config).

When an agent definition is loaded as a session persona via --agent <name>, the effort field has no effect — the session runs at the ambient level instead. model from the same frontmatter block is honored, so this is not a file-loading problem.

This looks like a third distinct path, separate from the two already on file:

| Path | effort honored? | Source |
|---|---|---|
| Plain subagent via Agent/Task tool | yes — confirmed | #80569 reports it; independently measured here, see below |
| Agent-team teammate | no | #80569 |
| --agent session persona | no | this report |

#31536 (add per-subagent effortLevel to frontmatter) is closed as completed, which is presumably why the field is documented. So this reads as a delivered feature that does not reach the --agent code path, rather than a feature request.

Repro

Create ~/.claude/agents/probe.md, declaring a model and an effort that both differ from the ambient session default:

---
name: probe
model: sonnet
effort: low
description: Probe.
---

Regardless of what the user asks, reply with exactly one word: PLATYPUS

Then run it headless, with CLAUDE_EFFORT unset so nothing is inherited from the parent shell:

env -u CLAUDE_EFFORT claude -p --agent probe 'What is 2+2?'

Read the resulting session transcript in ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl. Each type: "assistant" record carries a top-level effort field and message.model.

Observed (ambient default high, Opus 5 — measured on 2.1.219 and re-confirmed unchanged on 2.1.220):

  • message.model = claude-sonnet-5 — the frontmatter model was applied.
  • top-level effort = high — the ambient default, not the frontmatter's low.

Expected: effort = low, per the documented precedence.

Why the same-block comparison matters

The two fields sit in one frontmatter block and are read in one load. Because model came through and effort did not, the usual explanations are ruled out without needing a second run: the file loaded, it parsed, and the frontmatter was consulted. Only the effort field failed to apply.

Two notes for anyone reproducing this:

  • The agent's load was confirmed behaviorally, by having it answer PLATYPUS regardless of the prompt. Grepping the transcript for the injected system prompt does not work — -p transcripts do not contain it.
  • The ambient default here is high, so an agent declaring effort: high produces a three-way tie and measures nothing. The declared value has to differ from the ambient default or the result is unfalsifiable. This is easy to get wrong and it silently produces a null result.

The dispatch path does work — which is what makes this a path-specific bug

Worth recording, because it narrows the problem and corroborates #80569's report from the other direction. On the Agent/Task-tool dispatch path, frontmatter effort works reliably. Measured across 3 independent runs, 2 carriers (an ~/.claude/agents/*.md file and --agents inline JSON), and 2 models (Opus 5 and Sonnet 5), in both directions — including a declared xhigh correctly raising effort against a parent session pinned to low, which rules out a floor or default artifact.

Two related details from the same measurements, in case they help localize it:

  • Effort inherits from the nearest declaring ancestor, not from the root session.
  • The dispatch metadata (meta.json) records model but never effort — it logged model: null even where an explicit declaration was applied. So the only reliable read of a subagent's effort is the top-level effort field in that subagent's own transcript, not meta.json and not the CLAUDE_EFFORT environment variable (which reports the parent process's level from inside a subagent).

So the feature is delivered and working on one path and inert on two others.

Impact

Three long-lived agent definitions here carried effort: high from the day they were written, and all three were no-ops the entire time. It was invisible precisely because high matched the ambient default. Anyone who declared an effort tier matching their usual session level has the same silent no-op with no way to notice — no error, no warning, and the file reads as correct.

Ask

Either honor effort on the --agent path, consistent with model; or document that the field applies only to Agent/Task-tool dispatch, and warn when it is set on a definition used as a session persona.

Environment

  • Claude Code 2.1.219, re-confirmed on 2.1.220
  • macOS
  • Model: Opus 5 (claude-opus-5)
  • Ambient effort default: high
  • Reproduced headless (-p); CLAUDE_EFFORT unset via env -u; CLAUDE_CODE_EFFORT_LEVEL confirmed unset (it outranks frontmatter, so a stray export would mask this entirely)

Related: #80569 (agent-team path), #43083, #31536 (closed completed), #64033 (closed as duplicate, Workflow-tool scoped), #77298 (no effort param on the Agent tool).

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗