Diagnostics du cache
Diagnostiquez les échecs inattendus du cache de prompts en comparant des requêtes consécutives et en identifiant exactement où le préfixe du prompt a divergé.
La mise en cache des prompts (« prompt caching ») réduit considérablement la latence et les coûts, mais uniquement lorsque le début de votre prompt est identique octet pour octet à une requête récente. Un outil réordonné, un horodatage interpolé dans votre invite système (« system prompt ») ou une modification d'un message antérieur peuvent invalider silencieusement le cache. Sans les diagnostics du cache, le seul signal est la chute de usage.cache_read_input_tokens à zéro, sans aucune indication de ce qui a changé.
Les diagnostics du cache comblent cette lacune. Transmettez l'id de votre réponse précédente, et l'API compare les deux requêtes et vous indique où elles ont divergé (le modèle, l'invite système, les outils ou l'historique des messages) afin que vous puissiez corriger la cause première au lieu de deviner.
Fonctionnement des diagnostics du cache
Lorsque l'en-tête bêta est présent, l'API stocke une empreinte (« fingerprint ») légère de chaque requête, indexée par l'id de la réponse. Lors de votre requête suivante, incluez cet id en tant que diagnostics.previous_message_id. L'API reconstruit l'empreinte de la nouvelle requête, la compare à celle stockée et joint à la réponse un objet diagnostics décrivant le premier point de divergence.
La comparaison porte sur la structure de la requête, indépendamment du fait que le cache ait effectivement été atteint ou non. Consultez Lire les diagnostics conjointement avec l'utilisation pour savoir comment combiner le résultat diagnostics avec usage.cache_read_input_tokens.
Les empreintes ne contiennent que des hachages et des estimations du nombre de jetons (jamais le contenu brut du prompt), sont conservées pendant une durée limitée, sont restreintes à votre organisation et à votre espace de travail, et ne sont utilisées à aucune autre fin.
Utilisation de base
Envoyez l'en-tête bêta à chaque tour. Au premier tour, transmettez "previous_message_id": null pour activer la fonctionnalité sans message antérieur auquel comparer. Aux tours suivants, transmettez l'id de la réponse précédente.
client = anthropic.Anthropic()
SYSTEM = "You are an AI assistant analyzing a large document. <document>...</document>"
# Tour 1 : activer avec previous_message_id=None
r1 = client.beta.messages.create(
model="claude-opus-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[{"role": "user", "content": "Summarize section 1."}],
diagnostics={"previous_message_id": None},
betas=["cache-diagnosis-2026-04-07"],
)
# Tour 2 : référencer l'id de la réponse précédente
r2 = client.beta.messages.create(
model="claude-opus-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
betas=["cache-diagnosis-2026-04-07"],
)
diagnostics = r2.diagnostics
if diagnostics is None:
print("No divergence detected.")
elif diagnostics.cache_miss_reason is None:
print("Comparison still pending.")
else:
print(f"cache_miss_reason: {diagnostics.cache_miss_reason.type}")Streaming
Dans les réponses en streaming, diagnostics apparaît dans l'événement message_start.
# Tour 2 : streaming, en référençant l'id de la réponse précédente
with client.beta.messages.stream(
model="claude-opus-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
betas=["cache-diagnosis-2026-04-07"],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print()
r2 = stream.get_final_message()
diagnostics = r2.diagnostics
if diagnostics is None:
print("No divergence detected.")
elif diagnostics.cache_miss_reason is None:
print("Comparison still pending.")
else:
print(f"cache_miss_reason: {diagnostics.cache_miss_reason.type}")L'événement message_start contient le champ diagnostics complet ; consultez Format de la réponse pour connaître les valeurs possibles.
Propager les diagnostics dans une boucle de conversation
Dans une conversation à plusieurs tours, reportez le dernier id de réponse en tant que previous_message_id à chaque tour. La première itération transmet null pour activer la fonctionnalité ; chaque itération suivante transmet l'id de la réponse précédente.
client = anthropic.Anthropic()
SYSTEM = "You are an AI assistant analyzing a large document. <document>...</document>"
messages = []
prev_id = None
for i, user_message in enumerate(
["Summarize section 1.", "Now section 2.", "Now section 3."]
):
messages.append({"role": "user", "content": user_message})
r = client.beta.messages.create(
model="claude-opus-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=messages,
diagnostics={"previous_message_id": prev_id},
betas=["cache-diagnosis-2026-04-07"],
)
if r.diagnostics is not None and r.diagnostics.cache_miss_reason is not None:
print(f"Turn {i + 1} cache_miss_reason: {r.diagnostics.cache_miss_reason.type}")
messages.append({"role": "assistant", "content": r.content})
prev_id = r.idFormat de la réponse
Le champ diagnostics de l'objet Message de la réponse peut prendre quatre états :
| Valeur | Signification |
|---|---|
| champ absent | La requête n'incluait pas diagnostics, ou l'en-tête bêta était manquant. |
null | Soit previous_message_id valait null (premier tour, rien à comparer), soit une comparaison a été effectuée et n'a trouvé aucune divergence. |
{"cache_miss_reason": null} | La comparaison était encore en cours lorsque la réponse a été sérialisée. Cela peut se produire lorsque la réponse démarre très rapidement. Considérez ce résultat comme non concluant et vérifiez au tour suivant. |
{"cache_miss_reason": {...}} | Un cache_miss_reason est joint. Pour les types *_changed, il identifie le premier point de divergence ; previous_message_not_found et unavailable correspondent aux cas où aucune comparaison n'a été produite. |
Lorsque cache_miss_reason est non nul, il se présente ainsi :
{
"id": "msg_01Xyz...",
"type": "message",
"role": "assistant",
"content": [{ "type": "text", "text": "..." }],
"usage": {
"input_tokens": 42,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 41850,
"output_tokens": 210
},
"diagnostics": {
"cache_miss_reason": {
"type": "system_changed",
"cache_missed_input_tokens": 41850
}
}
}Types de raisons d'échec du cache
cache_miss_reason est une union discriminée sur type. La réponse ne signale que la divergence la plus précoce ; corrigez-la donc en premier, car des divergences ultérieures peuvent se cacher derrière elle.
| Type | Signification | Ce qu'il faut modifier |
|---|---|---|
model_changed | Le model diffère de celui de la requête précédente (par exemple, un routeur, un test A/B ou un mécanisme de repli a sélectionné un modèle différent). Le cache est propre à chaque modèle. | Conservez le même modèle tout au long d'une conversation mise en cache. |
system_changed | Le paramètre system diffère. Généralement, un horodatage, un identifiant de requête ou une autre valeur propre à chaque requête a été interpolé dans l'invite système. | Faites de l'invite système une constante stable à l'octet près et déplacez les données dynamiques dans le premier message user situé après votre point de rupture du cache. |
tools_changed | Le tableau tools diffère : des outils ont été ajoutés, supprimés ou réordonnés entre les tours, ou le JSON input_schema d'un outil a été sérialisé de manière non déterministe. | Envoyez la même liste d'outils à chaque tour, dans un ordre fixe, avec des schémas sérialisés de manière déterministe (par exemple, en triant les clés). |
messages_changed | Le modèle, l'invite système et les outils correspondent tous, mais une entrée antérieure de messages a été modifiée, réordonnée ou supprimée au lieu d'être simplement complétée par ajout. Généralement, l'historique de la conversation a été tronqué ou modifié, ou les tours de l'assistant et les blocs tool_result ont été resérialisés différemment lors du renvoi. | Traitez l'historique comme étant en ajout seul ; renvoyez le content de l'assistant et les résultats d'outils tels quels. |
previous_message_not_found | Aucune empreinte stockée n'existe pour le previous_message_id fourni. Cela ne prouve pas que votre requête a changé. Généralement, la requête précédente ne comportait pas l'en-tête bêta, elle provenait d'un autre espace de travail, ou trop de temps s'est écoulé depuis son envoi. | Envoyez l'en-tête bêta à chaque tour et maintenez les tours consécutifs rapprochés dans le temps. |
unavailable | Les informations de diagnostic n'étaient pas disponibles pour cette requête. Cela inclut le cas où model, system et tools correspondent mais où un autre paramètre de requête affectant le prompt (tool_choice, thinking, context_management, output_config, output_format ou l'ensemble des en-têtes anthropic-beta actifs) diffère, ainsi que les conversations très longues où la divergence se situe au-delà de l'horizon de comparaison. Votre requête a été traitée normalement. | Maintenez constants les paramètres de requête affectant le prompt pendant toute la durée de vie d'une conversation mise en cache. Si le problème persiste, appliquez les vérifications manuelles décrites dans la section Résolution des problèmes courants de la page sur la mise en cache des prompts. |
Lire les diagnostics conjointement avec l'utilisation
diagnostics répond à la question « ma requête a-t-elle changé ? » tandis que usage.cache_read_input_tokens répond à la question « le cache a-t-il été atteint ? ». Les combiner vous indique où chercher.
Cette matrice s'applique aux tours où vous avez transmis un véritable previous_message_id. Au premier tour (previous_message_id: null), diagnostics vaut toujours null et cache_read_input_tokens est normalement nul, car le cache est en cours d'écriture et non de lecture ; aucun dépannage n'est nécessaire. La matrice ne s'applique pas non plus lorsque cache_miss_reason vaut null (la comparaison est encore en attente ; vérifiez au tour suivant) ni lorsque son type est previous_message_not_found ou unavailable (aucune comparaison n'a été produite).
| Résultat des diagnostics | Jetons lus depuis le cache | Interprétation |
|---|---|---|
null | élevé | Fonctionnement conforme aux attentes. Votre préfixe est stable et le cache a été atteint. |
null | faible ou nul | Vos requêtes correspondent, mais l'entrée du cache n'était plus disponible. Envisagez de réduire les intervalles entre les tours ou d'utiliser le TTL de cache d'une heure. |
cache_miss_reason est d'un type *_changed | faible ou nul | Votre bogue. La requête a changé ; corrigez la cause indiquée par type. |
cache_miss_reason est d'un type *_changed | élevé | Rare. Un changement est survenu tard dans le prompt, mais un point de rupture cache_control antérieur a tout de même été atteint. Cela vaut la peine d'être corrigé, mais l'impact est faible. |
Limitations
- Bêta : les noms de champs et leur sémantique peuvent changer tant que cette fonctionnalité est en bêta.
- Claude API uniquement : non disponible sur Amazon Bedrock ni sur Google Cloud.
- Conservation limitée : les empreintes utilisées pour la recherche par
previous_message_idexpirent après une courte période. Effectuez les comparaisons de diagnostic entre des requêtes rapprochées dans le temps. - Même espace de travail : la requête précédente doit avoir été exécutée dans la même organisation et le même espace de travail. Pour le vérifier, comparez l'en-tête de réponse
anthropic-workspace-iddes deux réponses. - Horizon de comparaison : pour les conversations très longues où le seul changement se situe profondément dans la liste des messages, la réponse peut être
unavailableplutôt qu'un emplacement précis. - Au mieux : les diagnostics ne bloquent ni ne font jamais échouer votre requête. Si les informations de diagnostic ne sont pas disponibles, la réponse renvoie
unavailable, oucache_miss_reason: nulllorsque la comparaison était encore en cours.
Conservation des données
Les diagnostics du cache sont éligibles au ZDR (sous conditions). Anthropic ne stocke pas le texte brut de vos prompts ni les sorties de Claude pour cette fonctionnalité.
L'empreinte stockée pour chaque requête se compose uniquement de hachages cryptographiques et d'estimations du nombre de jetons, indexés par l'id de la réponse et restreints à votre organisation et à votre espace de travail. Les empreintes expirent après une courte période et ne sont utilisées à aucune autre fin.
Pour connaître l'éligibilité au ZDR de l'ensemble des fonctionnalités, consultez API et conservation des données.
Voir aussi
Compatibility
| Supported platforms |
|
|---|
Was this page helpful?