Le prompt caching avec l'API Claude : réduisez vos coûts d'entrée sans changer de modèle
Le prompt caching réduit le coût des entrées volumineuses et stables — votre prompt système, vos définitions d'outils, vos exemples few-shot — à environ 10 % du tarif d'entrée normal sur les requêtes répétées. Le mécanisme repose sur une correspondance par préfixe : placez un marqueur cache_control à la fin de votre contenu stable et gardez tout ce qui est volatil après lui. L'erreur qui ruine les taux de cache hit, c'est de laisser un horodatage ou un UUID s'infiltrer dans le préfixe.
Chaque mercredi. 28 400+ opérateurs. Zéro superflu.
✓ Vérifiez votre boîte mail — cliquez sur le lien de confirmation pour finaliser l'inscription.
✓ Vous êtes inscrit !
✓ Vous êtes déjà inscrit.
Table of contents
Open Table of contents
- Ce que fait réellement le prompt caching
- L’invariant de correspondance par préfixe
- Sur quoi placer un marqueur de cache
- Ce qu’il ne faut PAS mettre en cache (les invalidants silencieux)
- Vérifier votre taux de cache hit
- Le TTL d’1 heure : quand le surcoût d’écriture en vaut la peine
- Le pré-chauffage : rendre la première requête bon marché
- Le prompt caching dans les boucles agentiques
- Ce que ça donne sur la facture
- Le mot de la fin de l’opérateur
Ce que fait réellement le prompt caching
Chaque appel à l’API Claude envoie des tokens. Sans cache, chaque token de votre requête — prompt système, définitions d’outils, exemples few-shot et message utilisateur — est facturé au tarif d’entrée normal. Avec le cache, un préfixe de ces tokens est stocké sur les serveurs d’Anthropic après la première requête. Sur les requêtes suivantes qui partagent exactement ce préfixe, vous payez un tarif de lecture de cache au lieu de les retraiter de zéro.
L’écart de coût est bien réel :
- Écriture du cache : ~1,25× le tarif d’entrée de base (TTL de 5 minutes) ou ~2× (TTL d’1 heure)
- Lecture du cache : ~0,1× le tarif d’entrée de base
- Seuil de rentabilité : 2 requêtes avec un TTL de 5 minutes, 3 requêtes avec un TTL d’1 heure
Une fois le seuil de rentabilité dépassé — ce qui arrive vite sur tout agent exécuté plus de quelques fois par jour — chaque cache hit supplémentaire représente une remise de ~90 % sur ces tokens.
L’invariant de correspondance par préfixe
C’est la règle unique dont tout le reste découle : la clé de cache est une correspondance par préfixe de votre prompt rendu.
Les serveurs d’Anthropic stockent le contenu rendu depuis le début de votre prompt jusqu’au marqueur cache_control. Pour qu’un cache hit se produise à la requête suivante, chaque token depuis le début du prompt jusqu’à ce marqueur doit être identique — octet pour octet.
L’ordre de rendu pour la correspondance par préfixe est : tools → system → messages. Votre tableau de tools est donc haché en premier, puis le bloc system, puis les messages dans l’ordre.
Ce que cela implique en pratique : le contenu stable doit venir en premier. Si votre prompt système fait référence à quoi que ce soit de dynamique — une date courante, un identifiant utilisateur, un identifiant de trace de requête — et que cela apparaît avant le marqueur cache_control, le cache échouera à chaque requête parce que le préfixe ne cesse de changer.
Sur quoi placer un marqueur de cache
Les cibles à plus fort effet de levier sont :
1. Votre prompt système
Les prompts système constituent généralement le plus grand bloc stable. Un persona d’agent détaillé, une liste de règles comportementales, un ensemble d’instructions de format de sortie — tout cela est identique à chaque invocation du même agent. Marquez-le :
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 1024,
system: [
{
type: "text",
text: `You are a content operations agent for alejandrorioja.com.
Your job is to draft blog posts in Alejandro's voice: direct, practitioner,
first-person, numbered lists, honest caveats. No hedging. No filler.
Every section must earn its place.
[... 2000 more tokens of stable instructions ...]`,
cache_control: { type: "ephemeral" },
},
],
messages: [
{
role: "user",
content: "Draft a post about prompt caching.",
},
],
});Le cache_control: { type: "ephemeral" } sur le bloc system indique à Claude de mettre en cache tout ce qui précède ce bloc, y compris lui-même. Le tableau messages est volatil — différent à chaque requête — et reste hors de la limite du cache.
2. Les définitions d’outils
Si votre agent utilise des outils, ces définitions peuvent être conséquentes. Un schéma d’outil bien documenté avec sa description, ses noms de paramètres et ses valeurs d’enum peut atteindre 500 à 1 000 tokens par outil. Avec 5 outils, cela représente jusqu’à 5 000 tokens que vous payez à retraiter à chaque appel :
const response = await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 1024,
tools: [
{
name: "search_airtable",
description: "Search the Airtable content queue...",
input_schema: { type: "object", properties: { query: { type: "string" } } },
},
// ... more tools ...
{
name: "post_to_kit",
description: "Schedule a broadcast via the Kit API...",
input_schema: { /* ... */ },
// Mark the last tool to cache the entire tools array
} as Anthropic.Tool & { cache_control: { type: "ephemeral" } },
],
system: "...",
messages: [...],
});Marquez le dernier outil du tableau. La correspondance par préfixe couvrira l’ensemble du tableau de tools à partir de ce point.
3. Les exemples few-shot dans les messages
Si vous passez des exemples few-shot statiques comme premiers messages du tableau messages, ils peuvent eux aussi être mis en cache. Structurez-les comme les N premiers messages et marquez le dernier tour d’exemple :
const messages: Anthropic.MessageParam[] = [
{
role: "user",
content: [
{
type: "text",
text: "Here are examples of posts in my voice:\n\n[Example 1...]\n\n[Example 2...]",
cache_control: { type: "ephemeral" },
} as Anthropic.TextBlockParam & { cache_control: { type: "ephemeral" } },
],
},
{
role: "assistant",
content: "Understood. I'll follow that voice.",
},
// The actual user turn follows — this is volatile, no cache marker
{
role: "user",
content: actualUserRequest,
},
];Ce qu’il ne faut PAS mettre en cache (les invalidants silencieux)
Voici les éléments qui semblent stables mais ne le sont pas — et qui ruineront votre taux de cache hit en silence. L’API ne vous préviendra pas. Vous verrez simplement cache_creation_input_tokens à chaque requête et vous vous demanderez pourquoi.
Les horodatages dans le prompt système. L’erreur la plus courante de toutes :
// This invalidates the cache on every request
const system = `You are an agent. Current time: ${new Date().toISOString()}`;Déplacez les horodatages dans le message utilisateur, là où ils ont leur place :
// Stable system prompt — cacheable
const system = `You are an agent. Use the current time provided by the user.`;
// Volatile user message — not cached
const userMessage = `Current time: ${new Date().toISOString()}. Run the daily brief.`;Les UUID aléatoires et les identifiants de trace. Même problème. Si vous injectez un identifiant de trace dans le bloc system à des fins de journalisation, chaque requête obtient un préfixe inédit.
La sérialisation JSON non déterministe. Si vous sérialisez un objet dans le prompt système et que l’ordre des clés n’est pas garanti, la chaîne rendue peut différer même lorsque les données sous-jacentes sont identiques. Sérialisez avec un ordre de clés stable ou utilisez une chaîne de gabarit.
La sélection dynamique d’exemples few-shot. Si vous choisissez vos exemples few-shot en fonction de la requête courante et que vous les placez dans le préfixe mis en cache, vous avez rendu le préfixe « stable » dépendant de la requête. Soit vous vous en tenez à des exemples fixes pour la couche de cache, soit vous déplacez les exemples dynamiques vers le tour de message non mis en cache.
Vérifier votre taux de cache hit
Chaque réponse inclut des métadonnées d’usage. Vérifiez-les :
const response = await client.messages.create({ /* ... */ });
console.log({
inputTokens: response.usage.input_tokens,
cacheRead: response.usage.cache_read_input_tokens,
cacheWrite: response.usage.cache_creation_input_tokens,
outputTokens: response.usage.output_tokens,
});À la première requête : cache_creation_input_tokens sera non nul, cache_read_input_tokens sera à 0. C’est l’écriture.
À un cache hit : cache_read_input_tokens sera non nul, cache_creation_input_tokens sera à 0. C’est la lecture.
Si vous voyez cache_creation_input_tokens à chaque requête, c’est que votre préfixe change. Ajoutez une instruction de log qui affiche les 200 premiers caractères de votre prompt système rendu avant chaque appel — un horodatage flottant sautera immédiatement aux yeux.
Le TTL d’1 heure : quand le surcoût d’écriture en vaut la peine
Le TTL par défaut est de 5 minutes. Si votre agent tourne à faible fréquence — moins d’une fois toutes les 5 minutes — vous paierez des coûts d’écriture de cache sur la plupart des requêtes sans bénéficier de lectures.
// Opt into a 1-hour TTL
cache_control: { type: "ephemeral", ttl: "1h" }L’écriture avec TTL d’1 heure coûte ~2× le tarif d’entrée de base au lieu de 1,25×. Le calcul : si vous touchez le cache 3 fois ou plus par heure, le TTL d’1 heure fait économiser de l’argent. Si votre agent tourne une fois par jour (comme mon briefing quotidien), même le TTL d’1 heure n’aidera pas — vous payez des coûts d’écriture à chaque fois. Dans ce cas, le bénéfice du cache est modeste, à moins que le prompt système ne soit énorme.
Mon agent de briefing quotidien a un prompt système de 3 000 tokens mais ne tourne qu’une fois par jour. Le cache n’aide pas. Mon agent de newsletter tourne des dizaines de fois par session pendant la rédaction — le cache fait économiser substantiellement.
Le pré-chauffage : rendre la première requête bon marché
Si vous savez qu’un pic de trafic arrive — un traitement par lots, le lancement d’une API — vous pouvez pré-chauffer le cache avec une requête factice à faible coût :
// Pre-warm: write the cache at near-zero output cost
await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 1, // minimal output
system: [{ type: "text", text: stableSystemPrompt, cache_control: { type: "ephemeral" } }],
messages: [{ role: "user", content: "ping" }],
});
// Now the real requests read from cacheC’est surtout utile pour le traitement par lots, lorsque vous lancez de nombreuses requêtes en parallèle et que vous voulez que chacune touche un cache déjà chaud plutôt que de se précipiter pour l’écrire.
Le prompt caching dans les boucles agentiques
Dans une boucle agentique multi-tours, l’historique de conversation grossit à chaque tour. Le cache est assez intelligent pour gérer cela : il utilise une fenêtre de retour en arrière de 20 blocs, en cherchant le plus long préfixe correspondant parmi les 20 derniers blocs de contenu.
L’implication pratique : gardez votre contenu stable (prompt système, définitions d’outils) ancré tout en haut. L’historique de conversation qui grossit à la fin du tableau de messages ne cassera pas la correspondance par préfixe pour les blocs stables — ils précèdent le contenu volatil, et la correspondance par préfixe démarre du haut.
En pratique, mes agents structurent les tours comme ceci :
System (cached) → Tools (cached) → Few-shot (cached) → Turn 1 → Turn 2 → ... → Current turnLe cache couvre tout jusqu’au marqueur few-shot. L’historique des tours qui grossit ensuite est retraité à chaque fois, mais ce n’est pas grave — ces tokens sont propres à la session et restent petits par rapport au préfixe stable.
Ce que ça donne sur la facture
Prenons un agent à haute fréquence : 100 appels par jour, prompt système de 4 000 tokens, tarification Sonnet.
Sans cache :
- 100 × 4 000 tokens × 3 $/1M = 1,20 $/jour
Avec cache (TTL de 5 min, en supposant 50 appels/heure au pic) :
- 1 écriture toutes les 5 minutes × 3,75 $/1M × 4 000 tokens = ~0,02 $/jour en écritures
- ~98 lectures/jour × 0,30 $/1M × 4 000 tokens = 0,12 $/jour en lectures
Cela représente environ 90 % de réduction sur ces tokens d’entrée. À l’échelle — 1 000 appels par jour — l’écart se cumule encore davantage. Et cela s’ajoute à toute économie de routage de modèle issue du calcul Haiku vs Sonnet : le cache fonctionne à tous les niveaux.
Le mot de la fin de l’opérateur
Le prompt caching est l’optimisation de coût la plus simple de l’API Claude : un champ supplémentaire sur les blocs de contenu que vous écrivez déjà. La contrainte, c’est la discipline autour de la stabilité du préfixe — rien de dynamique avant le marqueur de cache. Si vous parvenez à garder votre prompt système, vos outils et vos éventuels exemples statiques exempts de contenu volatil, vous paierez ~10 % du coût d’entrée normal à chaque cache hit. Pour les agents à haute fréquence dotés de gros prompts stables, c’est un levier plus puissant que de changer de niveau de modèle.
À lire aussi : Le calcul du coût des agents IA : quand Haiku bat Sonnet · Agents déclenchés par événement vs planifiés · Les 5 outils IA que j’utilise vraiment pour faire tourner mon activité
Chaque mercredi. 28 400+ opérateurs. Zéro superflu.
✓ Vérifiez votre boîte mail — cliquez sur le lien de confirmation pour finaliser l'inscription.
✓ Vous êtes inscrit !
✓ Vous êtes déjà inscrit.
Recevez le guide IA dans votre boîte mail
Chaque mercredi. 28 400+ opérateurs. Zéro superflu.
Vérifiez votre boîte mail.
Nous vous avons envoyé un e-mail de confirmation — cliquez sur le lien pour finaliser votre inscription. Vérifiez les spams si vous ne le voyez pas d'ici une minute.
Vous êtes inscrit.
Bienvenue — la prochaine édition arrive bientôt dans votre boîte mail.
Vous êtes déjà inscrit — guettez-la chaque mercredi.