Agents IA
Comment donner une mémoire à long terme à un agent LLM
On donne une mémoire à long terme à un agent LLM en écrivant les éléments durables de son travail dans un stockage externe, puis en les récupérant par pertinence au début de chaque exécution, au lieu de rejouer la transcription.
Le motif, en quatre étapes
On donne une mémoire à long terme à un agent LLM en écrivant les éléments durables de son travail dans un stockage externe, puis en les récupérant par pertinence au début de chaque exécution plutôt qu'en rejouant toute la transcription. Tout le reste est du détail sur ces deux gestes.
En pratique cela se décompose en quatre étapes : choisir ce qui mérite d'être persisté, le typer pour pouvoir l'interroger, le récupérer sous plafond, et gérer la substitution. Chacune a son mode d'échec propre, et en sauter une produit un système qui a l'air d'avoir une mémoire jusqu'à ce qu'on s'en serve pendant un mois.
Étape 1 — choisir ce qui mérite d'être persisté
Les candidats sont les faits que l'agent a établis, les décisions qu'il a prises, les contraintes qu'il a découvertes, et les événements qui ont changé l'état du travail. Les non-candidats sont les tours de dialogue au cours desquels tout cela s'est produit.
Le mode d'échec ici consiste à tout écrire, au motif que le stockage ne coûte rien. Le stockage ne coûte rien ; la récupération sous budget de tokens, si. Une mémoire qui contient tout oblige chaque lecture future à classer un tas de quasi-doublons, et c'est du classement que viennent les erreurs.
Étape 2 — le typer pour pouvoir l'interroger
Une mémoire non typée est un tas de chaînes, et un tas de chaînes ne se cherche que par similarité. Typer une entrée comme décision plutôt que comme fait permet de demander les décisions d'un projet sans concurrencer toutes les phrases qui le mentionnent au passage.
Les types offrent aussi un endroit honnête pour les métadonnées qui comptent à la lecture : quel projet, quel agent a écrit, quand, et ce que cela remplace. Rien de tout cela n'est exprimable en texte libre sans obliger le lecteur à analyser de la prose pour le reconstituer.
Étape 3 — récupérer par pertinence, sous plafond
Au début d'une exécution, l'agent demande ce qui est pertinent pour la tâche qu'il va mener, et reçoit un ensemble borné. Le plafond n'est pas une optimisation de performance, c'est le mécanisme qui empêche le prompt de dériver vers la taille d'une transcription à mesure que le stockage grossit.
Le mode d'échec est la requête sans plafond qui renvoie tout ce qui touche à un projet. Elle se comporte bien sur la première semaine de données et se dégrade continûment ensuite, ce qui est la régression la plus difficile à voir puisque rien ne casse jamais.
Étape 4 — gérer la substitution et l'obsolescence
Un travail réécrit sa propre histoire. Une décision prise en mars est renversée en mai, et une mémoire qui renvoie les deux sans les ordonner remet à l'agent une contradiction à trancher seul — ce qu'il fera de façon instable.
C'est l'étape que les mémoires artisanales sautent le plus souvent, et c'est elle qui fait la différence entre un stockage qui devient plus utile avec le temps et un qui devient plus bruyant. Versionner les entrées, ou au minimum enregistrer ce qu'une entrée remplace, coûte peu à l'écriture et supprime toute une classe de confusions en aval.
Le construire, ou utiliser un stockage
Les quatre étapes se construisent sur une base de données et un index d'embeddings. Rien ici n'exige un produit, et pour un agent unique sur un projet unique la version maison est souvent la bonne.
Elle cesse de l'être quand plusieurs agents, sessions ou modèles doivent lire le travail des autres : les règles de typage et de substitution doivent alors être partagées plutôt que réimplémentées par agent. Venkai implémente ce motif comme un service en REST, SDK Python et MCP, soit quelques lignes par agent au lieu d'un sous-système à maintenir.
FAQ
Ne peut-on pas simplement réinjecter la conversation précédente ?
Cela tient une ou deux sessions, puis cela cesse. La transcription grossit plus vite que ce qu'on en apprend : on paie un coût en tokens croissant pour une part utile décroissante, et il faut finir par résumer, ce qui est le même problème avec un outillage plus destructeur.
Faut-il des embeddings pour cela ?
Pas toujours. Si l'agent sait sur quel projet ou quelle entité il travaille, une requête cadrée renvoie les bons éléments sans aucune recherche vectorielle. Les embeddings deviennent utiles quand l'agent ne sait pas nommer ce qu'il cherche — un cas réel, mais pas le premier à construire.
Combien réinjecter par exécution ?
Fixer un plafond dur avant de régler quoi que ce soit d'autre. Une mémoire sans plafond devient discrètement un prompt sans plafond, et la courbe de coût du système ressemble alors exactement à celle du rejeu de transcription qu'on cherchait à quitter.