Un POC IA qui tourne bien explose en facture deux semaines après la mise en prod. Pas parce qu'il est mal codé — parce que personne n'a regardé les coûts API. C'est la conversation qu'on a eue trois fois en six mois avec des CFOs qui découvraient une facture Anthropic à 8 200 € le mois sans alerte préalable.
Les Spend Limits ne sont pas une option de confort. C'est la seule chose qui empêche une boucle agentique non bornée de consommer le budget de l'année en 72 heures. On la configure avant la première API call de prod. Pas après.
Le problème, en chiffres
Sur un audit synthèse de douze projets IA livrés en 2025-2026 — les nôtres, plus des audits chez des confrères — 87 % avaient dépassé leur budget mensuel prévu au moins une fois en six premiers mois. Causes principales :
- Boucle agentique mal bornée (retry infini, contexte qui grossit)
- Trafic réel 3-5× plus élevé que l'estimation POC
- Pic événementiel (newsletter, presse, viralité) non absorbé
- Bug de prompt qui multiplie les tokens par 4 sans rien dire
Aucun de ces cas n'est exotique. Tous sont arrivés à des équipes sérieuses.
Ce qu'Anthropic offre
Depuis fin 2024, la console Anthropic propose des Spend Limits à deux
granularités. C'est dans Settings → Usage → Spend Limits.
Au niveau organisation. Un plafond mensuel global. Notifications email
automatiques à 50 %, 75 %, 90 % du seuil. À 100 %, l'API
renvoie un code d'erreur (402 BILLING côté Anthropic, traité comme
429 RATE_LIMITED côté SDK selon les versions) — c'est à toi de gérer le
fallback côté code.
Au niveau API key. Un plafond par clé. On recommande une clé par feature en production. Granularité qui change tout : si le RAG support explose, le système de classification de tickets continue à tourner.
Le pattern Opcodia
Sur chaque projet client, on pose la même architecture :
| Feature | API key | Spend Limit / mois |
|---|---|---|
| Classification | key-classify-tickets | 80 € |
| RAG support | key-rag-support | 250 € |
| Agent email | key-agent-email | 400 € |
| Réserve / debug | key-debug | 50 € |
Les seuils sont calés sur le budget mensuel négocié avec le client, avec 20 % de marge. Si une feature pousse vers son plafond, on a un signal avant le mur, pas après.
Côté observabilité, chaque clé est mappée à un dashboard Langfuse qui affiche le coût par feature en temps réel — déjà ventilé par modèle. Les alertes Slack se déclenchent à 75 % du plafond mensuel, pas à 100 %.
Code défensif côté serveur
Le hard cutoff Anthropic est utile, mais brutal — l'API arrête de répondre.
Côté code, on traite le 429 RATE_LIMITED et le 402 BILLING comme des
événements normaux, avec fallback gracieux.
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY })
export async function classifyTicket(text: string) {
try {
const response = await client.messages.create({
model: 'claude-haiku-4-5',
max_tokens: 256,
messages: [{ role: 'user', content: text }],
})
return { ok: true, result: response.content[0] }
} catch (err) {
if (err instanceof Anthropic.APIError) {
// Spend Limit hit ou rate limit organisation
if (err.status === 429 || err.status === 402) {
await notifySlack({
channel: '#ops-ia',
level: 'critical',
text: `Spend Limit hit (status ${err.status}). Feature classify dégradée.`,
})
// Fallback : enqueue pour retry quand le quota se reset
await queue.enqueue('ticket-classify', { text, retryAt: nextMonth() })
return { ok: false, reason: 'spend_limit', degraded: true }
}
// 5xx : retry exponentiel classique
if (err.status >= 500) {
return { ok: false, reason: 'upstream', degraded: true }
}
}
throw err
}
}
Trois principes dans ce snippet :
- On ne casse pas la requête utilisateur. On dégrade.
- On alerte une fois — pas un Slack par requête (saturation garantie).
- On enqueue la donnée pour traitement différé quand le quota se reset.
Pricing référence — mai 2026
Pour calibrer les Spend Limits, il faut connaître les coûts unitaires. État des prix Anthropic publiés à la date de cet article :
| Modèle | Input ($ / M tokens) | Output ($ / M tokens) |
|---|---|---|
| Claude Opus 4.7 | 5,00 | 25,00 |
| Claude Sonnet 4.6 | 3,00 | 15,00 |
| Claude Haiku 4.5 | 1,00 | 5,00 |
Un agent qui fait 50 000 appels Sonnet par mois avec 4 000 tokens input
moyens et 800 tokens output moyens : 50 000 × (4 × 3 + 0,8 × 15) / 1 000
= 1 200 $/mois. Un Spend Limit à 1 500 $ couvre la cible + 25 % de
marge. Si tu pars sur Opus pour la même charge, c'est 3 200 $/mois —
même architecture, 2,7× plus cher.
Les optimisations qu'on applique
Une fois les Spend Limits posés, on attaque la réduction du coût unitaire. Quatre leviers, par ordre d'impact :
1. Prompt caching
Anthropic facture les tokens en cache à 10 % du coût input normal. Sur un agent avec un system prompt de 3 500 tokens (instructions + few-shot examples), activer le cache divise par ~9 le coût de cette partie du prompt sur les requêtes suivantes.
await client.messages.create({
model: 'claude-sonnet-4-6',
system: [
{
type: 'text',
text: longSystemPrompt, // 3 500 tokens
cache_control: { type: 'ephemeral' },
},
],
max_tokens: 1024,
messages: [{ role: 'user', content: userQuery }],
})
Le cache vit 5 minutes (TTL ephemeral). Pour un agent qui reçoit 100+ requêtes par minute, c'est gratuit. Pour un agent à 1 requête par heure, le cache n'a pas le temps de s'amortir — on n'active pas dans ce cas.
2. Tier downgrade automatique
On essaie d'abord Haiku. Si un eval automatique détecte une réponse défaillante (heuristique côté code ou jugement Claude-as-judge), on retry sur Sonnet. Pour 1-2 % des requêtes seulement, on monte à Opus.
Résultat sur un agent de classification : 78 % des requêtes finissent en Haiku, 20 % en Sonnet, 2 % en Opus. Coût moyen pondéré ≈ 4× moins cher qu'un setup "tout Sonnet" — avec la même accuracy mesurée.
3. Batch API
Pour les workloads non-temps-réel (export nightly, scoring batch, re-classification historique), l'API Batch Anthropic offre -50 % sur le tarif standard. Latence garantie 24 h, ce qui est largement acceptable pour un cron quotidien.
4. Truncation des contextes longs
Pour un agent conversationnel, le contexte grossit linéairement avec la conversation. À 50 messages, on a un prompt de 30 000+ tokens — facture qui dérape vite. On applique une sliding window : on garde les 8 derniers messages + un résumé condensé des plus anciens (généré par Haiku, ~200 tokens).
Ce qu'on a appris
Trois choses qui ne sont écrites nulle part dans la doc Anthropic mais qu'on a payées cash sur des projets :
- Les Spend Limits ne préviennent pas un bug. Si une boucle infinie consomme 90 % du quota mensuel en 2 heures, la limite te coupera — mais le bug aura quand même brûlé 90 % du budget. Pose des limites par heure côté ton code (rate-limit applicatif) en plus des Spend Limits Anthropic.
- L'erreur 402 n'a pas exactement le même format selon les SDK. En
TypeScript v0.30+, c'est
APIError.status = 402. En Python v0.40+, c'est parfois remonté commeBadRequestErroravec un champtype: 'billing'. Tester en condition réelle (bumper artificiellement la limite à 0,01 $). - Les alertes email Anthropic arrivent avec 5-30 minutes de retard. C'est suffisant pour la plupart des cas, mais pas pour un incident critique. Branche un webhook côté ton observabilité (Langfuse, Helicone, custom) qui calcule la consommation en temps réel.
Ce qu'on fait sur les projets
Sur chaque projet IA Opcodia, on configure les Spend Limits avant la première API call de prod. Non négociable. Ça prend 15 minutes :
- Une API key par feature, avec un Spend Limit individuel
- Un Spend Limit global à l'organisation (somme + 10 %)
- Un dashboard Langfuse synchronisé avec ces clés
- Un alerting Slack à 75 % du plafond mensuel
- Du code défensif sur
429/402avec fallback gracieux
Si vous voulez voir comment ça s'intègre concrètement, le repo
opcodia/ai-evals montre le pattern complet — Spend Limits + Langfuse +
fallback + sliding window. Mehdi maintient l'exemple TypeScript à jour à
chaque update SDK Anthropic.
