[BUG] Session-invariant context (skill/agent listings, deferred tools, CLAUDE.md) is sent after the first user prompt, so every new session and subagent rewrites it to the prompt cache

Status Open
Reported on v2.1.284
Maintainer reply None cached
Activity 0 comments · opened Sep 30, 2026

Summary

On the first request of a session, Claude Code places session-invariant context after the user's first prompt. Because the prompt cache matches a prefix, every new session with a distinct first prompt pays a full cache write for content that is byte-identical across sessions. The same ordering applies to subagent spawns, whose first message is the task prompt.

Observed request layout

Agent SDK @anthropic-ai/claude-agent-sdk 0.3.284 (CLI 2.1.284), settingSources: ['project'], skills: 'all', captured from the outbound /v1/messages body:

| position | content | cached across sessions with different prompts? |
| --- | --- | --- |
| tools, system | tool schemas, system prompt (+ append) | yes |
| messages[0] (user) | project memory (CLAUDE.md, .claude/rules/*) as a <system-reminder>, then the user prompt | memory yes (it precedes the prompt), but no breakpoint sits between it and the prompt, so it is only read back when the prompt also matches |
| messages[1] (role system, carries the only message cache_control) | # Environment block, deferred-tool name list, MCP "still connecting" notice, agent-type listing, skill listing, date | no: it follows the user prompt |

Measurement

claude-sonnet-5-5, a fresh session per trial, first prompt salted to be unique (n=31 per arm, interleaved):

  • project memory in messages[0] (default): cache_read=12,185, cache_creation≈32.5K per first turn.
  • same content moved into systemPrompt: { type: 'preset', preset: 'claude_code', append } with claudeMdExcludes covering the memory files: cache_read=18,052, cache_creation≈16.1K per first turn.

The remaining ~16K-token write per new session is the post-prompt system message (environment, deferred tools, agent and skill listings), which no option moves in front of the prompt. excludeDynamicSections: true did not change its position.

Request

Place session-invariant context (the listings, the environment block, project memory) before the first user prompt, or offer an option to do so, so that a cache breakpoint can sit in front of the prompt and new sessions and subagent spawns read it from cache instead of rewriting it.

View original on GitHub ↗