Aller au contenu
Lecture : 0 %

La compaction perd de l'information : laquelle ?

Les six catégories d'information qu'un résumé de conversation laisse tomber, pourquoi ce sont précisément celles dont l'agent a besoin ensuite, et ce qu'il faut écrire hors du contexte pour qu'elles survivent.

Par Elias Varen7 min de lecture

Une session d'agent de code, trois heures de travail. Au début, vous avez écrit : « ne touche pas aux migrations déjà jouées, crée-en une nouvelle ». L'agent a respecté la consigne pendant deux heures. Puis la fenêtre s'est remplie, la conversation a été compactée, et vingt minutes plus tard il modifie une migration existante. Il n'a pas désobéi. La phrase n'existe plus, et le résumé dit seulement « l'utilisateur travaille sur le schéma de facturation ».

La compaction remplace l'historique par un résumé écrit par un modèle. C'est une compression avec perte, et la perte n'est pas aléatoire. Un résumé garde ce qui fait un bon récit (l'objectif, les grandes étapes, l'état d'avancement) et laisse tomber ce qui fait un bon travail. Savoir quoi permet de le sauver avant.

Six choses qu'un résumé de session efface

Je retrouve les mêmes catégories chaque fois que je compare une trace à son résumé.

Les valeurs exactes. Un chemin de fichier, un identifiant de tenant, le texte littéral d'un message d'erreur, un numéro de ligne, le nom précis d'une variable d'environnement. Le résumé écrit « une erreur de contrainte sur la table des factures » là où la trace contenait le nom de la contrainte. L'agent devra relancer la commande pour la retrouver, s'il pense à le faire au lieu de deviner.

Les résultats négatifs. Ce qui a été essayé et n'a pas marché. C'est l'information la plus chère de la session, puisqu'elle a coûté des tours et des tokens, et c'est la première à disparaître, parce qu'un résumé raconte le chemin qui a abouti. Après compaction, l'agent retente l'approche écartée une heure plus tôt, avec le même enthousiasme.

Les contraintes dites une seule fois. Une interdiction, une préférence, un périmètre : « pas de nouvelle dépendance », « les tests d'intégration sont lents, lance seulement ceux du module ». Elles ont été dites tôt, en une phrase, et jamais rappelées depuis puisqu'elles étaient respectées. Leur discrétion même les condamne.

Les raisons. Le résumé garde la décision (« on utilise une table d'outbox ») et perd le pourquoi (« parce que le worker de mails peut tomber entre le commit et l'envoi »). Sans la raison, l'agent ne sait pas si la décision s'applique au cas voisin, et il la défait à la première friction.

Le degré de certitude. Dans la trace, on lit « le problème vient peut-être du cache, à vérifier ». Dans le résumé, « le problème vient du cache ». Une hypothèse est devenue un fait, et la suite de la session se construit dessus.

Le détail des sorties d'outils. Le fichier lu, le résultat de la requête, le diff. Le résumé en garde une paraphrase, alors que l'agent raisonnait sur le texte lui-même ; pour modifier un fichier, il doit donc le relire.

Un résumeur écrit pour le lecteur, l'agent a besoin d'un exécutant

Le mécanisme tient à ce qu'on demande au modèle, à savoir produire un texte court qui rende compte d'un texte long. La cohérence narrative domine. Un détail qui ne sert pas l'histoire (un essai infructueux, une réserve, un littéral) est du bruit pour un résumeur et du signal pour un exécutant.

Il y a une seconde raison, plus embarrassante. Au moment de résumer, personne ne sait ce qui servira ensuite. Le nom de la contrainte SQL est inutile si le problème est réglé, décisif s'il revient. Le résumeur arbitre sans connaître la suite ; il a donc tort régulièrement, et vous ne le voyez pas, parce que le résumé se lit bien.

D'où le danger principal : la compaction ne produit aucune erreur visible. Pas d'exception, pas de test rouge. L'agent continue avec aplomb sur un état du monde légèrement faux, et les symptômes arrivent à retardement. Il relit des fichiers qu'il avait déjà lus, il refait ce qui avait échoué, il enfreint une règle qu'il suivait.

Le fichier d'état, et ce qui doit vivre hors du contexte

Un meilleur résumé ne règle pas grand-chose. Mieux vaut ne pas confier au résumé ce qui ne doit pas se perdre, et l'écrire dans un endroit que la compaction ne touche pas, en l'occurrence un fichier.

