SSD Nodes Learn
Guides Matt ConnorPar Matt Connor

Contrôler le coût d'un agent IA sur un VPS

Évitez les factures excessives d'un agent unattended. Apprenez à utiliser le prompt caching, le batching et des budgets par tâche pour limiter les tokens.

Comment éviter qu'un agent IA toujours actif ne fasse exploser la facture

Le contrôle des coûts d'un agent IA sur un VPS (virtual private server) repose sur les plafonds que vous définissez avant le lancement de l'agent, car personne ne surveille la consommation en temps réel. Limitez chaque réponse avec max_tokens, restreignez le nombre d'itérations de la boucle dans votre code, mettez en cache la partie statique du prompt et enregistrez les statistiques d'utilisation de chaque réponse pour identifier les tâches coûteuses. Le coût de location du serveur est un prix mensuel fixe. L'API du modèle est facturée au token, et une boucle autonome consomme les tokens très rapidement sans surveillance.

Ce guide suppose que l'agent existe déjà et appelle l'API Messages depuis un serveur vous appartenant. Construire un agent IA avec Claude sur un VPS présente le fonctionnement technique.

Pourquoi un agent unattended présente une structure de coûts différente

Une session interactive implique un humain. Si le modèle fait une erreur ou lit un log de 40 000 lignes, l'utilisateur l'arrête. Un agent unattended n'a pas de frein : il s'exécute jusqu'à la fin de la boucle, puis un timer le relance.

La fréquence est le multiplicateur souvent oublié. Une tâche planifiée toutes les cinq minutes s'exécute 288 fois par jour, soit environ 8 640 fois par mois. Le coût total est le coût d'une exécution multiplié par ce nombre. De nombreux agents "always-on" n'ont pas besoin d'être actifs en permanence. Ils doivent simplement répondre dans un délai de quelques minutes, ce qui constitue un planning.

Un agent génère aussi des coûts que ne génère pas une fenêtre de chat.

  • Les tool definitions sont incluses dans chaque requête. Le system prompt pour l'utilisation d'outils coûte 290 tokens sur Claude Opus 4.8 avec tool_choice de auto ou none, et 410 avec any ou tool. L'outil bash ajoute 325 tokens supplémentaires. Chaque serveur MCP attaché ajoute ses schémas à ce poids (MCP signifie Model Context Protocol).
  • Les résultats des outils sont des input tokens. Une commande qui affiche 8 000 lignes insère ces 8 000 lignes dans la requête suivante, et dans toutes les requêtes suivantes de ce tour de conversation.
  • Les pages récupérées sont des input tokens. Une page web moyenne de 10 kB représente environ 2 500 tokens, et un PDF de recherche de 500 kB environ 125 000. max_content_tokens tronque uniquement les fichiers texte, car cela "s'applique au contenu textuel, pas au contenu binaire comme les PDF". Utilisez plutôt max_uses et allowed_domains pour les PDF.
  • La recherche web est facturée par recherche, au tarif de 10 $ pour 1 000 recherches, quel que soit le nombre de résultats obtenus. Une recherche qui échoue n'est pas facturée.

Chacun de ces éléments n'est pas coûteux en une seule instance. L'ensemble devient coûteux lorsqu'il est exécuté 8 640 fois.

Les hard ceilings et les soft ceilings résolvent des problèmes différents

max_tokens est appliqué. Il s'agit d'une limite stricte sur la sortie totale d'une requête, incluant le texte de réflexion et la réponse. Claude ne génère jamais au-delà de cette limite, et le modèle ne peut pas voir ce nombre. Atteindre cette limite provoque une stop_reason: "max_tokens" et une réponse tronquée. La contrainte pour les agents : chaque requête dans une boucle de tool-use possède son propre max_tokens, ce qui limite une seule réponse et non la tâche entière. Dix appels de tool à 4 000 tokens représentent un plafond de 40 000 tokens pour le tour.

