Mid-Conversation System Prompts: Steering an Agent Without Breaking the Cache Anthropic's Claude models now support mid-conversation system messages, allowing developers to inject new instructions into a long-running agent session without invalidating the entire prompt cache. By placing a system-role message after the cached history, the cached prefix remains intact, reducing cost and latency. This feature also provides a non-spoofable operator channel, improving prompt-injection safety compared to the previous workaround of embedding instructions in user turns. Here is a problem I hit building a long-running agent: I needed to inject a new instruction partway through a session "the project is Go, write Go" but editing the top-level system prompt to add it invalidated my entire prompt cache. Every cached turn got reprocessed at full price. The fix is a feature that landed in the current Claude models: mid-conversation system messages. Here is what it is and when to use it. A long agent session has a large, stable system prompt and a growing message history, and you cache the prefix so each turn reuses the prior work cheaply. That works until you learn something mid-session that the agent needs to know: a mode toggled, the user delivered async context, files changed on disk, the token budget dropped. The naive move is to edit the system prompt to include the new fact. But the system prompt sits at the front of the cached prefix. Change one byte there and you invalidate everything after it. Your whole conversation history reprocesses at full input price on the next request. For a long session, that is expensive and slow. The current models let you put a system -role message directly in the messages array, after the history, instead of editing the top-level system : js const response = await client.messages.create { model: "claude-opus-4-8", max tokens: 16000, system: { type: "text", text: STABLE SYSTEM, cache control: { type: "ephemeral" } }, , messages: ...history, // cached prefix, untouched { role: "user", content: latestUserMessage }, // @ts-expect-error: role:"system" SDK types may still be landing { role: "system", content: "This project is Go. Write all code in Go." }, , }, { headers: { "anthropic-beta": "mid-conversation-system-2026-04-07" } }, ; Because the new instruction sits after the cached history, it invalidates nothing before it. The cached prefix stays intact, you pay full price only for the small new message, and the agent still receives the instruction with operator authority. The old workaround was to put operator instructions inside a user turn, often wrapped in something like