Prompt Caching avec Claude — Ce que `cache_control: ephemeral` économise vraiment
Le prompt caching d'Anthropic peut réduire votre facture de 80–95% sur les bonnes formes. Mal ordonnez vos blocs, et il ne fait rien du tout. Les patterns, les pièges et les chiffres de production.

En bref
Le prompt caching avec Claude est le levier de réduction de coûts le plus puissant disponible sur l'API d'Anthropic en 2026. Bien appliqué, il réduit la facture des tokens d'entrée sur les contextes longs et stables de 80–95% et diminue la latence médiane de 20–40%. Mal appliqué, il ne fait littéralement rien.
Sur les agents que nous faisons tourner en production, la différence entre "le caching fonctionne" et "le caching ne fait rien" se résume presque toujours à l'une de trois erreurs : des blocs dans le mauvais ordre, du contenu incorrectement marqué comme cacheable, ou l'attente d'un hit après expiration du TTL.
Voici le modèle mental validé en production.
La structure tarifaire qui rend le caching rentable
Le caching d'Anthropic repose sur deux prix et un TTL :
- Écriture de cache :
1.25×le prix d'entrée standard (une légère prime pour écrire le cache la première fois) - Lecture de cache :
0.1×le prix d'entrée standard (soit 90% de remise sur la portion mise en cache) - TTL par défaut : 5 minutes depuis la dernière lecture (ce délai glisse à chaque hit). Un TTL étendu d'une heure est disponible avec un multiplicateur d'écriture plus élevé.
Le seuil de rentabilité est atteint à deux lectures. Si vous écrivez un bloc de cache et le lisez deux fois dans les 5 minutes, vous avez déjà économisé de l'argent. Dix lectures, et vous n'avez payé que 10% de ce que vous auriez payé sans caching.
Pour les agents qui appellent l'API de nombreuses fois par minute sur le même prompt système — workers de chat, classifieurs, pipelines batch — c'est transformateur. Pour des appels ponctuels qui ne se répètent jamais, c'est net-négatif.
La règle des 4 blocs
Anthropic expose un maximum de 4 points d'arrêt de cache par requête. Chaque point d'arrêt marque la fin d'un bloc de cache — tout ce qui le précède (depuis le point d'arrêt précédent ou le début de la requête) est mis en cache comme un seul chunk.
Ces quatre points d'arrêt sont répartis sur l'entrée. La disposition canonique pour un agent de chat :
┌─────────────────────────────────────────────┐ <- début
│ prompt système (long, stable) │
│ - rôle, règles outils, garde-fous │
├─ cache_control: ephemeral ──────────────────┤ <- point d'arrêt 1
│ définitions d'outils (stables sur l'agent) │
├─ cache_control: ephemeral ──────────────────┤ <- point d'arrêt 2
│ contexte statique (config org, docs policy) │
├─ cache_control: ephemeral ──────────────────┤ <- point d'arrêt 3
│ historique de conversation récent │
│ - N derniers messages │
├─ cache_control: ephemeral ──────────────────┤ <- point d'arrêt 4
│ message utilisateur courant (volatile) │
└─────────────────────────────────────────────┘ <- fin (jamais mis en cache)
En régime stable, les trois premiers blocs sont stables pour toute la durée de vie de l'agent (souvent des heures ou des jours). Les lectures sur ces blocs coûtent 90% moins cher. Le bloc 4 correspond à "la conversation jusqu'au dernier tour inclus", partagé entre toutes les tentatives du même tour mais invalidé à chaque nouveau message. Tout ce qui suit est non mis en cache — typiquement le dernier message de l'utilisateur.
En pratique, on utilise rarement les 4 points en mode chat. Deux ou trois suffisent. L'essentiel est de savoir quelles frontières tracer.
L'ordre compte plus qu'on ne le croit
La clé de cache est un hash de préfixe de l'entrée. Si quoi que ce soit change avant un point d'arrêt cache_control, le hash du point d'arrêt change, et la lecture devient une écriture — au prix majoré, sans remise.
C'est le mode d'échec le plus courant que nous voyons en revue de code :
// ❌ CASSÉ — prompt système reconstruit avec un timestamp à chaque appel
const system = `You are an agent. Today is ${new Date().toISOString()}.
[long static rules block]
`
L'interpolation de Date() invalide le cache à chaque appel. Taux d'écriture de cache : 100%. Taux de hits : 0%. La facture augmente (vous payez le multiplicateur d'écriture 1.25× sur chaque requête).
La correction consiste à pousser le contenu volatile après tout le contenu statique, en aval du point d'arrêt :
// ✅ FONCTIONNE
const system = `You are an agent.
[long static rules block]
`
const messages = [
{ role: 'user', content: `Today is ${new Date().toISOString()}.` }, // éphémère
// ... reste de la conversation
]
Un check mental utile : avant chaque point d'arrêt, demandez-vous "est-ce que tout ce qui précède est strictement identique au dernier appel ?" Si non, le point d'arrêt est gaspillé.
L'illusion du caching
Anthropic retourne cache_creation_input_tokens et cache_read_input_tokens dans chaque réponse. Ces deux nombres sont la seule vérité terrain.
const response = await anthropic.messages.create({ ... })
console.log({
cache_read: response.usage.cache_read_input_tokens,
cache_write: response.usage.cache_creation_input_tokens,
input: response.usage.input_tokens,
output: response.usage.output_tokens,
})
Sur un agent sain en trafic stable, vous verrez quelque chose comme :
{ cache_read: 8421, cache_write: 0, input: 142, output: 87 }
Les tokens lus sont importants, l'écriture est nulle, et les tokens d'entrée standard reflètent uniquement la queue volatile. Voilà à quoi ressemble le succès.
Ce que nous observons sur du code qui croit utiliser le caching :
{ cache_read: 0, cache_write: 8563, input: 142, output: 87 }
Écriture à chaque appel, jamais de lecture. Soit le préfixe est instable, soit la forme de la requête a changé, soit 5 minutes se sont écoulées entre les appels. Surveillez cette métrique de près.
Nous loguons ces deux champs à chaque appel API comme propriété PostHog et construisons un dashboard avec cache_hit_ratio = cache_read / (cache_read + cache_write) segmenté par agent et par modèle. Quand il descend sous ~0.6, quelque chose a changé en amont.
Règles pratiques d'ordonnancement des blocs
Après plusieurs déploiements en production, les règles ci-dessous ont tenu :
- Les outils passent en premier. Les définitions d'outils sont stables pendant toute la durée de vie de l'agent et souvent volumineuses (une palette de 10 outils peut représenter 3–5k tokens). Marquez la fin des outils avec un point d'arrêt.
- Le prompt système avant les outils ? Après ? La documentation Anthropic autorise les deux, mais en pratique nous mettons le prompt système en premier et les outils en second. Le prompt système est plus court et change moins souvent que les outils (on ajoute des outils plus fréquemment qu'on ne modifie la description du rôle). Stable-plus-court-en-premier = meilleure survie du cache face aux petites modifications.
- Le contexte par organisation (config, docs, niveau de plan) vient après les outils. Stable pour la session de l'organisation, change par tenant.
- L'historique de conversation récent suit le contexte par organisation. Tout jusqu'au "dernier message" peut parfois être mis en cache si la conversation est relancée ; le tout dernier message de l'utilisateur n'est jamais mis en cache.
- Le message utilisateur courant passe en dernier et n'est jamais marqué. C'est la queue volatile.
Quand le TTL de 5 minutes vous rattrape
Le TTL par défaut est de 5 minutes depuis la dernière lecture. Si votre trafic n'est pas assez dense, vous écrirez le cache, obtiendrez une ou deux lectures, puis le verrez expirer — et le prochain appel écrira à nouveau au prix majoré de 1.25×.
Trois patterns pour gérer ça :
1. Agents à trafic en rafale (la plupart des workers de chat) : quand le trafic est actif, plusieurs lectures se produisent bien dans les 5 minutes ; le cache se rentabilise de nombreuses fois. Quand c'est inactif, le cache expire et le prochain utilisateur paie une écriture. Net positif dans presque tous les cas.
2. Agents à trafic peu dense (un assistant back-office interrogé 5 fois par heure) : le TTL de 5 minutes expire presque toujours entre les lectures. Les écritures dépassent les lectures. Le caching est légèrement déficitaire. Solution : basculer vers le TTL étendu d'une heure (cache_control: { type: 'ephemeral', ttl: '1h' }), qui supporte un multiplicateur d'écriture plus élevé (~2×) mais reste actif assez longtemps pour générer des lectures. C'est gagnant sur un trafic peu dense mais récurrent.
3. Agents ponctuels (un pipeline d'analyse de PDF à usage unique) : la requête ne se répète jamais. Ne pas mettre en cache. Vous paieriez la pénalité d'écriture pour rien.
Le seuil de rentabilité entre le TTL standard et le TTL d'une heure dépend de votre profil, mais la règle pratique : si votre écart moyen entre requêtes sur le même préfixe est supérieur à 4 minutes et inférieur à 50 minutes, passez à 1h. En dessous de 4 minutes, le TTL par défaut de 5 minutes convient. Au-delà de 50 minutes, ne mettez pas en cache du tout.
Caching multi-tours — ce qui est réellement mis en cache
Un point subtil qui piège les équipes : à mesure que la conversation grandit, le préfixe change. Chaque nouveau tour étend le tableau de messages. Le préfixe de cache valide au tour 5 est donc invalidé au tour 6 — le préfixe du tour 6 correspond à "tout jusqu'au tour 5 inclus", une chaîne plus longue.
La façon dont Anthropic gère cela : le préfixe entier jusqu'au dernier point d'arrêt de cache est vérifié dans le cache. Si vous placez un point d'arrêt à la fin de l'historique du tour 5, au tour 6, l'API peut encore hitter le cache pour tout jusqu'au tour 5, et seul le message de l'utilisateur du tour 6 n'est pas mis en cache. C'est exactement ce qu'on veut.
En pratique : placez un point d'arrêt après l'historique de conversation, pas sur des messages individuels. L'API fera avancer le cache au fil de la conversation, tant que les messages ne sont pas mutés.
Ce qui casse cela : modifier des messages passés, les réordonner, ajouter des résultats d'outils à des positions arbitraires. Chacune de ces mutations invalide le préfixe à partir de ce point.
Exemple de calcul de coût
Chiffres réels d'un agent de chat-ops que nous faisons tourner, pour un seul appel en milieu de conversation :
| Composant | Tokens | Sans caching | Avec caching |
|---|---|---|---|
| Prompt système | 1 200 | $0,0036 | $0,00036 (lecture cache) |
| Définitions d'outils | 2 800 | $0,0084 | $0,00084 (lecture cache) |
| Contexte organisation | 600 | $0,0018 | $0,00018 (lecture cache) |
| Historique récent | 3 400 | $0,0102 | $0,00102 (lecture cache) |
| Message courant | 180 | $0,00054 | $0,00054 |
| Sortie | 320 | $0,0048 | $0,0048 |
| Total | — | $0,029 | $0,011 |
Les deux appels produisent le même résultat. La version avec cache coûte ~38% de la version sans cache sur cet appel unique. Sur une journée chargée avec des milliers d'appels par agent, c'est la différence entre une facture Anthropic qui évolue linéairement avec le nombre de sièges et une qui évolue de façon sous-linéaire.
Les tokens de sortie dominent quand l'entrée est courte. Le caching ne bénéficie qu'au côté entrée. Cette technique est donc la plus efficace quand vous avez une grande entrée, une petite sortie — exactement la forme des agents avec tool calling forcé (règles + outils volumineux, sortie structurée concise).
Ce que vous ne pouvez pas mettre en cache
Quelques points qui sèment souvent la confusion :
- La sortie n'est pas cacheable. Les tokens de sortie sont toujours facturés au tarif standard. L'optimisation porte sur l'entrée que vous réutilisez.
- Le cache n'est pas partageable entre différents
modelIDs. Passer de Sonnet à Haiku invalide le cache. Si votre pipeline est multi-modèles (Sonnet pour le routing, Haiku pour le re-check de sécurité), chaque modèle a son propre budget de cache. - Les changements de
temperature,top_pou d'autres paramètres d'échantillonnage invalident le cache — ils font partie de la clé de cache. - Le contenu image ne peut pas être mis en cache au moment de la rédaction de cet article (cela peut évoluer ; consultez les notes de version d'Anthropic). Anticipez-le si vous déployez des pipelines multimodaux.
Quand le prompt caching est la mauvaise optimisation
Quelques scénarios de production où le caching ajoute de la complexité sans bénéfice notable :
- Prompts courts (moins de ~1k tokens). La taille minimale cacheable fait que les prompts très courts ne peuvent pas être mis en cache du tout, et même lorsque c'est possible, les économies sont négligeables.
- Prompts à haute variance où chaque appel a un contenu différent (résumé ponctuel, génération de rapport personnalisé). Le préfixe est rarement identique → pas de hits.
- Agents où la sortie domine l'entrée (génération de contenu long à partir d'un prompt court). La sortie n'est pas mise en cache, l'optimisation déplace la courbe de ~5% seulement.
- Cas limites de charges de travail réglementées où la réutilisation de prompts pourrait déclencher des signaux de conformité (exigences contractuelles spécifiques ou de résidence des données). Vérifiez toujours avant d'activer.
Mise en production
Trois pratiques concrètes que nous recommandons :
- Loguez
cache_read_input_tokensetcache_creation_input_tokensà chaque appel, segmentés par agent. C'est votre tableau de bord. Si vous ne mesurez pas, le caching reste de la magie noire — et la magie noire déçoit toujours. - Traitez votre structure de prompt comme un contrat stable. Toucher au prompt système est un événement de release, pas une modification anodine. Incrémenter une version d'un bloc mis en cache invalide le cache pour toute la durée nécessaire au trafic pour le remplir à nouveau. Soyez délibéré.
- Construisez un canary "sans cache". Faites passer un petit pourcentage du trafic avec le caching désactivé et comparez coût, latence et qualité de sortie. Le caching ne devrait pas modifier la qualité, mais les bugs arrivent — le canary est votre alarme.
Pour conclure
Le prompt caching est l'un des rares leviers au niveau de l'API qui rembourse réellement le travail d'ingénierie. Le pattern est simple — grand préfixe stable, queue volatile courte, point d'arrêt entre les deux, métriques loguées — mais les modes d'échec sont silencieux. La plupart des gains que nous observons viennent d'équipes qui ont commencé à mesurer le taux de hit de cache, puis ont corrigé ce qui le brisait.
Si vous avez activé le caching et n'êtes pas sûr qu'il fonctionne vraiment, un examen de 30 minutes de votre ratio cache_read / cache_write par agent vous donnera la réponse immédiatement. Si vous souhaitez un regard extérieur sur votre structure de prompt, contactez-nous.
Travailler avec Ikki
Vous payez plein tarif sur les tokens Claude ?
Nous auditons votre structure de prompt et débloquons 40–90% de réduction de coût via le cache ephemeral. Pilote en deux jours.
Autres articles
La semaine où Anthropic a pris le contrôle de la pile complète
Project Glasswing en bêta publique, acquisition de Stainless, sept releases SDK en quatre jours. La question n'est plus 'quel modèle' — c'est 'quelle plateforme'.
AgentsSix releases en onze jours : ce que le sprint pré-I/O de Google annonce
@google/genai a livré les API Agent et Environment aujourd'hui — à quelques jours de Google I/O. La cadence du SDK vous dit ce qui arrive avant le keynote.