Anthropic just patched one of the sharpest pain points in long-running agentic Claude sessions: you can now add or remove tools mid-conversation without destroying your prompt cache. Three features — mid-conversation tool changes, turn-scoped system messages, and defer_ — shipped between July and September 2026. If you’re building production agents with the Claude API, this changes your architecture and, more directly, your invoice.
Why Changing Tools Mid-Session Was Expensive #
The prompt cache hashes your request prefix in a fixed order: tools → system → messages. The tools array sits at position zero. Touch it — add a tool, remove one, reorder anything — and the cache invalidates for the entire conversation. For a long-running agent accumulating millions of cached tokens over hundreds of turns, that’s not a minor inconvenience. That’s paying full input-token price for context you already paid to write.
Before this feature, developers had two equally bad options: keep the entire tool set active throughout the session (which bloats context and dilutes model attention across irrelevant tools), or start a fresh session at each phase transition (which loses all cached context). Both are architectural compromises. Anthropic’s fix is more surgical.
The Fix: tool_addition and tool_removal #
The core idea: declare your complete tool set in the tools array at the start and never change it. Instead, use tool_addition and tool_removal content blocks inside a role: "system" message to control what the model can actually see at any point in the conversation. Because the tools array itself never changes, the cache prefix stays byte-identical and the cache hit holds.
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=1024,
betas=["mid-conversation-tool-changes-2026-07-01"],
tools=[
{
"name": "web_search",
"description": "Search the web.",
"input_schema": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]
},
},
{
"name": "write_file",
"description": "Write content to a file.",
"input_schema": {
"type": "object",
"properties": {
"path": {"type": "string"},
"content": {"type": "string"}
},
"required": ["path", "content"]
},
"defer_": True, # Hidden until surfaced
},
],
messages=[
{"role": "user", "content": "Research quantum computing advances."},
{
"role": "system",
"content": [
{"type": "tool_removal", "tool": {"type": "tool_reference", "name": "web_search"}},
{"type": "tool_addition", "tool": {"type": "tool_reference", "name": "write_file"}},
],
},
{"role": "user", "content": "Now write up your findings."},
],
)
The blocks reference tools by name ({"type": "tool_reference", "name": "..."}) rather than re-defining them — the full definition stays in tools, untouched. Referencing a name not in tools returns a 400 error with error.details.error_code: tool_reference_unresolved.
defer_: Solving Tool Soup #
Complex agents with large tool registries run into a subtler problem: too many tools active at once confuse the model and waste context on definitions it doesn’t need yet. defer_: true solves this. Declare a tool in tools with that flag and the model won’t see it until you explicitly surface it with a tool_addition block. You get a stable, cache-safe declaration up front and surgical reveal on demand.
This is especially useful for security-gated capabilities. Declare execute_shell with defer_: true; surface it only after the user grants explicit consent mid-session. The tool’s schema is registered, the cache is stable, and the model is none the wiser until you decide otherwise.
Mid-Conversation System Messages (No Beta Header Required) #
The same cache logic that breaks on tools changes also applies to the top-level system field — it sits just one position later in the hash. Edit it mid-session to add a new constraint and you blow the system-plus-messages portion of the cache.
Mid-conversation system messages sidestep this by appending {"role": "system"} to the messages array instead of editing the top-level field. Everything before the new message stays cached. The instruction still carries operator-level authority, taking precedence over user messages if they conflict. This feature has been GA since May 2026 with no beta header required, on Claude Fable 5/5.1, Mythos 5/5.1, Opus 4.8, and Opus 5.
Turn-Scoped Messages: Per-Turn Nudges Without Accumulation #
Long agentic sessions often need periodic nudges — reminders like “request independent reads together” or “the user hasn’t heard from you in a while.” The naive approach is injecting these as regular system messages. The problem: they accumulate. By turn 200, you’re paying token cost for 200 nudges, most of which are irrelevant to the current turn.
Turn-scoped system messages fix this with clear_at: "next_user_message". The message renders for the current turn only. After the next user message, it remains in conversation history but costs zero tokens to process — frozen in place without consuming context.
messages.append({
"role": "system",
"content": "Request independent reads together when possible.",
"clear_at": "next_user_message"
})
Beta header: mid-conversation-system-clear-at-2026-08-21.
Practical Decision Guide #
- Phase-based workflows (research → execute → review): Use
tool_removalandtool_additionat each phase boundary. No session restart, no cache miss. - Security-gated tools :
defer_: trueon powerful tools; surface viatool_additionafter explicit permission. - Mid-session policy changes : Mid-conversation system message (no beta header). Inject operator constraints without touching the cached prefix.
- Per-turn reminders : Turn-scoped messages with
clear_at. Renders once, disappears from active token count. - Rate-limited tools :
tool_removalwhen the external API is throttling; re-add withtool_additionlater. No new session required.
One gotcha: batch your tool changes. Each role: "system" message with tool blocks is itself uncached new content. If you’re making three changes, put them in one message, not three. The cache miss cost applies per message, not per tool change.
What’s Not Supported #
Claude Sonnet 5 does not support mid-conversation system messages or tool changes. Use the top-level system field there. All features require models from the Fable 5/Mythos 5 generation or Opus 4.8 and above.
Mid-conversation tool changes (mid-conversation-tool-changes-2026-07-01) and turn-scoped messages ( mid-conversation-system-clear-at-2026-08-21) are still beta. Basic mid-conversation system messages need no header — they graduated to GA. Check the Claude API release notes for current status as these features approach general availability.
The Bigger Picture #
These features are part of a broader pattern in Anthropic’s 2026 API work: on-demand conversation compaction (compact-2026-09-04), per-message effort changes, and thinking display updates all shipped in the same window. Anthropic is treating long-running sessions as a first-class use case, not an edge case to architect around.
For developers running Claude at scale, the cache is the primary cost lever. At 0.025x base input price on Fable 5.1 cache reads, a well-managed cache across a multi-million-token session is the difference between an economically viable production system and one that burns budget on redundant processing. These features exist to keep that cache alive longer, across more complex workflows. Read the full documentation and start using them.