Un budget de tâche est consultatif. task_budget se trouve à l'intérieur de output_config et indique au modèle le nombre de tokens disponibles pour l'ensemble de la boucle agentique, en comptant la réflexion, les tool calls, les résultats des outils et la sortie.

resp = client.beta.messages.create(
    model="claude-opus-4-8",
    max_tokens=4096,
    betas=["task-budgets-2026-03-13"],
    output_config={"task_budget": {"type": "tokens", "total": 64000}},
    messages=messages,
)

"Les budgets de tâche sont une indication souple, pas une limite stricte." Claude peut dépasser cette limite en cours d'action, et la limite appliquée sur la sortie reste max_tokens. "Le compte à rebours est visible uniquement par le modèle", et les réponses ne contiennent aucun champ de budget restant. Le task_budget.total minimum accepté est de 20 000 tokens ; une valeur inférieure renvoie une erreur 400. Un budget trop petit pour la charge de travail produit un comportement de refus : le modèle réduit alors l'ampleur de la tâche ou s'arrête prématurément.

Un détail entraîne un coût au lieu d'une économie. Si votre client décrémente task_budget.remaining à chaque requête de suivi, la valeur modifiée invalide tout préfixe mis en cache qui la contient. Définissez-la une seule fois, lors de la première requête.

Les budgets de tâche sont en bêta sur Claude Fable 5, Claude Opus 4.8 et Claude Opus 4.7. Claude Sonnet 5 et Claude Haiku 4.5 sont listés comme Not supported, et les budgets de tâche ne s'appliquent pas à Claude Code ; une session Claude Code détachée dans tmux dépend donc de l'hygiène de la session.

Le troisième plafond se trouve dans la Claude Console : attribuez à l'agent son propre workspace, puis définissez une limite de dépenses mensuelle et des limites de taux par minute. "Vous ne pouvez pas définir de limites sur le Default Workspace", et "Les limites au niveau de l'organisation s'appliquent toujours, même si la somme des limites des workspaces est supérieure". Ajoutez des notifications de dépenses pour être alerté par un seuil avant d'atteindre le plafond.

Choix du modèle par tâche, et impact réel de l'effort

Le choix du modèle se décide pour chaque tâche. En juillet 2026, le coût par million de tokens (input puis output) est le suivant : Claude Fable 5 à 10 $ et 50 $, Claude Opus 4.8 et Opus 4.7 à 5 $ et 25 $, Claude Sonnet 5 à 3 $ et 15 $, Claude Haiku 4.5 à 1 $ et 5 $. Le prix de Sonnet 5 est actuellement inférieur au tarif affiché, car « un tarif de lancement de 2 $/10 $ par million de tokens d'input/output est en vigueur jusqu'au 31 août 2026 ». Une étape qui sert uniquement à classifier des lignes de logs n'a pas besoin d'Opus.

L'effort est le second levier. output_config.effort accepte low, medium, high, xhigh et max. La valeur par défaut est high ; configurer explicitement high revient donc au même que de l'omettre. Réduire l'effort impacte plus que la longueur du raisonnement : la documentation indique que cela réduit le nombre de tool calls et combine les opérations en une seule. Pour un agent, l'économie est plus importante, car un tool call évité est une requête entière qui n'est jamais envoyée.

Le piège est que l'effort entre en conflit avec le cache. Modifier la valeur entre deux requêtes invalide le prompt caching. Dans l'exemple documenté, la requête 2 a rapporté cache_read_input_tokens: 3546 ; la requête 3, avec un changement d'effort de high à medium, a rapporté cache_creation_input_tokens de 3546 et cache_read_input_tokens de 0. Variez l'effort selon les workloads, mais jamais à l'intérieur d'une même conversation mise en cache. Pour contrôler la profondeur sans briser le cache, faites-le dans le prompt : une instruction comme « Répondez directement sans délibérer » dans le dernier message utilisateur laisse les breakpoints précédents intacts.

