Pourquoi mes sessions OpenClaw ont brûlé 21,5 millions de jetons en une journée (et ce qui l’a réellement résolu)
Auteur original : MOSHIII
Peggy, BlockBeats
Note de la rédaction : À l’ère où les applications Agent se répandent rapidement, de nombreuses équipes constatent un phénomène apparemment paradoxal : le système fonctionne normalement, mais le coût des tokens augmente continuellement, souvent sans être remarqué. En analysant une charge de travail réelle d’OpenClaw, nous avons découvert que la cause de cette explosion de coûts ne provient pas souvent des entrées utilisateur ou des sorties du modèle, mais du répétition négligée du cache de contexte (cached prefix replay). Le modèle lit à chaque appel les vastes historiques de contexte, générant ainsi une consommation massive de tokens.
L'article, en s'appuyant sur des données de session spécifiques, montre comment les grandes sorties intermédiaires — telles que les résultats de l'outil, des captures d'écran du navigateur et des journaux JSON — sont continuellement écrites dans le contexte historique et répétitivement lues dans la boucle de l'agent.
À travers ce cas, l'auteur présente une approche d'optimisation claire : depuis la conception de la structure du contexte, la gestion des sorties des outils jusqu'à la configuration du mécanisme de compaction. Pour les développeurs en train de construire un système Agent, cela ne se limite pas à un simple dossier de dépannage technique, mais constitue également un guide concret pour réduire les coûts.
Voici le texte original :
J'ai analysé une charge de travail réelle d'OpenClaw et j'ai repéré un modèle que je pense que de nombreux utilisateurs d'Agent reconnaîtront :
La consommation de jetons semble très « active »
La réponse semble également normale
Mais la consommation de jetons a soudainement explosé
Voici la décomposition structurelle, la cause fondamentale et le chemin de correction praticable pour cette analyse.
TL;DR
Le principal facteur de coût n'est pas la longueur des messages des utilisateurs, mais la répétition répétée d'un grand nombre de préfixes mis en cache.
Selon les données de session :
Total des tokens : 21 543 714
cacheRead : 17 105 970 (79,40 %)
4 345 264 (20,17 %)
résultat : 92 480 (0,43 %)
Autrement dit : le coût de la plupart des appels ne provient pas du traitement de nouvelles intentions utilisateur, mais de la lecture répétée d’un contexte historique très volumineux.
Le moment où vous dites : « Attendez, comment est-ce possible ? »
Je pensais initialement que la forte utilisation de jetons provenait de : des prompts utilisateurs très longs, une grande quantité de génération de sortie, ou des appels d'outils coûteux.
Mais le modèle véritablement dominant est :
Des centaines à des milliers de tokens
cacheRead : chaque appel utilise entre 170 000 et 180 000 tokens
Autrement dit, le modèle lit à chaque tour le même très long préfixe stable.
Plage de données
J'ai analysé les données sur deux niveaux :
1. Journaux d'exécution (runtime logs)
2. Transcriptions de session
Il faut noter que :
Les journaux d'exécution sont principalement utilisés pour observer les signaux de comportement (tels que les redémarrages, les erreurs, les problèmes de configuration)
Les statistiques précises des tokens proviennent du champ usage du fichier JSONL de la session.
Script utilisé :
scripts/session_token_breakdown.py
scripts/session_duplicate_waste_analysis.py
Fichier d'analyse généré :
tmp/session_token_stats_v2.txt
tmp/session_token_stats_v2.json
tmp/session_duplicate_waste.txt
tmp/session_duplicate_waste.json
tmp/session_duplicate_waste.png
Où les jetons sont-ils réellement consommés ?
1) Session concentrée
Une session consomme bien plus que les autres :
570587c3-dc42-47e4-9dd4-985c2a50af86 : 19 204 645 jetons
Ensuite, une chute nette et soudaine :
ef42abbb-d8a1-48d8-9924-2f869dea6d4a : 1 505 038
ea880b13-f97f-4d45-ba8c-a236cf6f2bb5 : 649 584
2) Regroupement des comportements
Les jetons proviennent principalement de :
toolUse : 16 372 294
arrêter : 5 171 420
Le problème provient principalement de la boucle d'appel d'outils, et non d'une conversation ordinaire.
3) Concentration temporelle
Les pics de token ne sont pas aléatoires, mais se concentrent sur plusieurs périodes horaires :
2026-03-08 16:00 : 4 105 105
2026-03-08 09:00 : 4 036 070
2026-03-08 07:00 : 2 793 648
Qu'y a-t-il exactement dans ce très grand préfixe de cache ?
Ce n'est pas le contenu de la conversation, mais principalement les grands intermédiaires :
Gros bloc de données toolResult
Longues traces de raisonnement / réflexion
Gros instantané JSON
Liste des fichiers
Récupération de données par le navigateur
Historique des conversations de l'agent secondaire
Dans la session maximale, le nombre de caractères est d'environ :
366 469 caractères
assistant:thinking:331,494 caractères
assistant:toolCall : 53 039 caractères
Une fois que ces contenus sont conservés dans le contexte historique, chaque appel ultérieur peut les relire via le préfixe cache.
Exemples concrets (issus du fichier de session)
Des blocs de contexte massifs ont été répétés à l'emplacement suivant :
sessions/570587c3-dc42-47e4-9dd4-985c2a50af86.jsonl:70
Journal JSON de la passerelle principale (environ 37 000 caractères)
sessions/570587c3-dc42-47e4-9dd4-985c2a50af86.jsonl:134
Capture d'écran du navigateur + enveloppe sécurisée (environ 29 000 caractères)
sessions/570587c3-dc42-47e4-9dd4-985c2a50af86.jsonl:219
Liste de fichiers énorme (environ 41 000 caractères)
sessions/570587c3-dc42-47e4-9dd4-985c2a50af86.jsonl:311
session/status Capture d'état + structure de prompt volumineuse (environ 30 000 caractères)
« Gaspillage de contenu dupliqué » vs « Charge de relecture en cache »
J'ai également mesuré le pourcentage de contenu répété à l'intérieur d'un seul appel :
Ratio de répétition environ : 1,72 %
Il existe effectivement, mais ce n'est pas le problème principal.
Le véritable problème est que la taille absolue du préfixe de cache est trop grande.
Structure : contexte historique vaste, lecture répétée à chaque appel, ajout uniquement de quelques nouvelles entrées au-dessus
Ainsi, l'accent de l'optimisation ne se situe pas sur la suppression des doublons, mais sur la conception de la structure du contexte.
Pourquoi la boucle Agent est-elle particulièrement sujette à ce problème ?
Trois mécanismes s'accumulent :
1. De nombreux outils de sortie ont été écrits dans le contexte historique
2. Les appels en boucle d'outils génèrent un grand nombre d'appels à courts intervalles.
3. Le préfixe change très peu → le cache est relu à chaque fois
Si la compactation du contexte ne se déclenche pas de manière stable, le problème s'amplifiera rapidement.
Les stratégies de correction les plus importantes (classées par impact)
P0 — Ne remplissez pas le contexte long avec des sorties d'outils massifs
Pour la sortie de l'outil ultra-grand :
- Garder le résumé + chemin/ID de référence
- Écriture du payload original dans le fichier artifact
- Ne conservez pas l'original complet dans l'historique du chat
Priorisez ces catégories :
- Fichier JSON volumineux
- Longue liste de répertoires
- Capture complète du navigateur
- Transcript complet du sous-agent
P1—Vérifiez que le mécanisme de compaction fonctionne réellement
Dans ces données, des problèmes de compatibilité de configuration se produisent à plusieurs reprises : la clé de compaction n'est pas valide
Cela désactivera discrètement le mécanisme d'optimisation.
Bonnes pratiques : n'utilisez que des configurations compatibles avec la version.
Then verify:
openclaw doctor --fix
Vérifiez les journaux de démarrage pour confirmer que la compaction a été acceptée.
P1—Réduire la persistance des textes de raisonnement
Évitez les longs textes de raisonnement qui sont rejoués en boucle
En production : enregistrer un résumé court, et non le raisonnement complet
P3 — Améliorer la conception du cache de prompt
L'objectif n'est pas de maximiser cacheRead. L'objectif est d'utiliser le cache sur des préfixes compacts, stables et de haute valeur.
Suggestion :
- Incorporer les règles de stabilité dans le prompt système
- Ne mettez pas les données instables dans le préfixe stable
- Évitez d'injecter de grandes quantités de données de débogage à chaque round
Plan de stop-loss pratique (si c'était à gérer demain)
1. Identifier la session avec le plus haut pourcentage de cacheRead
2. Exécutez /compact sur la session runaway
3. Ajouter une troncation + une artéfactisation à la sortie de l'outil
4. Relancez le comptage des jetons après chaque modification
Suivez quatre KPI principaux :
cacheRead / totalTokens
toolUse avgTotal/call
Nombre d'appels >= 100k tokens
Pourcentage maximal de session
Signal de succès
Si l'optimisation prend effet, vous devriez voir :
Appels de jetons réduits de plus de 100 000
La part de cacheRead diminue
Poids d'appel de toolUse réduit
La dominance d'une session unique diminue
Si ces indicateurs n'ont pas changé, cela signifie que votre stratégie contextuelle est encore trop laxiste.
Commandes de réplication de l'expérience
python3 scripts/session_token_breakdown.py 'sessions' \
--include-deleted \
--top 20 \
--outlier-threshold 120000 \
--json-out tmp/session_token_stats_v2.json \
> tmp/session_token_stats_v2.txt
python3 scripts/session_duplicate_waste_analysis.py 'sessions' \
--include-deleted \
--top 20 \
--png-out tmp/session_duplicate_waste.png \
--json-out tmp/session_duplicate_waste.json \
> tmp/session_duplicate_waste.txt
Conclusion
Si votre système Agent semble fonctionner normalement, mais que les coûts continuent d'augmenter, vérifiez d'abord ce point : payez-vous de nouvelles inférences, ou reprenez-vous à grande échelle des contextes anciens ?
Dans mon cas, la majorité des coûts proviennent en réalité de la relecture du contexte.
Une fois que tu en prends conscience, la solution devient claire : contrôler strictement les données entrant dans le contexte long.
