Comment Code Buddy gère 200K tokens sans perdre la mémoire
Il est 16h. Tu travailles avec un agent IA depuis ce matin sur un refactoring massif. L'agent a lu 47 fichiers, exécuté 112 commandes, analysé 23 résultats de tests. Ton historique de conversation fait 180 000 tokens. Il reste 20 000 tokens de fenêtre — et l'agent commence à oublier des décisions prises ce matin.
Tu as deux options : relancer une session fraîche (et perdre tout le contexte de la journée) ou continuer avec un agent qui hallucine. Les deux sont mauvaises.
Code Buddy propose une troisième option : un Context Engine à 7 hooks qui orchestre 6 stratégies de compression et 9 types de mémoire. Le résultat ? Des sessions de plusieurs heures sur des codebases de millions de lignes, sans dégradation.
Voici comment ça fonctionne sous le capot.
Le problème universel : la fenêtre qui se remplit
Tous les agents IA souffrent du même problème fondamental. La fenêtre de contexte est finie. Chaque fichier lu, chaque commande exécutée, chaque message échangé consomme des tokens. Et quand la fenêtre est pleine, il faut choisir quoi garder et quoi jeter.
Les solutions classiques sont toutes insatisfaisantes :
- •Résumer — on perd des détails critiques (quel était le message d'erreur exact ? quelle ligne posait problème ?)
- •Tronquer — on supprime l'historique le plus ancien, qui contient souvent les décisions architecturales fondamentales
- •Ignorer — on espère que le modèle se débrouille, et il finit par halluciner
Le problème est d'autant plus aigu que les agents de code sont gourmands. Un simple cat fichier.ts sur un fichier de 500 lignes consomme ~2 000 tokens. Un résultat de npm test avec 40 tests peut facilement faire 5 000 tokens. En une heure de travail intensif, un agent consomme facilement 100 000 tokens de résultats d'outils — la moitié de sa fenêtre.
Les 7 hooks du cycle de vie
Le cœur du Context Engine est une interface TypeScript à 7 hooks. Chaque hook correspond à un moment précis dans le cycle requête-réponse de l'agent :
Hook 1 : `bootstrap()` — l'initialisation
Au démarrage de la session, le système charge les instructions projet (CLAUDE.md, AGENTS.md), récupère les mémoires persistantes de la base SQLite, configure les budgets token par catégorie, et initialise les indices de recherche sémantique.
Le point clé ici, c'est le budget token :
this.budget = TokenBudget.forModel(config.model, {
system: 0.08, // 8% pour le prompt système
instructions: 0.03, // 3% pour les instructions projet
code: 0.18, // 18% pour le code source
tools: 0.13, // 13% pour les résultats d'outils
conversation: 0.53, // 53% pour la conversation
memory: 0.04, // 4% pour la mémoire persistante
margin: 0.01, // 1% de marge de sécurité
});Chaque catégorie a un budget fixe. Quand une catégorie déborde, elle déclenche la compression — pas la suppression.
Hook 2 : `ingest()` — le tri à l'entrée
Chaque message entrant passe par trois opérations : classification (type, importance, catégorie), scoring d'importance (0.0 à 1.0), et transformation optionnelle. Un résultat d'outil volumineux peut être immédiatement compressé de façon réversible avant même d'entrer dans le contexte.
Hook 3 : `assemble()` — la construction du prompt
L'opération la plus critique. Le système construit le prompt final en respectant un ordre de priorité strict : prompt système (toujours inclus intégralement), instructions projet, mémoire persistante, messages à haute importance (score > 0.8), puis les messages moyens et faibles en fonction du budget restant.
Hook 4 : `compact()` — la compression
Quand on approche les limites, compact() déclenche les stratégies de compression selon le niveau d'utilisation : stratégie légère à 60 %, agressive à 85 %, urgente à 95 %.
Hook 5 : `afterTurn()` — l'extraction de connaissances
Après chaque tour de conversation, le système extrait les faits, met à jour les indices de mémoire, et applique le decay temporel. C'est ici que l'agent « apprend » de chaque interaction.
Hook 6 et 7 : les sous-agents
prepareSubagentSpawn() sélectionne un sous-ensemble pertinent du contexte pour un agent enfant. onSubagentEnded() fusionne les résultats quand il revient. C'est ce qui permet la parallélisation des tâches sans exploser la mémoire.
Les 6 stratégies de compression
C'est là que ça devient vraiment intéressant. Le Context Engine ne se contente pas de « résumer » — il utilise 6 stratégies spécialisées, chacune inspirée de la recherche récente.
1. Importance-weighted scoring
Chaque message reçoit un score basé sur son type :
| Type de message | Score d'importance |
|---|---|
| System prompt | 1.00 |
| Error/exception | 0.95 |
| Code generation | 0.70 |
| Tool result (fichier lu) | 0.50 |
| Conversation courante | 0.25 |
| Acknowledgment (« ok », « compris ») | 0.05 |
2. Observation masking (inspiré JetBrains)
L'idée : masquer les outputs d'outils qui ne sont plus pertinents. Si tu as lu un fichier il y a 50 tours et que tu ne l'as plus référencé depuis, son contenu est remplacé par un placeholder : [output masqué — 2 340 tokens — restaurable]. Résultat mesuré par JetBrains : -7 % de coût en tokens, +2,6 % de résolution de tâches. Moins de bruit = meilleure qualité.
3. Restorable compression (inspiré Manus AI)
C'est la stratégie la plus élégante. Au lieu de supprimer un message, on le remplace par un résumé court + un identifiant. Si l'agent a besoin du contenu original plus tard, il peut appeler restore_context(id) pour le récupérer. Compression réversible.
// Avant : 2 340 tokens
"Le fichier auth.service.ts contient 187 lignes avec
les fonctions login(), register(), validateToken()..."
// Après : 45 tokens
"[résumé: auth.service.ts — 3 fonctions auth — id:ctx_a7f3]"4. JIT context discovery (inspiré Gemini CLI)
Les instructions projet ne sont pas chargées en bloc au démarrage. Elles sont découvertes dynamiquement quand l'agent explore le filesystem. Si l'agent entre dans /src/auth/, le système cherche un .context.md dans ce répertoire et l'injecte. Résultat : les instructions pertinentes sont toujours présentes, les autres ne consomment jamais de tokens.
5. Partial summarization
Résumé sélectif des parties les moins critiques. Pas un résumé global de toute la conversation — un résumé ciblé des zones à faible importance, préservant intégralement les zones à haute importance.
6. Proactive compaction
Avant même de compresser, le système flush les faits et patterns extraits vers la mémoire persistante (SQLite). Comme ça, même si le message source est compressé, l'information survit dans la base de données et peut être réinjectée dans les prochaines sessions.
Les 9 types de mémoire
Le Context Engine catégorise les souvenirs en 9 types, chacun avec son propre cycle de vie :
| Type | Exemple | Decay |
|---|---|---|
| fact | « Le projet utilise PostgreSQL 15 » | Lent |
| preference | « L'utilisateur préfère les arrow functions » | Très lent |
| pattern | « Les fichiers de test sont en *.spec.ts » | Lent |
| decision | « On a choisi JWT au lieu de sessions » | Aucun |
| context | « On travaille sur le module auth » | Rapide |
| summary | « Résumé de la session de refactoring » | Moyen |
| instruction | « Toujours utiliser ESLint avant de commiter » | Aucun |
| error | « Le bug #42 était un off-by-one dans la pagination » | Moyen |
| definition | « UserDTO = { id, email, name, role } » | Lent |
Le decay temporel est crucial : les faits contextuels (« on travaille sur auth ») perdent leur pertinence rapidement, tandis que les décisions architecturales ne décayent jamais. Un système de mémoire sans decay finit par noyer les informations récentes sous les anciennes.
Pour aller plus loin
Le Context Engine de Code Buddy est détaillé dans le chapitre 12 de « La Mémoire des Machines » — avec le code TypeScript complet de chaque hook, les benchmarks de compression, et les leçons apprises en production.
Si tu veux comprendre le pattern qui complète le Context Engine — le Ralph Loop, qui élimine la dégradation en relançant l'agent avec un contexte frais à chaque tâche — j'ai un livre dédié.
Soutenez mon travail sur Patreon
Accès anticipé aux articles, contenu exclusif, et la satisfaction de soutenir un auteur indépendant.
Rejoindre — à partir de 3€/mois