Se invii un prompt di sistema lungo — contesto RAG, catalogo di strumenti, regole dell'agente, esempi — probabilmente paghi il prezzo pieno dell'input a ogni chiamata. Il caching dei prompt di Anthropic riduce il costo al 10% della tariffa sulla parte memorizzata nella cache. OpenAI fa lo stesso implicitamente. La maggior parte dei team ritiene che valga 30 minuti di lavoro, perché riduce in modo affidabile del 60–90% la voce di costo dell'input.
Kunavo gestisce entrambi i casi. I tuoi breakpoint cache_control passano attraverso l'API Messages senza modifiche; sulle API Chat Completions e Responses — dove il formato non dispone di un campo analogo da inviare — Kunavo li imposta per te e aggiunge breakpoint attorno a ciò che hai inviato, senza mai superare il limite di 4. Questo articolo illustra entrambi i casi, le insidie che invalidano silenziosamente le cache e come verificare il tasso di hit.
Prima e dopo
Un ciclo ingenuo che invia dieci volte lo stesso prompt di sistema da 18K token:
# What most people start with: every call re-pays for the whole prompt.
import anthropic
client = anthropic.Anthropic(
api_key="sk-kn-...",
base_url="https://api.kunavo.com",
)
SYSTEM = open("system-prompt.md").read() # 18,000 tokens of rules + examples
# 10 user questions in a session. Every call sends the 18K-token system block.
for question in questions:
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=SYSTEM,
messages=[{"role": "user", "content": question}],
)
# Cost per call (input only): 18,000 × $3 / 1M = $0.054
# 10 calls: $0.54 in input alone.Ora contrassegna il blocco di sistema come memorizzabile nella cache — un campo in più:
# The fix: mark the static prefix as cacheable. After the first call,
# subsequent calls within ~5 minutes pay 10% the input rate on the cached
# portion. Same answer, 89% cheaper.
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=[
{
"type": "text",
"text": SYSTEM,
"cache_control": {"type": "ephemeral"}, # mark cacheable
}
],
messages=[{"role": "user", "content": question}],
)
# First call (cache write): 18,000 × $3.75 / 1M = $0.0675 (1.25× input)
# Calls 2–10 (cache hit): 18,000 × $0.30 / 1M = $0.0054 each
# Total: $0.0675 + 9 × $0.0054 = $0.116 (was $0.54 — 78.5% saved)Hai appena risparmiato il 78,5% del costo dell'input in questa sessione. La prima chiamata è in realtà leggermente più costosa della versione ingenua (~1,25× la tariffa dell'input per scrivere la cache). Dalla chiamata 2 alla 10 paghi il 10% della tariffa. Il punto di pareggio è la chiamata 2; dalla chiamata 3 sei già in vantaggio. Alla chiamata 10 la differenza è enorme.
Stile OpenAI: non devi fare nulla
Il formato OpenAI Chat Completions non ha il campo cache_control, perché OpenAI memorizza implicitamente nella cache sui propri server. Claude no: memorizza solo ciò che un breakpoint contrassegna. Quando raggiungi un modello Claude tramite /v1/chat/completions o /v1/responses, Kunavo imposta i breakpoint al posto tuo: uno scorrevole sull'ultimo messaggio quando la conversazione contiene almeno un turno dell'assistente, poi uno dopo system e uno dopo tools. Un messaggio system o developer inviato dopo la prima risposta del modello resta nella conversazione invece di essere spostato in system (a meno che il suo stesso breakpoint non chieda la cache di un'ora). Quando la richiesta termina con un messaggio del genere, il breakpoint scorrevole va sul blocco immediatamente precedente, e quelli ancora disponibili vanno davanti agli ultimi messaggi di questo tipo seguiti da qualcos'altro. Quelli che imposti tu restano esattamente dove li hai messi; Kunavo riempie solo le posizioni vuote e solo fino al limite di 4. Non devi configurare nulla e lo stesso modello costa uguale sia se accedi tramite il percorso Anthropic sia tramite quello OpenAI:
# OpenAI Chat Completions style — Kunavo sets the breakpoints for you.
# No flag to set. The "usage" object tells you what was cached.
from openai import OpenAI
client = OpenAI(
api_key="sk-kn-...",
base_url="https://api.kunavo.com/v1",
)
resp = client.chat.completions.create(
model="claude-sonnet-4-6",
messages=[
{"role": "system", "content": LONG_SYSTEM_PROMPT}, # >1024 tokens
{"role": "user", "content": "Latest question…"},
],
)
# In the response:
# resp.usage.prompt_tokens_details.cached_tokens → 17,800
# resp.usage.prompt_tokens → 18,200
# 17.8K/18.2K = 98% of input came from cache. Bill reflects that automatically.Leggi usage.prompt_tokens_details.cached_tokens per vedere quanto è stato fornito dalla cache. Più grande è il prefisso fisso, maggiori sono i risparmi. Regola pratica: se il prompt di sistema è più corto del contenuto utente variabile, la cache serve a poco. Ristruttura il prompt in modo che le parti statiche siano grandi e all'inizio.
Caching multilivello — fino a 4 breakpoint
Per i cicli degli agenti in cui alcuni livelli cambiano più rapidamente di altri, imposta più breakpoint cache_control. Ognuno è un'istantanea di tutto ciò che lo precede:
# Anthropic supports up to 4 cache breakpoints per request — use them
# to keep the cache hot even as later layers change.
client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=[
{"type": "text",
"text": ROLE_AND_RULES, # ~3,000 tokens
"cache_control": {"type": "ephemeral"}}, # breakpoint 1
{"type": "text",
"text": LARGE_KNOWLEDGE_BASE, # ~15,000 tokens, rarely changes
"cache_control": {"type": "ephemeral"}}, # breakpoint 2
],
messages=[
{"role": "user",
"content": [
{"type": "text",
"text": CONVERSATION_HISTORY, # grows each turn
"cache_control": {"type": "ephemeral"}}, # breakpoint 3
{"type": "text", "text": new_question},
]},
],
)
# When CONVERSATION_HISTORY changes, breakpoints 1+2 still hit cache.
# Only breakpoint 3 + the new question pay full input rate.La chiave della cache è l'intero prefisso. Aggiungi un token alla posizione N e ogni breakpoint alla posizione N o successiva viene invalidato. L'ordine conta: prima i contenuti più stabili. Il livello delle regole dovrebbe cambiare raramente; la knowledge base si aggiorna ogni settimana; la conversazione cresce a ogni turno.
Modi comuni per interrompere silenziosamente la cache
- Inserire nel prompt la data corrente o un request_id. Ogni chiamata crea un nuovo prefisso, quindi il tasso di hit è 0%. Esegui l'hash degli input del prompt e confrontalo tra le chiamate.
- Assemblaggio non deterministico del prompt di sistema. Se costruisci il sistema da un dict, in alcune versioni di Python l'ordine di iterazione del dict è importante. Ordina esplicitamente le chiavi.
- La durata della cache è di circa 5 minuti. Con traffico sporadico (una chiamata ogni 10 minuti) ottieni zero hit. Raggruppa le chiamate oppure accetta la perdita.
- Il minimo di 1.024 token. Sotto 1K token il caching in stile OpenAI non si attiva. Unisci i piccoli frammenti statici in un unico prefisso più lungo.
- Strumenti / definizioni delle funzioni fanno parte del prefisso. Un nuovo strumento aggiunto al catalogo invalida la cache per tutti. Mantieni stabile il catalogo e assegnagli versioni.
Verificare il tasso di hit
Una cache che non puoi osservare non è ingegneria: è speranza. Registra usage a ogni chiamata:
# Always read usage. If cached_tokens is 0 when you expected a hit,
# something's wrong — usually a non-deterministic prefix.
resp = client.messages.create(...)
u = resp.usage
print({
"input_uncached": u.input_tokens,
"input_cache_read": u.cache_read_input_tokens,
"input_cache_write": u.cache_creation_input_tokens,
"output": u.output_tokens,
})
# A common gotcha: putting today's date or a request_id in the system prompt
# silently invalidates the cache. Hash your inputs; verify cache_read_input_tokens
# is non-zero on the 2nd identical call.Nella dashboard Kunavo, la pagina Usage mostra la suddivisione della cache per modello e per giorno. Se vedi cache_read_input_tokens crescere come percentuale dell'input totale, la cache funziona. Se resta a 0 o oscilla molto, ripercorri l'elenco delle insidie qui sopra.
Quanto costa realmente su Kunavo
La tariffa della cache di ogni modello è pubblicata nella pagina dei prezzi:
- Modelli Anthropic: le letture della cache costano 10% della tariffa di input — 2,5% su Claude Fable 5.1, 5% su Claude Opus 5.5. Le scritture della cache costano 1,25× la tariffa di input — il moltiplicatore di cinque minuti di Anthropic — e Kunavo fattura allo stesso 1,25× le scritture di un'ora, sotto il 2× di Anthropic.
- Modelli OpenAI / Gemini: le letture della cache costano 10% della tariffa di input (il rapporto pubblicato dai fornitori). Le scritture costano 1,25× su GPT-5.6 e GPT-6 Astra, e la normale tariffa di input su ogni altro modello.
- Tutti i prezzi della cache includono già lo sconto Kunavo sul modello (inferiore al prezzo upstream indicato per modello). Quindi una lettura della cache di Sonnet 4.6 su Kunavo costa
$3 × 0.40 × 0.10 = $0.12 per 1M tokens. Circa 25 volte meno della tariffa upstream senza cache.
Quando la cache non è la risposta
Alcuni casi in cui il lavoro non vale la pena:
- Prompt brevi (<1K token totali). L'overhead domina; semplicemente non ne vale la pena.
- Attività una tantum senza traffico ripetuto. La prima chiamata è leggermente più costosa; la cache si ripaga solo dalla chiamata 2 in poi.
- Attività con output elevato e input ridotto (scrittura creativa, generazione di codice). L'input rappresenta già una piccola parte della fattura. Concentrati invece sui limiti del budget di output.
Per tutto il resto — chatbot RAG, agenti con catalogo di strumenti fisso, classificatori su un criterio statico, pipeline di estrazione strutturata con few-shot coerenti — il caching è l'ottimizzazione con il ROI più alto che puoi distribuire in un solo pomeriggio. Abbinalo alle altre quattro tecniche della nostra guida all'ottimizzazione dei costi e una riduzione del 70% è realistica senza alcun compromesso sulla qualità dell'output.
Sei già su Kunavo? Apri /app/usage e controlla la colonna cache del tuo modello più grande. Se è zero, stai lasciando soldi sul tavolo. Guida completa: /docs/caching.