Verificando Cache Hits com cache_read_input_tokens
Adicionar um breakpoint cache_control não prova, por si só, que suas requisições estão realmente atingindo o cache.
O único sinal confiável é o objeto usage em cada resposta, especificamente cache_read_input_tokens e cache_creation_input_tokens.
Esta página mostra como ler esses campos corretamente, como incorporar uma verificação leve em seu próprio código e quais valores realmente significam sucesso versus falha.
Resumo
response.usage contém quatro contagens de tokens que são importantes para o cache: input_tokens, output_tokens, cache_creation_input_tokens e cache_read_input_tokens.
Uma escrita no cache aparece como cache_creation_input_tokens diferente de zero; um hit no cache aparece como cache_read_input_tokens diferente de zero.
Como o cache falha silenciosamente - um cache não encontrado nunca gera um erro - verificar esses campos em cada requisição, não apenas durante o desenvolvimento, é a única maneira de saber se sua configuração de cache está realmente funcionando em produção.
Esta página constrói um pequeno helper reutilizável para essa verificação e detalha os valores que você deve esperar em cada estágio do ciclo de vida de uma requisição.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=200,
system=[
{
"type": "text",
"text": "Você é o assistente de suporte da Acme Corp." * 200,
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": "Qual é a sua janela de reembolso?"}],
)
usage = response.usage
print("input_tokens:", usage.input_tokens)
print("cache_creation_input_tokens:", usage.cache_creation_input_tokens)
print("cache_read_input_tokens:", usage.cache_read_input_tokens)Quando usar isso:
- Logo após adicionar seu primeiro breakpoint
cache_control, para confirmar que ele está funcionando. - No logging ou métricas de produção, para capturar uma regressão de cache no momento em que ela acontece.
- Ao depurar uma fatura mais alta do que o esperado para uma carga de trabalho supostamente em cache.
- Sempre que você alterar o conteúdo do prompt e quiser confirmar que o cache ainda está sendo atingido depois.
Exemplo de Trabalho
import anthropic
client = anthropic.Anthropic()
SYSTEM_TEXT = "Você é o assistente de suporte da Acme Corp. O material de referência a seguir.\n" + ("Detalhe da política. " * 300)
def ask_with_cache_check(question: str) -> str:
"""Envia uma requisição em cache e relata exatamente o que aconteceu com o cache."""
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=300,
system=[
{
"type": "text",
"text": SYSTEM_TEXT,
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": question}],
)
usage = response.usage
if usage.cache_read_input_tokens > 0:
status = "HIT"
elif usage.cache_creation_input_tokens > 0:
status = "WRITE (primeira chamada ou TTL expirado)"
else:
status = "NENHUMA ATIVIDADE DE CACHE (breakpoint muito pequeno ou ausente)"
print(
f"[{status}] read={usage.cache_read_input_tokens} "
f"write={usage.cache_creation_input_tokens} "
f"input={usage.input_tokens} output={usage.output_tokens}"
)
return response.content[0].text
ask_with_cache_check("Qual é a sua janela de reembolso?")
ask_with_cache_check("Você envia internacionalmente?")O que isso demonstra:
- Uma verificação de status tripla: hit de cache, escrita de cache ou nenhuma atividade de cache.
- Chamando a mesma função duas vezes seguidas com um bloco de sistema idêntico - a segunda chamada deve relatar
HIT. - Exibindo todos os quatro campos de uso relevantes juntos, para que uma regressão seja visível em um único olhar, em vez de exigir pesquisas separadas.
- Um padrão que você pode inserir no logging de requisições sem alterar o tratamento real da resposta do seu aplicativo.
Análise Detalhada
Como Funciona
response.usageé preenchido em cada chamadamessages.create()bem-sucedida, independentemente de o cache estar configurado ou não.cache_creation_input_tokensconta os tokens gravados no cache nesta chamada - diferente de zero em uma nova gravação ou após a expiração do TTL.cache_read_input_tokensconta os tokens lidos de uma entrada de cache existente - diferente de zero apenas em um hit real.input_tokensreflete os tokens processados normalmente, fora de qualquer segmento em cache - isso geralmente é pequeno quando o cache está funcionando, pois é apenas a cauda não em cache do seu prompt.- Nenhum desses campos gera um aviso ou erro em caso de falha; uma falha de cache se parece exatamente com uma requisição normal que, por acaso, também carrega um valor
cache_creation_input_tokens.
Lendo os Quatro Campos Juntos
| Cenário | cache_creation_input_tokens | cache_read_input_tokens | input_tokens |
|---|---|---|---|
| Primeira chamada de sempre (cache frio) | Alto | 0 | Baixo (apenas cauda não em cache) |
| Chamada repetida, cache ainda ativo | 0 | Alto | Baixo (apenas cauda não em cache) |
| Cache expirado, reescrito | Alto (novamente) | 0 | Baixo |
Nenhum cache_control usado | 0 | 0 | Tamanho total do prompt |
| Prefixo alterado, cache invalidado | Alto (novamente) | 0 | Baixo |
Notas Python
# os campos de uso são inteiros simples no objeto de uso tipado do SDK -
# seguros para comparar, somar ou registrar diretamente sem análise extra.
usage = response.usage
total_cached_prefix_tokens = usage.cache_read_input_tokens + usage.cache_creation_input_tokens
hit_ratio = (
usage.cache_read_input_tokens / total_cached_prefix_tokens
if total_cached_prefix_tokens
else 0.0
)Parâmetros e Valores de Retorno
| Campo | Tipo | Descrição |
|---|---|---|
usage.input_tokens | int | Tokens processados normalmente, fora de qualquer prefixo em cache. |
usage.output_tokens | int | Tokens gerados pelo Claude na resposta. |
usage.cache_creation_input_tokens | int | Tokens gravados no cache nesta chamada. |
usage.cache_read_input_tokens | int | Tokens lidos de uma entrada de cache existente nesta chamada. |
Armadilhas
- Verificar apenas
input_tokense assumir que o cache está "simplesmente funcionando".input_tokenssozinho não diz se uma leitura de cache ocorreu - você precisa dos dois campos específicos do cache. Correção: sempre registre todos os quatro campos de uso juntos, não apenas os tokens totais. - Testar o cache com uma única requisição. A primeira chamada para um novo prefixo é sempre uma escrita, nunca um hit - testar com uma chamada e ver
cache_read_input_tokens == 0é esperado, não um bug. Correção: sempre teste com pelo menos duas chamadas consecutivas compartilhando o mesmo prefixo. - Assumir que um
cache_creation_input_tokensdiferente de zero significa que algo está errado. Uma escrita é completamente normal na primeira chamada ou após a expiração do TTL - não é um sinal de erro por si só. Correção: trate apenas "nenhuma atividade de cache de nenhum tipo" ou "uma escrita inesperada em uma chamada que deveria ser repetida" como um sinal de alerta. - Não registrar o uso em produção, apenas em testes locais. Regressões de cache de uma alteração de prompt muitas vezes passam despercebidas porque ninguém está observando
cache_read_input_tokensno sistema ao vivo. Correção: emita esses campos para seu pipeline de métricas ou logging em cada requisição, não apenas durante o desenvolvimento. - Comparar a taxa de hits entre requisições com prefixos diferentes. Uma queda na taxa de hits agregada pode significar que um prefixo específico começou a falhar, não que o cache "parou de funcionar" amplamente. Correção: marque suas métricas de cache pelo prompt/endpoint de onde vieram, para que você possa isolar o prefixo afetado.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Verificação de uso por requisição (esta página) | Você precisa da verdade absoluta em cada chamada | Você só precisa de uma noção aproximada do gasto geral |
| Revisão do painel de faturamento agregado | Verificação pontual das tendências gerais de gastos periodicamente | Você precisa capturar uma regressão no momento em que ela acontece |
| Depuração manual baseada em print | Investigação local pontual de um prompt específico | Qualquer configuração de produção ou CI - não é durável ou consultável |
FAQs
Qual campo me diz que uma requisição foi um hit de cache?
usage.cache_read_input_tokens. Um valor diferente de zero lá significa que a requisição reutilizou com sucesso um prefixo previamente em cache.
Qual campo me diz que uma requisição gravou no cache?
usage.cache_creation_input_tokens. Um valor diferente de zero significa que esta chamada em cacheou conteúdo que não estava previamente em cache, ou que havia expirado.
É normal que a primeira requisição a um novo prompt mostre zero cache_read_input_tokens?
Sim - a primeira chamada para qualquer prefixo dado é sempre uma escrita, não um hit. Você precisa de pelo menos duas chamadas com um prefixo idêntico para ver uma leitura.
Uma falha de cache gera uma exceção ou aviso?
Não. Uma falha de cache se parece com uma requisição normal; a única diferença é quais campos de uso são diferentes de zero. Não há um sinal de erro separado.
O que significa se ambos cache_creation_input_tokens e cache_read_input_tokens são zero?
Ou nenhum breakpoint cache_control foi definido, ou o conteúdo marcado para cache foi muito pequeno para valer a pena cachear. Verifique se seu breakpoint está realmente presente na requisição.
Uma única resposta pode mostrar ambos cache_creation_input_tokens e cache_read_input_tokens como diferentes de zero?
Sim, se você tiver múltiplos breakpoints - um segmento anterior pode atingir uma entrada de cache existente enquanto um segmento posterior grava uma nova na mesma requisição.
Como construo uma métrica de taxa de hits a partir desses campos?
Divida cache_read_input_tokens pela soma de cache_read_input_tokens e cache_creation_input_tokens para um determinado prefixo, rastreado ao longo de uma janela de requisições.
Devo registrar esses campos em produção, ou apenas durante o desenvolvimento?
Em produção. Regressões de cache são silenciosas por design - a única maneira de capturar uma em ação é observando esses campos continuamente, não apenas quando você configurou o cache pela primeira vez.
Se input_tokens for baixo, isso significa que o cache está funcionando?
Não por si só - verifique cache_read_input_tokens diretamente. Um input_tokens baixo combinado com um cache_creation_input_tokens diferente de zero apenas significa que você está no meio de uma escrita, não necessariamente atingindo o cache ainda.
Qual é a maneira mais rápida de confirmar que o cache está configurado corretamente?
Envie a mesma requisição duas vezes seguidas e verifique se a segunda resposta mostra cache_read_input_tokens diferente de zero. Se não mostrar, o breakpoint ou o prefixo não é estável entre as duas chamadas.
Relacionados
- Como o Match de Prefixo do Prompt Caching Realmente Funciona - por que um hit requer conteúdo idêntico byte a byte.
- Noções Básicas de Prompt Caching - o primeiro breakpoint que esta página verifica.
- Depurando Invalidadores Silenciosos de Cache em Prompts Longos - o que fazer quando esta verificação revela um problema.
- Tempestades de Cache Miss de Prompt - Diagnosticando Picos Súbitos de Custo e Latência - resposta a incidentes de produção para uma falha generalizada de cache.
Versões da Stack: Escrito contra a linha de modelos Claude atual a partir de ~junho de 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (o padrão), e Claude Haiku 4.5 - e o SDK oficial
anthropicPython (última versão 0.x). Nomes de modelos, versões de SDK e preços mudam rapidamente - verifique os detalhes atuais em platform.claude.com/docs antes de confiar neles.