Les tokens de réflexion sont facturés au tarif de l'output et comptabilisés dans max_tokens. C'est pourquoi une réponse tronquée signifie souvent que la réflexion a consommé le budget. Consultez usage.output_tokens_details.thinking_tokens pour connaître le chiffre exact. Ce qui remplit réellement une facture Claude détaille le fonctionnement.

Mettez le préfixe stable en cache et évitez de le corrompre par accident

L'écriture en cache coûte 1,25 fois le prix d'entrée de base pour le cache de cinq minutes, et 2 fois pour le cache d'une heure. La lecture en cache coûte 0,1 fois le prix. Le cache est donc rentable dès la première lecture pour la durée de 5 minutes (écriture à 1,25x), ou après deux lectures pour la durée d'une heure (écriture à 2x).

Une phrase explique pourquoi cela convient à un agent toujours actif : « Le cache est rafraîchi sans coût supplémentaire chaque fois que le contenu mis en cache est utilisé. » Un job s'exécutant toutes les deux minutes sur le cache de cinq minutes maintient son préfixe actif toute la journée pour une seule écriture.

Trois façons de perdre le cache sans s'en rendre compte.

Un préfixe qui change. « Les préfixes de cache sont créés dans l'ordre suivant : tools, system, puis messages. » Tout changement d'octet plus tôt dans cet ordre invalide tout ce qui suit. Modifier les définitions d'outils invalide l'intégralité du cache. L'erreur classique est d'inclure un timestamp ou un run id dans le system prompt : chaque requête possède alors un préfixe différent, effectue une nouvelle écriture à 1,25x et ne récupère aucune lecture. L'indice est un taux de usage.cache_read_input_tokens à 0 pour des appels identiques. Déplacez le texte volatil dans le message utilisateur le plus récent.

Un préfixe trop court. Chaque modèle possède une longueur minimale de mise en cache. En dessous de ce seuil, la requête est traitée sans cache et « aucune erreur n'est renvoyée ». Les valeurs incluent 1 024 tokens pour Claude Opus 4.8 et Claude Sonnet 5, et 4 096 pour Claude Haiku 4.5. Passer un job de Sonnet à Haiku peut désactiver le cache silencieusement.

Une conversation qui dépasse la fenêtre de recherche. « La fenêtre de recherche (lookback window) est de 20 blocs. » Le système vérifie au maximum 20 positions par breakpoint, puis s'arrête. Dans l'exemple documenté, un tour contenant 35 blocs avec un breakpoint sur le bloc 35 vérifie les blocs 35 à 16. L'entrée du tour précédent au bloc 15 est hors de la fenêtre, il n'y a donc pas de hit. Un agent qui ajoute plusieurs blocs de tool-use et tool-result par tour dépasse la limite de 20 en deux ou trois tours. Vous disposez de quatre breakpoints par requête ; consacrez-en un aux messages récents.

Envoyez tout ce qui peut attendre à l'API Batches

"Toute utilisation est facturée à 50 % du prix standard de l'API", pour l'input comme pour l'output. Le traitement par batch est asynchrone. "La plupart des batches se terminent en moins d'une heure". Les résultats sont disponibles quand toutes les requêtes sont finies ou après 24 heures, selon la première échéance atteinte. Ce délai est indicatif et non garanti.

Interrogez processing_status jusqu'à ce qu'il affiche ended. Les requêtes retournant errored, canceled ou expired ne sont pas facturées. Une mise en garde si vous utilisez un spend cap : "les batches peuvent légèrement dépasser la limite de dépenses configurée pour votre Workspace."

Les réductions se cumulent. Comme un batch peut durer plus de cinq minutes, la documentation recommande l'utilisation du cache d'une heure pour les batches partageant le même contexte. Divisez donc votre charge de travail : tout ce qui nécessite une réponse immédiate d'une personne ou d'un webhook doit rester sur le flux live. Un résumé nocturne ou la classification des logs de la veille doit être envoyé dans un batch à moitié prix.