Je fais tenir à l'agent un fichier d'état, relu après chaque compaction, avec des rubriques qui correspondent une à une aux pertes décrites plus haut.

markdown
# État de la tâche

## Objectif
Ajouter l'émission d'avoirs partiels au module de facturation.

## Contraintes (ne pas enfreindre)
- Ne jamais modifier une migration existante ; en créer une nouvelle.
- Aucune nouvelle dépendance Composer.

## Décisions et raisons
- Avoir = nouvel événement, pas une facture négative : la numérotation
  des factures doit rester continue.

## Essayé, écarté
- Recalcul de la TVA dans la projection : arrondis divergents entre
  l'écriture et la lecture. Le calcul reste dans l'aggregate.

## Hypothèses non vérifiées
- Le test instable viendrait de l'ordre des fixtures (pas confirmé).

## Repères exacts
- Contrainte en cause : invoice_line_amount_check
- Commande de test : make test-integration FILTER=Billing

D'autres leviers complètent le fichier, du plus rentable au moins rentable.

Vider avant de résumer. Une grande part du contexte d'un agent est faite de sorties d'outils anciennes, comme un fichier lu quarante tours plus tôt et modifié depuis, ou un listing de répertoire. Les retirer en laissant la trace de l'appel, sans son résultat, libère de la place sans rien réécrire. Rien n'est paraphrasé, donc rien n'est déformé ; si l'agent en a besoin, il relit. Je préfère toujours cette opération à un résumé.

Donner des consignes au résumeur. Si votre outillage permet d'orienter la compaction, demandez explicitement ce qu'il oublie d'habitude : les contraintes de l'utilisateur mot pour mot, les approches écartées avec leur raison, les identifiants exacts, les hypothèses marquées comme telles. Le résumé sera plus long, c'est le prix.

Compacter au bon moment. Une compaction qui se déclenche au milieu d'un debug coupe le fil au pire endroit. Il vaut mieux la déclencher soi-même à une frontière naturelle (une étape finie, les tests verts, un commit), quand l'état à transmettre est simple.

Ce que coûtent ces parades, et les sessions qu'on ne compacte pas

Rien de tout cela n'est gratuit. Le fichier d'état consomme des tours d'écriture et de relecture, et il se périme ; un agent qui oublie de le mettre à jour relit après compaction un état faux auquel il fait pleinement confiance, ce qui est pire que pas d'état du tout. Les consignes au résumeur allongent le résumé et réduisent d'autant la place gagnée. Vider les sorties d'outils modifie le milieu de la conversation et invalide le cache de prompt à partir de ce point, si bien que vous repayez une lecture complète au tour suivant.

Dans certains cas, il ne faut pas compacter du tout.

Quand la tâche est finie et qu'une autre commence, une session neuve s'impose. Traîner le résumé d'un travail terminé dans un travail sans rapport revient à payer pour du bruit.

Quand la tâche se découpe, mieux vaut déléguer que compacter. Un sous-agent explore dans son propre contexte et rend vingt lignes ; le contexte principal n'a jamais contenu les quarante fichiers lus, il n'y a donc rien à résumer. La perte existe aussi, puisque le sous-agent résume à son tour, mais elle porte sur une question bornée que vous avez formulée et non sur toute votre session.

Quand la session est un debug serré où chaque détail compte, un passage de relais écrit fait mieux. Vous demandez à l'agent de rédiger la note qu'il laisserait à un collègue, vous la relisez, vous la corrigez, et vous repartez de zéro avec elle. C'est ce que la compaction fait à l'aveugle, fait à la main avec une relecture humaine au milieu.

Ce que je vérifie avant de laisser compacter

  • Les contraintes que j'ai données sont-elles écrites quelque part hors de la conversation, mot pour mot ?
  • Les approches écartées sont-elles notées avec leur raison ?
  • Les valeurs exactes dont la suite dépend (chemins, identifiants, commandes) sont-elles dans le fichier d'état ?
  • Les hypothèses sont-elles marquées comme hypothèses ?
  • Suis-je à une frontière d'étape, ou au milieu d'un raisonnement ?
  • Une session neuve avec une note de relais ferait-elle mieux ?

Si la réponse n'est oui qu'aux deux dernières questions, je ne compacte pas et je repars proprement. Après chaque compaction, l'agent relit le fichier d'état avant toute action, parce que c'est la seule mémoire de la session que personne n'a résumée.

La compaction perd de l'information : laquelle ? · Deepstack