Agent SDK subagents have prompt caching disabled by default (enablePromptCaching: false)

Status Open
Reported on v2.1.63
Maintainer reply ✓ Yes — ashwin-ant
Activity 7 comments · opened Mar 2, 2026
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Summary

Subagent requests spawned via the Agent tool have enablePromptCaching hardcoded to false, causing all subagent API calls to miss prompt caching entirely. This results in significant unnecessary cost for tools, system prompts, and conversation history being sent as uncached input on every request.

Root Cause

In the CLI bundle, the main REPL query path correctly defaults to enabling prompt caching:

// Main REPL path (line ~6108 in cli.js):
let S = w.enablePromptCaching ?? YWq(w.model)  // YWq() returns true unless env var disabled

However, subagent internal queries explicitly default to false:

// Subagent path:
enablePromptCaching: z.enablePromptCaching ?? false  // hardcoded false

This means:

  • Main CLI (Opus): enablePromptCachingundefined → falls through to YWq()true
  • Subagent (Sonnet/etc): enablePromptCachingundefined → falls through to false

Impact

From real proxy logs analyzing 104 requests in a single session:

| Request Type | Count | Cache Behavior |
|-------------|-------|---------------|
| Main CLI (Opus) | 50 | ✅ Cache breakpoints injected, cache hits observed |
| Subagent (Sonnet) | 54 | ❌ Zero cache breakpoints, all input uncached |

Subagent requests typically carry ~7,000+ tokens of tools and system prompt that are identical across requests. Without caching, these are billed as full uncached input every time.

Cost example: 54 subagent requests × 7,013 uncached tokens each = ~378,000 wasted uncached input tokens per session.

Proposed Fix

Change the subagent default from false to use the same YWq() check as the main REPL:

// Before:
enablePromptCaching: z.enablePromptCaching ?? false

// After:
enablePromptCaching: z.enablePromptCaching ?? YWq(model)

This would make subagents respect the same environment variable controls (DISABLE_PROMPT_CACHING, DISABLE_PROMPT_CACHING_SONNET, etc.) while enabling caching by default — consistent with the main CLI behavior.

Environment

  • Claude Code version: 2.1.63
  • Agent SDK version: 0.2.63
  • Provider: AWS Bedrock (but issue applies to all providers)
  • Analysis method: Reverse proxy intercepting API requests, confirmed zero cache_control blocks in subagent request bodies

Workaround

Currently using a local reverse proxy that injects cache_control breakpoints into subagent requests that lack them. This works but adds operational complexity. A one-line fix in the CLI would eliminate the need for this workaround.

View original on GitHub ↗

7 Comments

6639835 · 5 months ago

Same! I have no idea why they don't fix it. I got 400$ in a single thread with 10 agents. Normally it's 10 times cheaper.

ashwin-ant collaborator · 4 months ago

Thanks for the detailed investigation. We looked into this and the code path you identified isn't the one subagents use, so changing that default wouldn't affect what you're seeing. The subagent path does enable caching by default.

That said, zero cache_control markers across 54 requests is worth understanding. One possibility is that cache markers depend on the shape of the system prompt, so a custom subagent system prompt may not get them even when caching is on.

To help narrow it down, could you share:

  • Whether your subagents use a custom system prompt
  • One example request body from your proxy capture (system block only, redacted is fine)
KevinZhao · 4 months ago

Thanks for looking into this, @ashwin-ant.

To answer your questions:

  • Yes, I use custom subagents (via the Everything Claude Code plugin which defines 18+ agent types, plus 8 personal agents in ~/.claude/agents/)
  • However, I don't think this is specific to custom system prompts.

My reverse proxy logs show the issue affects all Agent tool subagents, not just custom ones. The distinguishing factor is the User-Agent / code path:

# Main CLI (User-Agent: cli) — 3 pre-existing breakpoints
[#13131] cache: 1bp(tools,1h,pre=3,upg=3) → read=82610 write=408

# Subagent (User-Agent: agent-sdk/0.1.76) — 0 breakpoints
[#13153] cache: 2bp(tools+system,1h,pre=0) → read=65370 write=3312

pre=0 means the Agent SDK sent zero cache_control markers. My proxy then injects them (2bp), and caching works perfectly — proving the API supports it, the SDK just isn't sending them.

I built a Go reverse proxy specifically to work around this. It intercepts all requests and injects cache_control breakpoints for requests that lack them:
https://github.com/KevinZhao/claudecode-bedrock-proxy

See the README section on Agent SDK caching for detailed analysis and log evidence.

nicolasnoble · 4 months ago

Related lever for reducing subagent token pressure, adjacent to the caching fix: let subagents load a different set of CLAUDE.md files than the main session.

Today subagents inherit the full user-scope CLAUDE.md from ~/.claude/ plus any project CLAUDE.md in cwd. With substantial user-scope customization, that's easily 10-20k tokens of preamble per spawn, most of which a typical research or edit subagent doesn't need.

Possible shapes:

  • Per-agent-type inheritClaudeMd: 'none' | 'project' | 'all' in the agent definition YAML
  • Section markers in CLAUDE.md for primary-session-only content
  • Env var or CLI flag to skip user-scope CLAUDE.md on subagent spawns

Complementary to the caching fix, not a substitute. Caching reduces cost when breakpoints exist; scoping reduces cost by not sending the bytes at all.

MeetMartin · 3 months ago

Has there been any progress on this issue from the claude team? This seems like quite a costly bug.

bdoyle0182 · 1 month ago

@ashwin-ant Kevin provided a detailed report that caching is not working on subagents in the sdk. we have evidence of the same behavior in our internal coding agent used by 1k developers on the latest SDK. could you please provide a further clarification or a statement on this?

meteozond · 1 month ago

Here is my approach to subagent cache enabling proxy.

https://gist.github.com/meteozond/a9d1e10691075786a1769a595bcc3fc3

It handles <cache></cache> section inside prompt.