Ein Agent läuft seit zwanzig Zügen, der Kontext ist gut gefüllt und jetzt soll ein Tool weg. Der Schreibzugriff aufs Repository zum Beispiel, weil der Pull Request raus ist und ab hier nur noch geprüft werden soll. Wer dafür einfach den Eintrag aus dem tools-Array streicht, verliert mit dem Tool den kompletten Prompt-Cache. Der nächste Request schreibt die gesamte bisherige Konversation neu in den Cache, zum 1,25-fachen des Input-Preises statt zum 0,1-fachen fürs Lesen.
Genau dafür gibt es seit dem Release von Claude Opus 5 einen Weg daran vorbei. Er heißt mid-conversation-tool-changes-2026-07-01 und ist ein Beta-Header. Was er tut, ist unspektakulär und genau deshalb wirksam.
Warum ein einziges Tool die ganze Konversation kostet
Prompt-Caching arbeitet über einen Hash des Request-Prefix. Anthropic hasht dabei strikt in der Reihenfolge tools, dann system, dann messages. Eine Änderung auf einer Ebene invalidiert diese Ebene und alles, was danach kommt.
Damit ist die Tool-Definition die teuerste Stelle im ganzen Request, weil sie ganz vorne steht. Ändert sich dort ein Name, eine Beschreibung oder ein Schema, sind Tools, System-Prompt und sämtliche Messages auf einen Schlag ungültig. Die Invalidierungstabelle in der Dokumentation zeigt das Gefälle deutlich. Websuche oder Citations umzuschalten kostet System-Prompt und Messages. Die speed-Einstellung ebenso. tool_choice und disable_parallel_tool_use kosten nur die Messages, genau wie das Hinzufügen oder Entfernen von Bildern. Thinking- und Effort-Parameter wirken auf die Messages, auf manchen Modellen zusätzlich auf Tools und System-Prompt.
Foto: davidschultz / Unsplash
Wie viel Geld daran hängt, hängt an der Prefix-Größe. Anthropic nennt in der Dokumentation zu Tool Search für ein typisches Multi-MCP-Setup mit GitHub, Slack, Sentry, Grafana und Splunk rund 55.000 Token allein an Tool-Definitionen, bevor überhaupt etwas passiert ist. Mit den Listenpreisen durchgerechnet kostet ein 5-Minuten-Write bei Claude Opus 5 6,25 USD je Million Token, für 55.000 Token also rund 0,34 USD. Aus dem Cache gelesen wären es bei 0,50 USD je Million rund 0,03 USD. Diese Differenz fällt bei jedem unnötigen Neuaufbau an. Dazu kommt die Latenz, die dem Nutzer in dem Moment auffällt, in dem der Agent eigentlich flüssig weiterarbeiten sollte.
Was der Cache kostet und was er spart
Die Multiplikatoren auf den Basis-Input-Preis sind überschaubar. Ein Write mit fünf Minuten TTL kostet das 1,25-fache, ein Write mit einer Stunde das 2-fache, jedes Lesen und jeder Refresh das 0,1-fache. Für Claude Opus 5 heißt das konkret 5 USD Input, 6,25 USD für den 5-Minuten-Write, 10 USD für den Stunden-Write, 0,50 USD fürs Lesen und 25 USD Output, jeweils je Million Token.
Ein paar Randbedingungen sollte man kennen, bevor man Cache-Verhalten debuggt. Pro Request sind maximal vier Cache-Breakpoints erlaubt, das Lookback-Fenster pro Breakpoint umfasst 20 Content-Blöcke. Und es gibt eine Mindestlänge. Claude Opus 5 cacht ab 512 Token, vorher waren es bei Opus 4.8 noch 1.024. Fable 5 und Mythos 5 liegen ebenfalls bei 512, Mythos Preview bei 2.048, Opus 4.7 bei 2.048, Opus 4.6 und 4.5 bei 4.096, Sonnet 5, 4.6 und 4.5 jeweils bei 1.024 und Haiku 4.5 bei 4.096.
Wer darunter bleibt, bekommt keinen Fehler. Der Request läuft, cache_control wird still ignoriert und in der Antwort stehen nur Nullen. Deshalb lohnt sich der Blick ins usage-Objekt, bevor man über Preise spekuliert.
print(response.usage.cache_creation_input_tokens) # neu geschrieben, 1,25x bzw. 2x
print(response.usage.cache_read_input_tokens) # aus dem Cache gelesen, 0,1x
print(response.usage.input_tokens) # nur die Token NACH dem letzten Breakpoint
# total_input_tokens = cache_read + cache_creation + input_tokens
Der Wert input_tokens ist dabei die häufigste Stolperstelle, weil er eben nicht den ganzen Input meint, sondern ausschließlich die Token nach dem letzten Breakpoint.
Foto: sigmund / Unsplash
Der neue Weg über tool_addition und tool_removal
Der Trick des Beta-Features besteht darin, das tools-Array in Ruhe zu lassen. Sichtbarkeit wird stattdessen über Content-Blöcke innerhalb einer Message mit "role": "system" gesteuert. Der gehashte Prefix bleibt byte-identisch, also trifft der Cache weiter.
curl https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: mid-conversation-tool-changes-2026-07-01" \
-d '{
"model": "claude-opus-5",
"max_tokens": 1024,
"tools": [ { "name": "get_weather", "description": "Get the current weather for a location.", "input_schema": { "type": "object", "properties": { "location": {"type": "string"} }, "required": ["location"] } } ],
"messages": [
{ "role": "user", "content": "Say OK." },
{ "role": "system", "content": [ { "type": "tool_removal", "tool": {"type": "tool_reference", "name": "get_weather"} } ] }
]
}'
Über die SDKs läuft dieselbe Logik auf dem Beta-Endpunkt.
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=1024,
betas=["mid-conversation-tool-changes-2026-07-01"],
tools=[{
"name": "get_weather",
"description": "Get the current weather for a location.",
"input_schema": {"type": "object", "properties": {"location": {"type": "string"}}, "required": ["location"]},
}],
messages=[
{"role": "user", "content": "Say OK."},
{"role": "system", "content": [
{"type": "tool_removal", "tool": {"type": "tool_reference", "name": "get_weather"}},
]},
],
)
Referenziert wird über {"type": "tool_reference", "name": "..."}. Für Tools aus dem MCP-Connector gibt es zwei eigene Formen, einmal mcp_tool_reference mit server_name und name für ein einzelnes Tool und einmal mcp_toolset_reference mit server_name für einen kompletten Server.
{"type": "tool_addition", "tool": {"type": "mcp_tool_reference", "server_name": "github", "name": "create_pull_request"}}
{"type": "tool_removal", "tool": {"type": "mcp_toolset_reference", "server_name": "github"}}
Der zweite Fall ist der interessantere. Ein ganzer MCP-Server lässt sich damit in einem Block stilllegen, ohne dass sich am Request-Prefix irgendetwas ändert.
Für die andere Richtung braucht es eine Vorbereitung. Jedes Tool im tools-Array ist ab Konversationsbeginn verfügbar, außer es trägt defer_loading: true. Dann bleibt es zurückgehalten, bis ein tool_addition-Block es freischaltet. Derselbe Block reaktiviert auch ein Tool, das vorher per tool_removal entzogen wurde.
{
"name": "get_forecast",
"description": "Get the 5-day forecast.",
"input_schema": {"type": "object", "properties": {"city": {"type": "string"}}},
"defer_loading": true
}
Die Regeln, an denen es scheitert
Die role: "system"-Message darf nicht überall stehen. Sie darf nicht der erste Eintrag in messages sein. Sie muss unmittelbar auf einen user-Turn folgen, wobei ein user-Turn mit tool_result-Blöcken mitzählt, oder auf einen assistant-Turn, der mit einem Server-Tool-Ergebnis endet. Und sie muss vor einem assistant-Turn stehen oder das Array beenden. Wer sie zwischen tool_use und das zugehörige tool_result schiebt, bekommt einen 400er.
Mehrere aufeinanderfolgende System-Messages sind erlaubt und werden als ein einziger System-Abschnitt behandelt. Was nicht geht, ist eine bereits gesendete Mid-Conversation-System-Message nachträglich zu editieren. Das invalidiert den Cache ab dieser Stelle, womit der Vorteil des ganzen Verfahrens dahin wäre. Diese Blöcke sind Historie, nicht Konfiguration.
Foto: afgprogrammer / Unsplash
Ein Name, der nicht im tools-Array deklariert ist, liefert ebenfalls 400. Ohne Deklaration keine Referenz.
Bei den SDKs lohnt ein kurzer Blick auf die eigene Version. Die Dokumentation zeigt typisierte Beispiele für Go, Java und C#, während die Python- und TypeScript-Beispiele die Blöcke als einfache Dicts beziehungsweise Objektliterale übergeben. In Anthropics gebündelter Skill-Dokumentation steht dazu, dass die Typings hinterherhinken und man auf Plain Dicts ausweichen soll. Je nach SDK-Stand also erst prüfen, statt sich auf saubere Typen zu verlassen.
Die Schwesterfunktion ohne Beta-Header sind die Mid-Conversation-System-Messages selbst. Sie sind GA und laufen auf Fable 5, Mythos 5, Opus 4.8 und Opus 5, ausdrücklich nicht auf Claude Sonnet 5. Für die Tool-Change-Blöcke gilt dieselbe Modell-Liste, verfügbar über die Claude API, Amazon Bedrock und Google Cloud.
Wenn nur nachgeladen wird, reicht Tool Search
Für den häufigeren Fall gibt es die einfachere Lösung schon länger. Tool Search ist mit tool_search_tool_regex_20251119 und tool_search_tool_bm25_20251119 auf der Claude API allgemein verfügbar und braucht keinen Beta-Header. Deferred Tools stehen nicht im System-Prompt-Prefix, gefundene Tools werden als tool_reference-Blöcke inline in die Konversation gehängt. Der Prefix bleibt unangetastet.
tools=[
{"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"},
{"name": "get_weather", "description": "...", "input_schema": {...}, "defer_loading": True},
]
Zwei Fehlerquellen sind vorprogrammiert. Mindestens ein Tool muss defer_loading: false behalten, sonst kommt 400 mit dem Hinweis, dass nicht alle Tools deferred sein dürfen. Und ein Tool mit defer_loading: true darf kein cache_control tragen, ebenfalls 400. Der Breakpoint gehört auf ein nicht-deferred Tool. Weitere Grenzen sind 10.000 deferred Tools pro Request, bis zu fünf Treffer pro Suche, 200 Zeichen für ein Regex-Pattern und 500 Zeichen für eine BM25-Query.
Der Effekt geht über Geld hinaus. Anthropic beziffert die Reduktion des Definitions-Overheads typischerweise auf über 85 Prozent, weil nur die drei bis fünf tatsächlich benötigten Tools geladen werden. Wichtiger finde ich den anderen Hinweis aus derselben Dokumentation, dass die Tool-Auswahlgenauigkeit ab 30 bis 50 verfügbaren Tools sinkt. Ein aufgeräumtes Tool-Set ist damit kein reines Kostenthema, sondern eine Qualitätsfrage. Wer Agenten für Code-Reviews oder KI-gestützte Audits baut, merkt das an der Trefferquote, bevor er es an der Rechnung merkt.
Was das für ein Setup mit vielen MCP-Servern bedeutet
Die praktische Konsequenz ist eine Arbeitsteilung. Nachladen läuft über Tool Search und defer_loading, ohne Beta-Header, auch auf Sonnet 5. Entziehen läuft über tool_removal mit Beta-Header, und nur dafür lohnt er sich wirklich. Typische Fälle sind Phasenwechsel im Agenten, etwa wenn nach dem Schreiben nur noch gelesen werden soll, oder ein kompletter MCP-Server, der nach getaner Arbeit vom Tisch muss.
Wofür die alte Faustregel unverändert weitergilt, ist das tools-Array selbst. Wer dort Namen, Beschreibungen oder Schemata anfasst, zahlt den vollen Preis. Es gibt keinen dokumentierten Weg, eine Tool-Definition mitten in der Konversation zu ändern, ohne den Cache zu verlieren. tool_addition und tool_removal schalten Sichtbarkeit, mehr nicht. Ein geändertes Schema muss ins Array und das invalidiert. Die Regel ist also nicht tot, sie hat nur eine Umgehung für einen bestimmten Fall bekommen.
Foto: alesnesetril / Unsplash
Zwei Details noch, die in Rechnungen für Verwunderung sorgen. Der reine Tool-Use-Overhead im System-Prompt beträgt bei Claude Opus 5 286 Token bei tool_choice auto oder none und 406 Token bei any oder tool. Bei Opus 4.7 waren es noch 675 beziehungsweise 804. Und sobald Prompt-Caching überhaupt aktiv ist, setzt die API nach Server-Tool-Ergebnissen automatisch einen zusätzlichen Breakpoint mit fester 5-Minuten-TTL, sichtbar als cache_creation.ephemeral_5m_input_tokens. Das passiert auch dann, wenn alle eigenen Marker auf eine Stunde stehen.
Wann sich der Beta-Header lohnt
Er lohnt sich, wenn eine lange Konversation mit großem Prefix läuft und darin regelmäßig Tools verschwinden sollen. Er lohnt sich nicht, wenn nur nachgeladen wird, dafür ist Tool Search der sauberere Weg ohne Beta-Flag. Und er lohnt sich nicht auf Sonnet 5, weil das Modell nicht dabei ist. Damit bleiben genau die Setups übrig, die ohnehin auf Fable 5, Mythos 5, Opus 4.8 oder Opus 5 laufen und dort lange Agenten-Sessions fahren.
Wer Agenten oder MCP-Anbindungen betreibt und nicht weiß, wie viel im eigenen Setup an Cache-Neuaufbau hängt, findet das über cache_read_input_tokens und cache_creation_input_tokens in wenigen Minuten heraus. Wenn du bei so einer Auswertung oder beim Umbau deiner Tool-Architektur eine zweite Meinung brauchst, meld dich gerne bei mir.
Häufige Fragen
Bleibt der Prompt-Cache erhalten, wenn ich mitten in der Konversation ein Tool entferne?+
Mit dem Beta-Header mid-conversation-tool-changes-2026-07-01 ja, sofern das Entfernen über einen tool_removal-Block in einer Message mit role system läuft. Das tools-Array im Request bleibt dabei unangetastet, deshalb ändert sich der gehashte Prefix nicht. Streicht man das Tool dagegen aus dem tools-Array, invalidiert das laut Anthropics Dokumentation Tools, System-Prompt und Messages auf einen Schlag.
Welche Änderungen invalidieren den Prompt-Cache überhaupt?+
Tool-Definitionen zu ändern kostet den gesamten Cache. Websuche oder Citations umzuschalten sowie die speed-Einstellung invalidieren System-Prompt und Messages. tool_choice, disable_parallel_tool_use und das Hinzufügen oder Entfernen von Bildern betreffen nur die Messages. Thinking- und Effort-Parameter wirken auf die Messages, auf manchen Modellen zusätzlich auf Tools und System-Prompt.
Funktioniert das Feature auch mit Claude Sonnet 5?+
Nein. Anthropic listet für Mid-Conversation-System-Messages und die zugehörigen Tool-Change-Blöcke ausdrücklich Fable 5, Mythos 5, Opus 4.8 und Opus 5 und schließt Sonnet 5 aus. Wer auf Sonnet 5 nur Tools nachladen und nichts entziehen muss, kommt mit Tool Search und defer_loading ans gleiche Ziel.
Warum zeigt usage trotz cache_control nur Nullen?+
Vermutlich ist der Prefix zu kurz. Claude Opus 5 cacht ab 512 Token, Sonnet 5 ab 1.024, Haiku 4.5 ab 4.096. Unterhalb der Grenze wird still nicht gecacht, es kommt kein Fehler und cache_creation_input_tokens sowie cache_read_input_tokens bleiben schlicht bei 0.
Du willst mehr erfahren?
In einem kostenlosen Erstgespräch besprechen wir, wie du diese Themen für dein Unternehmen nutzen kannst. Kein Verkaufsgespräch, sondern eine ehrliche Einschätzung.
Kostenloses Erstgespräch vereinbaren