Enregistrez les champs d'usage de chaque réponse dans votre propre stockage

Vous ne pouvez pas attribuer une dépense que vous n'avez jamais enregistrée. Chaque réponse indique son coût.

u = resp.usage
row = {
    "job": job_name,
    "model": resp.model,
    "uncached_input": u.input_tokens,
    "cache_write": u.cache_creation_input_tokens,
    "cache_read": u.cache_read_input_tokens,
    "output": u.output_tokens,
    "stop_reason": resp.stop_reason,
}

Ajoutez une ligne par appel API dans un fichier JSON-lines, avec le nom de votre job en étiquette. Une semaine plus tard, vous pourrez identifier les jobs qui génèrent des coûts et ceux qui sont simplement restés actifs. Surveillez cache_read : une colonne de zéros est le bug de coût le plus fréquent sur un agent auto-hébergé.

Un champ est facile à mal interpréter. input_tokens compte uniquement les tokens après le dernier breakpoint de cache, donc la taille réelle du prompt est total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens. Un agent qui rapporte input_tokens: 400 sur un prompt volumineux n'est pas peu coûteux : le reste provient du cache.

Comptez avant d'envoyer. Le comptage de tokens est gratuit et ses rate limits sont distinctes de la création de messages ; utilisez donc count_tokens pour refuser une pièce jointe trop volumineuse au lieu de payer pour la découvrir. Le résultat est une estimation, donc mesurez à nouveau par modèle et ne réutilisez jamais le compte d'un tokenizer d'un autre fournisseur. Claude Opus 4.7 et les modèles Opus ultérieurs, Claude Fable 5 et Claude Sonnet 5 utilisent un nouveau tokenizer qui « produit environ 30 % de tokens en plus pour le même texte ». Claude Sonnet 4.6 et versions antérieures, dont Claude Haiku 4.5, utilisent le précédent.

Pour une vue faisant autorité, l'Admin API rapporte l'usage à https://api.anthropic.com/v1/organizations/usage_report/messages et le coût à https://api.anthropic.com/v1/organizations/cost_report. Les deux utilisent une clé admin (sk-ant-admin01-...) comme x-api-key: $ANTHROPIC_ADMIN_KEY avec anthropic-version: 2023-06-01, et acceptent bucket_width=1d, group_by[]=model et api_key_ids[]=. Une limitation : « L'Admin API est indisponible pour les comptes individuels. »

Ce dernier paramètre est une astuce d'attribution économique : donnez à chaque job sa propre clé API, filtrez avec api_key_ids[], et divisez le rapport par clé avec group_by[]=api_key_id. Le filtre est au pluriel, la dimension de regroupement est au singulier. Conservez les clés dans l'environnement plutôt que dans le code, comme le fait une première application Claude API sur un VPS.

Limitez la boucle, car rien d'autre ne le fera

Un nombre d'itérations limité est obligatoire ici. La boucle vous appartient, donc le compteur vous appartient :

for step in range(MAX_STEPS):          # MAX_STEPS = 12, never "while True"
    resp = client.messages.create(...)
    if resp.stop_reason != "tool_use":
        break
else:
    log.warning("job %s hit MAX_STEPS=%d, giving up", job_name, MAX_STEPS)

Aucun des plafonds ci-dessus ne le fait pour vous : max_tokens limite une seule réponse, et le modèle reçoit seulement un budget de tâches.

Ajoutez un second frein à l'extérieur du processus. Exécutez la tâche via un timer systemd plutôt que via un processus permanent, et configurez RuntimeMaxSec= sur son unité de service. Avec RuntimeMaxSec=600, une exécution bloquée est tuée après dix minutes au lieu de tourner indéfiniment. Exécuter un programme en tant que service et timer systemd explique la configuration des fichiers d'unité. Consultez les résultats d'une exécution avec journalctl -u triage-agent.service --since "1 hour ago".

