Auto-memory is sent to subagents despite docs stating it requires the `memory` field (34% of a small subagent's payload)
Summary
The subagent documentation states that a non-fork subagent starts with:
- CLAUDE.md files (except Explore/Plan)
- not auto memory, "unless
memoryfield set"
I captured the raw HTTP request bodies and measured the opposite: auto-memory (MEMORY.md) is delivered to every subagent, bundled inside the # claudeMd context block, with no agent declaring a memory: field anywhere in the project.
On a small Haiku status-checking subagent this is 7,133 tokens — 34.0% of its entire 20,993-token first turn.
How it was measured
A local forwarding proxy set as ANTHROPIC_BASE_URL, logging request bodies verbatim and relaying to the API, so the parent turn genuinely runs and genuinely spawns a subagent. Exact token counts via POST /v1/messages/count_tokens on the captured payload. Transcript-based inspection cannot see this — injected context is assembled at request time and never written to the .jsonl.
What the subagent request actually contains
The subagent's messages[0] carries a text block of 53,310 bytes / 16,083 tokens, opening with <system-reminder>As you answer the user's questions, you can use the following context: and containing, in order:
# claudeMd
Contents of <project>/CLAUDE.md (project instructions, checked into the codebase):
...
Contents of <user>/memory/MEMORY.md (user's auto-memory, persists across conversations):
...
# currentDate
Split by count_tokens:
| component | tokens | bytes |
|---|---|---|
| whole inherited block | 16,083 | 53,310 |
| CLAUDE.md portion | 8,956 | 31,558 |
| MEMORY.md portion (auto-memory) | 7,133 | 21,752 |
The MEMORY.md portion is explicitly labelled (user's auto-memory, persists across conversations) in the payload itself, so it is unambiguously the auto-memory feature and not a file included via CLAUDE.md.
For context on the shape: the same subagent correctly does not receive the skills listing, the agent-type listing, MCP server instructions, SessionStart hook output, or 80 of the parent's 82 tool schemas. So subagent payload trimming clearly works in general — auto-memory just appears to ride along inside the CLAUDE.md block and escape it.
Expected vs actual
- Expected (per docs): a subagent with no
memory:field receives CLAUDE.md but not auto-memory. - Actual: it receives both, because auto-memory is nested inside the
# claudeMdblock rather than being a separately-gated section.
Why it matters
Subagents are a large share of token spend for agent-heavy workflows. Auto-memory grows monotonically with use, and it is content a status check or a grep sweep has no use for. There is also no per-agent way to opt out: no frontmatter key, settings key, env var or SDK AgentDefinition field controls CLAUDE.md/auto-memory inheritance (I probed 11 candidate key names empirically — all silently ignored, verified by diffing the resulting payloads against a control).
Either outcome is useful
- If this is a bug, gating auto-memory behind the documented
memory:field would remove ~7k tokens from every subagent spawn in setups like mine. - If it is intended, the docs are wrong and should say auto-memory is always inherited — and a per-agent opt-out would be a valuable addition, since
Explore/Planalready prove the harness can skip this block.
Environment
- Claude Code 2.1.234
- macOS
- Subagent: user-defined,
model: haiku, small declared tool set, nomemory:field