{"slug": "claude-api-mid-conversation-tool-changes-fix-the-cache-bug", "title": "Claude API Mid-Conversation Tool Changes: Fix the Cache Bug", "summary": "Anthropic's beta for mid-conversation tool changes, shipped with Claude Opus 5, fixes a prompt-caching bug that caused cache misses when the `tools` array was modified mid-session, costing up to 87% savings on tool schema tokens per session. The beta, enabled with header `mid-conversation-tool-changes-2026-07-01`, freezes the `tools` array and uses `tool_addition` and `tool_removal` system blocks instead, and is available on Claude Fable 5, Mythos 5, Opus 4.8, and Opus 5 across the Claude API, Amazon Bedrock, and Google Cloud, but not on Claude Sonnet 5.", "body_md": "If you build long-running Claude agents with more than a handful of tools, you are probably bleeding money on cache misses you have not diagnosed yet. The `tools`\n\narray is hashed before your system prompt, before your messages — it sits at the very front of Claude’s prompt prefix. Modify it mid-session to change which tools are available, and you invalidate the cache for the entire conversation. Anthropic shipped a beta with [Claude Opus 5](https://www.anthropic.com/news/claude-opus-5) that fixes this: mid-conversation tool changes. The `tools`\n\narray stays frozen. You add or remove availability using system message blocks instead.\n\n## Why Your Tool List Was Breaking the Cache\n\nClaude’s prompt caching hashes the request prefix in order: `tools`\n\nfirst, then `system`\n\n, then `messages`\n\n. A cache hit requires that prefix to match the previous request byte-for-byte up to the breakpoint. Editing the `tools`\n\narray — even appending one new entry — changes the very front of the hash, and everything downstream misses.\n\nFor production agents, this is not a theoretical concern. A typical MCP-connected agent carries 3,000 to 8,000 tokens of tool schemas on every request. A long-running session with 30 turns and 6,000 tool schema tokens, without caching, pays for those schemas 30 times. With caching intact, you pay once to write the cache and then 10% of input price on every subsequent read. The difference on Claude Opus 5 ($5.00 per million input tokens, $0.50 per million on cache hits) works out to roughly 87% savings on tool schema tokens alone — per session.\n\nTeams who noticed high `cache_creation_input_tokens`\n\nand low `cache_read_input_tokens`\n\nin their usage logs were often hitting this exact problem: something was changing the tool list mid-session, collapsing the cache on every turn.\n\n## What Mid-Conversation Tool Changes Actually Do\n\nThe beta — enabled with the header `mid-conversation-tool-changes-2026-07-01`\n\n— lets you declare your full tool set in `tools`\n\nonce, at the start, and never touch it again. From there, you control tool availability using `tool_addition`\n\nand `tool_removal`\n\ncontent blocks inside `role: \"system\"`\n\nmessages placed at the relevant point in the conversation. The blocks reference tools by name rather than redefining them, so the frozen `tools`\n\narray stays byte-identical across turns and the cache keeps hitting.\n\nThis is available on Claude Fable 5, Mythos 5, Opus 4.8, and Opus 5, across the Claude API, Amazon Bedrock, and Google Cloud. One notable exception: Claude Sonnet 5 does not support this beta. If your production agent runs on Sonnet 5, you are waiting.\n\n## How to Implement It\n\nThree changes to your existing code:\n\n- Add the beta header to your request\n- Declare every tool your agent might ever use in\n`tools`\n\nat the start — do not modify this array - Use\n`tool_removal`\n\nor`tool_addition`\n\nblocks in system messages to change what Claude can see\n\nHere is a minimal example in Python:\n\n```\nclient = anthropic.Anthropic()\n\nresponse = client.beta.messages.create(\n    model=\"claude-opus-5\",\n    max_tokens=1024,\n    betas=[\"mid-conversation-tool-changes-2026-07-01\"],\n    # Declare all tools upfront. This array never changes.\n    # The cache prefix stays byte-identical across turns.\n    tools=[\n        {\n            \"name\": \"read_file\",\n            \"description\": \"Read file contents.\",\n            \"input_schema\": {\n                \"type\": \"object\",\n                \"properties\": {\"path\": {\"type\": \"string\"}},\n                \"required\": [\"path\"],\n            },\n        },\n        {\n            \"name\": \"write_file\",\n            \"description\": \"Write content to a file.\",\n            \"input_schema\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"path\": {\"type\": \"string\"},\n                    \"content\": {\"type\": \"string\"},\n                },\n                \"required\": [\"path\", \"content\"],\n            },\n        },\n    ],\n    messages=[\n        {\"role\": \"user\", \"content\": \"Review main.py for issues.\"},\n        # ... (assistant turn with tool use, user turn with tool results) ...\n        # After the review phase, withdraw write access.\n        # This references the tool by name — no cache invalidation.\n        {\n            \"role\": \"system\",\n            \"content\": [\n                {\n                    \"type\": \"tool_removal\",\n                    \"tool\": {\"type\": \"tool_reference\", \"name\": \"write_file\"},\n                },\n            ],\n        },\n    ],\n)\n```\n\nNote the placement constraint: a system message must immediately follow a user turn (or an assistant turn ending in a server tool result). Placing it between a `tool_use`\n\nblock and its `tool_result`\n\nreturns a 400 error. In an agentic loop, insert it after the user message that delivers tool results — that is the natural seam.\n\n## defer_loading: The Companion Feature Worth Using\n\nDeclare a tool with `defer_loading: true`\n\nand it is hidden from Claude until a `tool_addition`\n\nblock explicitly surfaces it. This pairs well with mid-conversation tool changes for agents with large, specialized tool libraries.\n\nA practical pattern: a coding agent starts with read-only tools (`read_file`\n\n, `search_code`\n\n, `run_tests`\n\n). After a review pass completes, a `tool_addition`\n\nblock surfaces the write tools (`write_file`\n\n, `apply_patch`\n\n). The full set is declared upfront — the cache prefix is stable — but Claude only sees the subset relevant to the current phase. You get dynamic capability management without paying a cache penalty for it.\n\n## When This Is Worth the Complexity\n\nMid-conversation tool changes are not a one-size fix. Short sessions, static tool sets, or small tool inventories will see minimal benefit and added code complexity. The calculus changes when:\n\n- Sessions run 10 or more turns\n- Your tool set carries more than 3,000 tokens of schemas\n- Tool availability legitimately changes mid-session (mode switches, capability unlocking, security revocation)\n\nIf none of those apply, stick with a static `tools`\n\narray. The feature exists for the class of production agents where these conditions are true — and at scale with Opus 5 pricing, the savings are not marginal.\n\n## Placement Rules and Caching Gotchas\n\nSystem messages have strict placement requirements that will bite you if you ignore them. They must follow a user turn or a tool-result-bearing user turn. They cannot be the first message. And once sent, do not edit or remove them — rewriting a system message already in the cached history invalidates everything after it. If an instruction needs to change, append a new system message rather than modifying the existing one. Later system messages take precedence over earlier ones.\n\nAnthropic’s [cache diagnostics tool](https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics) is useful here: it identifies exactly where two requests diverged when an expected cache hit does not happen. Pair it with the [prompt caching docs](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) to verify your breakpoints are placed correctly before blaming the tool change logic.\n\n## Bottom Line\n\nMid-conversation tool changes is a narrow feature with outsized impact for a specific class of production agents. If you are running multi-phase or long-running Claude Opus 5 sessions with dynamic tool requirements, the combination of a frozen `tools`\n\narray, `tool_removal`\n\nand `tool_addition`\n\nblocks, and `defer_loading`\n\nis the architecture you want. The cache math makes the investment clear.\n\nThe Sonnet 5 exclusion is the only real friction — if Anthropic extends this beta to Sonnet 5, it becomes the default pattern for production Claude agents. Until then, this belongs in any Opus 5 agent that changes its tool set mid-session.\n\nBeta header: `mid-conversation-tool-changes-2026-07-01`\n\n. Full docs at [platform.claude.com](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages).", "url": "https://wpnews.pro/news/claude-api-mid-conversation-tool-changes-fix-the-cache-bug", "canonical_source": "https://byteiota.com/claude-api-mid-conversation-tool-changes/", "published_at": "2026-08-19 09:14:13+00:00", "updated_at": "2026-08-19 09:41:40.532484+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-products", "ai-infrastructure"], "entities": ["Anthropic", "Claude Opus 5", "Claude Fable 5", "Claude Mythos 5", "Claude Opus 4.8", "Claude Sonnet 5", "Amazon Bedrock", "Google Cloud"], "alternates": {"html": "https://wpnews.pro/news/claude-api-mid-conversation-tool-changes-fix-the-cache-bug", "markdown": "https://wpnews.pro/news/claude-api-mid-conversation-tool-changes-fix-the-cache-bug.md", "text": "https://wpnews.pro/news/claude-api-mid-conversation-tool-changes-fix-the-cache-bug.txt", "jsonld": "https://wpnews.pro/news/claude-api-mid-conversation-tool-changes-fix-the-cache-bug.jsonld"}}