Limitez également les tentatives de réessai (retries), car un gestionnaire qui réessaie indéfiniment facture chaque tentative. Une erreur 429 ou 500 mérite quelques essais avec un backoff. Une erreur 400 n'en mérite aucun, car la même requête échouera toujours de la même manière.

Le contrôle des coûts des agents IA commence par l'analyse de vos propres données

Personne ne peut prédire le coût d'un agent toujours actif. Le coût est égal au nombre de tokens par exécution multiplié par le nombre d'exécutions par jour ; ces deux variables vous appartiennent. Effectuez un test, lisez la ligne d'utilisation enregistrée, puis multipliez par votre fréquence d'exécution prévue. Comparez le rapport de coût obtenu deux jours plus tard avec ce calcul. Si les résultats diffèrent, l'écart est presque toujours dû à un cache défectueux ou à une boucle plus longue que prévu.

Ce calcul suppose l'utilisation d'une clé API, car l'agent est votre propre programme appelant l'API Messages. Pour votre usage interactif, quel forfait Claude correspond à votre façon de travailler traite de la partie abonnement. Chaque prix et chaque limite ont été vérifiés par rapport à la documentation d'Anthropic en juillet 2026 ; relisez la page des tarifs avant d'établir un budget.

FAQ

Quel est le coût d'exécution d'un agent IA toujours actif sur un VPS ?

Il y a deux factures et une seule est prévisible. Le serveur a un prix mensuel fixe. L'API du modèle est facturée au token, donc le coût est égal à la consommation d'une exécution multipliée par la fréquence d'exécution. Anthropic ne publie aucun chiffre pour un agent toujours actif auto-hébergé, considérez donc tout chiffre cité comme une estimation. Loggez usage lors d'une exécution réelle et multipliez par votre fréquence d'exécution.

Quelle est la différence entre max_tokens et un budget de tâche (task budget) ?

max_tokens est appliqué et invisible pour le modèle. Cela limite la sortie d'une requête, incluant le thinking, et atteindre cette limite produit stop_reason: "max_tokens". Un budget de tâche est l'opposé : le modèle reçoit le nombre et ajuste sa boucle agentique en fonction de celui-ci, mais « Les budgets de tâches sont une indication souple, pas une limite stricte » et la limite appliquée reste max_tokens.

Pourquoi cache_read_input_tokens est-il toujours à zéro pour mon agent ?

Parce que le préfixe change entre les appels, ou parce qu'il est trop court pour être mis en cache. La cause habituelle est un timestamp ou un run id interpolé dans le system prompt : le cache est indexé sur le préfixe, donc tout changement d'un seul octet invalide tout ce qui suit. Modifier les définitions des outils ou la valeur effort produit le même résultat. Sinon, il s'agit de la taille, car les prompts courts ne sont pas mis en cache et aucune erreur n'est renvoyée.

Comment empêcher un agent IA de boucler indéfiniment ?

Comptez les itérations dans votre code de boucle et arrêtez-vous à un maximum fixe, car max_tokens limite une seule réponse alors qu'un agent en effectue plusieurs. Ajoutez une limite de temps (wall-clock) en dehors du processus : lancez la tâche via un timer systemd avec RuntimeMaxSec= configuré, afin qu'une exécution bloquée soit tuée selon l'horaire prévu. Limitez également les retries, car une boucle de retry facture chaque tentative.

Puis-je définir une limite de dépenses sur une seule clé API Claude ?

La limite de dépenses documentée s'applique par workspace et non par clé ; attribuez donc au agent son propre workspace et plafonnez ses dépenses mensuelles à cet endroit. « Vous ne pouvez pas définir de limites sur le Default Workspace ». Ajoutez des notifications de dépenses pour qu'un seuil vous alerte en premier. Pour l'attribution, attribuez à chaque tâche sa propre clé, puis regroupez le rapport d'utilisation avec group_by[]=api_key_id.

#claude#ai#agents#api#cost