La plupart des équipes connaissent leurs dépenses API totales. Presque aucune ne sait quelles étapes d'agent les génèrent. Le coût apparaît comme une ligne mensuelle chez le fournisseur, et il ne se décompose pas en « l'étape de synthèse documentaire du workflow X coûte 14× l'étape de vérification de statut, et elle s'exécute à chaque invocation même si l'utilisateur ne voit jamais le résultat parce qu'une porte en aval a court-circuité le workflow. » La facture que vous ne voyez pas est la facture que vous ne pouvez pas corriger.
La facture que vous ne voyez pas est celle que vous ne pouvez pas corriger.
Ce n'est pas un problème de surveillance. C'est un problème d'architecture. La consommation de tokens n'est pas mesurée au niveau des étapes parce que les étapes ne sont pas des objets de première classe dans la plupart des implémentations d'agents. Les appels se font, les tokens s'accumulent, la facture arrive. La chaîne causale entre « nous avons ajouté une étape de planification » et « nos dépenses API ont augmenté de 40 % » est invisible sans instrumentation délibérée.
L'étape d'agent moyenne dans nos systèmes en production coûte 0,0004 $, un chiffre qui semble dérisoire jusqu'à ce qu'on le multiplie par les invocations à l'échelle. Avec 5 000 workflows actifs par jour, chacun comportant en moyenne 11 étapes, cela représente 22 $ par jour pour les étapes au coût médian. Les étapes aberrantes (les 12 %) coûtent environ 18× la médiane. Quand les étapes aberrantes se concentrent dans les workflows à haute fréquence, elles s'accumulent en silence.
La trace de coût. Ce qu'elle mesure.
L'objet central est un CostTrace : un gestionnaire de contexte qui enveloppe chaque appel au modèle dans votre graphe d'agents, enregistre les comptes de tokens et le niveau de modèle, convertit en montant en dollars selon la grille tarifaire courante, et émet un événement de log structuré. Il ajoute moins de 1 ms de surcoût par appel.
from dataclasses import dataclass, field from contextlib import contextmanager import time, logging # Current rates, update when provider reprices RATES = { "claude-sonnet-4-6": {"input": 3.00, "output": 15.00}, # per 1M tokens "claude-haiku-4-5": {"input": 0.25, "output": 1.25}, } @dataclass class StepCost: step_name: str model: str input_tokens: int output_tokens: int duration_ms: float workflow_id: str @property def dollars(self) -> float: r = RATES[self.model] return ( (self.input_tokens / 1_000_000) * r["input"] + (self.output_tokens / 1_000_000) * r["output"] ) @property def is_outlier(self) -> bool: # Flag steps costing > 5× the p50 for their step_name return self.dollars > OUTLIER_THRESHOLDS.get(self.step_name, 0.005) @contextmanager def cost_trace(step_name: str, model: str, workflow_id: str): t0 = time.perf_counter() usage = {} # filled by the model call yield usage # caller populates from response.usage elapsed = (time.perf_counter() - t0) * 1000 cost = StepCost( step_name=step_name, model=model, workflow_id=workflow_id, input_tokens=usage.get("input_tokens", 0), output_tokens=usage.get("output_tokens", 0), duration_ms=elapsed, ) logging.info("step_cost", extra={ "cost_usd": cost.dollars, "step": step_name, "is_outlier": cost.is_outlier, "input_tokens": cost.input_tokens, "output_tokens": cost.output_tokens, "workflow_id": workflow_id, }) # ── Usage in a LangGraph node ───────────────────────── def summarise_node(state: AgentState) -> AgentState: with cost_trace("summarise", "claude-sonnet-4-6", state["workflow_id"]) as usage: response = client.messages.create(...) usage["input_tokens"] = response.usage.input_tokens usage["output_tokens"] = response.usage.output_tokens return {**state, "summary": extract_text(response.content)}
Trois choses que la trace capture et que la journalisation API standard ne voit pas : le nom de l'étape (pour regrouper par nœud de workflow, pas seulement par modèle), l'identifiant de workflow (pour corréler le coût à la tâche spécifique en cours), et le drapeau d'aberration (pour que vos tableaux de bord n'exigent pas une jointure SQL pour faire remonter les anomalies).
La distribution des dépenses. Elle n'est jamais plate.
Après deux semaines de traçage sur nos workflows d'agents en production, la distribution était exactement ce que nous soupçonnions et pire que ce que nous espérions. Le coût par étape suit quelque chose proche d'une distribution de Pareto : un petit nombre de types d'étapes représente la majorité des dépenses.
Une seule étape (doc_synthesis) représentait 38 % des dépenses API totales. Elle s'exécutait sur 9 % des invocations, ce qui la rendait peu remarquable dans une vue basée sur le volume. C'est seulement en triant par dollars qu'elle est apparue. La cause profonde : elle transmettait l'intégralité du corpus de documents comme contexte à chaque exécution, y compris les exécutions où le résultat de la synthèse n'était jamais présenté à l'utilisateur parce qu'une porte en aval avait court-circuité le workflow.
| Étape | Moy. tokens (entrée) | Moy. tokens (sortie) | Moy. coût/appel | % du volume | % des dépenses |
|---|---|---|---|---|---|
| doc_synthesis | 42 800 | 1 240 | 0,147 $ | ||
| planning | 8 400 | 620 | 0,034 $ | ||
| research | 11 200 | 880 | 0,047 $ | ||
| summarise | 6 100 | 480 | 0,025 $ | ||
| status_check | 420 | 80 | 0,0003 $ |
La ligne status_check est la référence saine : 41 % du volume, 3 % des dépenses, 0,0003 $ par appel. C'est à quoi ressemble une étape bien cadrée. doc_synthesis à 0,147 $ par appel est 490× plus chère, et elle s'exécutait sur 9 % des invocations, dont beaucoup étaient gaspillées.
Ce que nous avons changé. Et ce qu'il en coûtait de ne pas le faire.
avant optimisation
après (60 premiers jours)
régression du recall
doc_synthesis s'exécutait inconditionnellement à chaque invocation. Une vérification classificatrice à 2 tokens avant elle (« ce workflow a-t-il réellement besoin de synthèse documentaire ? ») a éliminé 61 % de ses invocations. Le classificateur coûte 0,00004 $. La porte s'amortit en 4 appels.doc_synthesis correspondaient à l'intégralité du corpus de documents. L'étape n'avait besoin que des 3 meilleurs chunks retrouvés : environ 3 200 tokens. RAG avant la synthèse, pas pendant. Le coût d'entrée a chuté de 92 % sur les invocations restantes. Même qualité de sortie, le harnais d'éval l'a confirmé.classify et status_check tournaient sur Sonnet. Ce sont des tâches à sortie structurée : faible créativité, haute prévisibilité. Les passer sur Haiku a réduit leur coût de 12× sans régression de qualité mesurable. Le harnais d'éval n'a détecté aucune régression sur 500 cas de test.Réduction mensuelle totale : 2 460 $, soit 60 % des dépenses avant optimisation. Aucune de ces optimisations n'a nécessité de réarchitecturer l'agent. Elles ont exigé de mesurer d'abord. La porte, la troncature du contexte, la sélection du niveau de modèle et le cache de prompt n'étaient visibles comme opportunités qu'après que la trace de coût nous ait montré où allait l'argent.
À quoi ressemble la trace de coût en production.
Les événements de log structurés de cost_trace alimentent un tableau de bord simple : une ligne par type d'étape, triée par dépenses totales. Nous le maintenons sur le même écran que le tableau de bord de latence parce que les régressions de coût et de latence arrivent souvent ensemble et ont des causes profondes similaires (taille du contexte, boucles de retry, appels au modèle sans porte).
Le tableau de bord trie par dépenses sur 30 jours, pas par volume. C'est le choix de conception clé : une étape qui s'exécute rarement mais coûte cher doit apparaître en tête, pas être enfouie dans une moyenne. La barre de tokens donne une idée visuelle de l'empreinte de contexte d'un coup d'œil, et l'avertissement d'aberration se déclenche quand le coût d'une étape dépasse 5× son p50 historique.
Nous maintenons une vue supplémentaire : le coût par sortie de workflow complété, pas par étape. Un workflow qui prend 18 étapes pour produire une sortie n'est pas nécessairement plus cher qu'un workflow à 6 étapes, parce que le workflow à 18 étapes peut utiliser des étapes moins chères. Les vues de coût au niveau des étapes et au niveau des sorties racontent des histoires différentes. Vous avez besoin des deux.
Si vous voulez un audit de 30 minutes pour savoir où vont réellement les dépenses API de votre agent, le formulaire de contact est le moyen le plus rapide. Envoyez-nous un exemple de workflow et un export d'utilisation sur 7 jours, vous recevez un graphique de Pareto annoté dans la semaine.