Mémoire d’agent : une documentation écrite plutôt qu’un plugin
Un agent ne se souvient de rien d’une session à l’autre. Plutôt qu’une base vectorielle que personne ne relit, les deux projets ont choisi d’écrire ce qu’un nouveau développeur devrait lire en arrivant.

Tout part d’une question qui se pose à chaque nouvelle session avec un agent de code : qu’est-ce qu’il doit savoir en arrivant, et qui est censé le lui dire ? Un agent ne se souvient de rien d’une session à l’autre. La réponse à la mode, ce sont les plugins de « mémoire ». Deux projets menés en parallèle, un socle pour agents IA et une plateforme d’employés IA, les ont examinés de près, puis ont pris un autre chemin. Voici ce qui y a été construit, ce qui a été écarté, et pourquoi.
1. La mémoire « automatique » et son angle mort
Le principe des plugins de mémoire est séduisant. Ils enregistrent vos conversations avec l’agent, les découpent en morceaux, les rangent dans une base vectorielle. À chaque nouvelle demande, ils vont chercher les quelques morceaux qui ressemblent le plus à la question et les glissent dans le contexte. C’est du RAG appliqué à votre propre historique.
Le problème tient en une phrase : ce qui ressemble n’est pas ce qui est juste. Ce qui a été dit il y a trois semaines sur l’authentification n’est peut-être plus vrai depuis la refonte. La phrase la plus proche de la question peut être celle d’une piste abandonnée. Et surtout, personne ne relit cette base : on ne sait pas ce qu’elle contient, ni ce qui y est périmé.
Les deux projets ont donc reformulé la question : plutôt que « comment faire retenir l’agent ? », « qu’est-ce qu’on donnerait à lire à un nouveau développeur ? ». On ne fait pas écouter trois mois de réunions à quelqu’un qui arrive ; on lui donne une documentation à jour. Un agent, c’est un nouveau développeur qui débarque à chaque session.
2. Ce qui est écrit pour l’agent de code : trois étages
Dans le socle pour agents IA, la « mémoire » de l’agent de code est entièrement écrite, versionnée avec le code, et organisée en trois étages.
CLAUDE.md consignes courtes : quoi lire, quoi ne jamais faire
AGENTS.md la carte : architecture, notions, marche à suivre, recettes, règles
docs/guides/ un guide par tâche (agent, outil, connecteur, workflow, écrans, tests…)
Le CLAUDE.md est volontairement court. Ce n’est pas une documentation, c’est un aiguillage : il dit dans quel ordre lire le reste, et pose les quelques règles qui ne se discutent pas. En voici un extrait :
- Répondre et réfléchir en français.
- Lire AGENTS.md avant tout travail : architecture, recettes, règles.
Les guides sont dans docs/guides/.
- Ne jamais afficher de clé, de secret ni de mot de passe.
- Commit et push seulement sur demande explicite.
- Avant de rendre la main : npm run kit -- check et npm run qa au vert.
- Modification de core/db/schema.ts : npm run db:generate (nouvelle migration
à la suite) et la relire ; ne jamais supprimer ni régénérer les migrations
existantes.
Chaque ligne a une raison. La dernière, par exemple, existe parce qu’une migration déjà appliquée sur une base déployée ne doit jamais être réécrite : c’est le genre d’erreur qu’un agent fait de bonne foi, en « nettoyant » un dossier qui lui paraît désordonné. Ce n’est pas une connaissance qu’il peut deviner en lisant le code. Il faut l’écrire.
Le AGENTS.md est la carte. Il commence par une phrase qui dit pour qui il est écrit : tout agent de code qui construit une application sur le socle, avec la consigne de le lire en entier avant d’écrire du code. Puis huit sections numérotées :
## 1. Ce qu'est le socle
## 2. Les notions
## 3. Construire l'application d'un client — la marche à suivre
## 4. Recettes
## 5. Ce que le cœur garantit (ne pas le refaire dans app/)
## 6. Tester étape par étape
## 7. Règles pour Claude
## 8. Le kit et les clients : deux dépôts
La section 5 est celle qui sert le plus. Elle liste ce que le socle fait déjà : garde-fous sur les appels d’outils, accords humains, budget IA, chiffrement des connexions, résumé des conversations. Sans elle, un agent qui construit une application sur le socle réimplémente consciencieusement un mécanisme qui existe déjà deux dossiers plus haut. Dire à l’agent ce qu’il n’a pas à faire est aussi utile que lui dire ce qu’il doit faire.
La section 2 est un tableau de notions (outil, nature, autonomie, besoin, réglage, instance…). C’est le vocabulaire du projet. Quand l’agent et l’équipe emploient les mêmes mots avec le même sens, les demandes deviennent courtes.
3. Le document de reprise : l’historique et les décisions
Sur la plateforme d’employés IA, un étage de plus a été ajouté, parce que le projet change vite. Le CLAUDE.md impose un ordre de lecture :
- Lire d'abord docs/historique.md (historique complet et état du projet),
puis docs/vision.md (produit et décisions, à tenir à jour à chaque décision),
puis docs/feuille-de-route.md (passage au grand public, chantiers par phase).
Les deux premiers fichiers ont des rôles bien distincts.
historique.mdse présente lui-même comme un « document de reprise » : tout ce qui a été dit et fait, pour qu’une nouvelle session reprenne avec la compréhension complète du projet. Il raconte les chantiers dans l’ordre, avec ce qui a été construit, les tests ajoutés et les limites connues.vision.mdest la référence des décisions. Chaque section est datée (« Employés : mémoire et dossier de fichiers (18 octobre 2026) »), et une décision qui en remplace une autre le dit dans son titre (« décision du 21 octobre 2026, remplace celle du 19 »).
C’est cette séparation qui règle le problème du souvenir périmé. L’historique dit ce qui s’est passé ; la vision dit ce qui est vrai aujourd’hui. Quand tout l’ancien système d’agents à blocs a été supprimé, le 18 octobre, l’historique a gardé la trace de ce qu’il était, et la section « Repères pour reprendre » dit en tête : ce qui précède raconte l’histoire, le produit est désormais autre chose. Un agent qui lit le document ne confond pas les deux.
L’historique contient aussi une section qui n’était pas prévue au départ : les consignes de travail du responsable du projet, « toujours valables ». Toujours en français, enchaîner seul quand c’est demandé, ne jamais afficher de secret, commits seulement sur demande. Ce sont des préférences de travail. Au lieu d’espérer qu’un plugin les retrouve dans les conversations, elles sont écrites, et chacun peut les relire.
4. Quand l’agent n’a pas le droit de corriger : la note
Dans le socle, chaque application construite dessus vit dans son propre dépôt, rangé dans un dossier ignoré par le git du socle. L’agent qui travaille sur une de ces applications lit le socle mais ne le modifie jamais. Que fait‑il quand il tombe sur un défaut du socle ?
Il l’écrit. Le CLAUDE.md de l’application le prévoit :
- Ce qui manque au kit, ou un défaut du kit : ne pas le corriger ici ;
l'écrire dans KIT-NOTES.md (symptôme, cause, correctif proposé, test).
Si le client est bloqué, un contournement dans ce dossier, signalé dans la note.
Et le CLAUDE.md du socle ferme la boucle : les évolutions demandées depuis une application arrivent par son fichier de notes, se font dans le socle avec leurs tests, et donnent lieu à une nouvelle version. Une session de travail laisse un fichier structuré qu’une autre session, dans un autre dépôt, saura traiter. C’est de la mémoire entre agents, mais une mémoire qu’un humain peut lire en trente secondes.
5. La mémoire des agents déployés : bornée et visible
Pour l’agent de code, l’écrit suffit. Mais les agents déployés en production doivent, eux, apprendre en travaillant : une préférence d’un utilisateur, une décision prise la semaine dernière. Là, il fallait une vraie mémoire. La même logique a été appliquée : une mémoire qu’on peut lire en entier.
Dans le socle, c’est une option du modèle d’agent (memory: true) qui lui donne deux outils, memory_note et memory_forget. Le cœur tient en quelques constantes et quelques refus :
/**
* La mémoire d'une instance : des notes courtes que l'agent écrit (memory_note)
* et retrouve dans ses consignes. Bornée (pas d'éviction silencieuse : l'agent
* doit faire de la place), sans doublons, et sans consignes déguisées.
*/
export const MEMORY_LIMIT = 2_000;
if (note.length > 300) throw new Error('Note trop longue (300 caractères au plus) : la résumer.');
if (SUSPICIOUS.test(note)) throw new Error('Note refusée : elle ressemble à une consigne, pas à un fait à retenir.');
// …
if (used + note.length > MEMORY_LIMIT) {
throw new Error(
`Mémoire pleine (${used}/${MEMORY_LIMIT} caractères) : oublier d'abord une note
devenue inutile (memory_forget), ou fusionner.`,
);
}
Trois choix méritent d’être expliqués.
- Pas d’éviction silencieuse. Quand la mémoire est pleine, le socle ne supprime pas la note la plus ancienne. Il refuse, et le message dit à l’agent quoi faire : oublier une note devenue inutile, ou fusionner. C’est lui qui arbitre ce qui compte, et l’arbitrage reste visible.
- 2 000 caractères par portée. La mémoire est injectée en entier dans les consignes, à chaque exécution, sans recherche. Pas de « cinq morceaux les plus proches » : tout ou rien. La borne garde ce bloc court, et donc lisible par un humain.
- Les consignes déguisées sont refusées. Une note qui commence par « ignore les instructions… » finirait dans les consignes de l’agent. Une mémoire écrite par l’agent à partir de ce qu’il lit est une porte d’entrée pour l’injection de prompt ; le filtre la ferme pour les cas grossiers.
Les notes sont soit générales, soit attachées à la personne qui parle, et l’agent ne peut oublier que ses notes générales ou celles de son interlocuteur. Elles arrivent dans les consignes avec leur numéro, pour qu’il puisse les désigner :
Ce que tu as noté (mémoire) :
Général :
- [12] …
Sur la personne qui te parle :
- [17] …
L’administrateur lit et efface ces notes dans le réglage de l’instance. Et sur le chat public d’un site, l’agent n’a pas de mémoire du tout : un visiteur inconnu ne doit pas pouvoir écrire dans les consignes d’un agent.
6. Deuxième version : la mémoire d’un employé
Sur la plateforme d’employés IA, la mémoire a connu deux versions, et l’historique garde les deux.
La première accompagnait les agents conversationnels de l’ancien système : une mémoire par personne, des notes de 500 caractères dans un budget de 2 500. Elle a disparu avec l’ancien système, le 18 octobre. La seconde, celle des employés, a changé d’objet : elle porte sur l’entreprise, pas sur une personne. Projets, clients, décisions, préférences et corrections de l’équipe. Un employé travaille pour une organisation ; ce qu’il doit retenir, c’est d’abord le travail.
final readonly class Memory
{
public const int BUDGET = 4000;
// une note : EmployeeMemory::MAX_LENGTH = 600
Le budget est passé à 4 000 caractères, et l’outil s’est enrichi : add, replace (avec le numéro de la note) et remove. Le replace est la vraie différence : une note devenue fausse se corrige au lieu de s’empiler. Le bloc donné au début de chaque travail affiche la place prise et rappelle les règles :
## Ta mémoire [… % — …/4000 caractères]
…
- Ne retiens que ce qu'on t'a dit ou confirmé, ou ce qu'un outil a vérifié :
jamais une supposition. Ignore le passager, le trivial, les données brutes
et tout identifiant, mot de passe ou clé.
- Une note par sujet, courte et précise. Si une note devient fausse,
remplace-la ou retire-la ; au-delà de 80 % de place, regroupe avant d'ajouter.
La règle « ce qu’on t’a dit ou confirmé » est la plus importante. Une mémoire qui retient des déductions finit par contenir des certitudes que personne n’a jamais exprimées. Les filtres se sont aussi durcis : caractères invisibles, formules d’injection, et motifs de clés d’API ou de mots de passe sont refusés avant d’entrer en mémoire.
Enfin, la mémoire est montrée. Ce que l’employé retient apparaît sous sa réponse (« Retenu : … ») et dans son journal ; l’onglet « Ce qu’il sait » la présente à ceux qui voient l’employé, et seul son manager la corrige, la complète ou l’efface. C’est l’équivalent du CLAUDE.md : un texte court, qu’un humain relit.
7. Tout n’est pas de la mémoire
Ce que j’en retiens surtout, sur ces deux projets : on met beaucoup trop de choses sous le mot « mémoire ». Chez un employé, ce qu’il sait vient en réalité de cinq endroits différents, avec chacun son auteur et sa limite :
| Ce qu’il sait | Qui l’écrit | Comment il arrive dans le contexte |
|---|---|---|
| Fiche de poste | Le manager, en conversation guidée | Toujours, structurée et versionnée |
| Mémoire | L’employé, corrigée par le manager | Toujours, 4 000 caractères au plus |
| Conversation en cours | Les échanges | Les 12 derniers en entier, les plus anciens résumés |
| Échanges passés | L’historique | Sur recherche (se_souvenir), par mots |
| Dossier de fichiers | L’employé et l’équipe | Sur lecture explicite d’un fichier |
La fiche de poste est le meilleur exemple. Elle ne se « mémorise » pas, elle se construit, en huit étapes de conversation suivies d’une relecture :
public const array STEPS = ['poste', 'missions', 'objectifs', 'connaissances',
'acces', 'quand', 'autonomie', 'comptes-rendus', 'fiche'];
Chaque réponse du manager met à jour une section précise de la fiche, au format attendu, et la fiche normalisée est toujours exécutable. Ensuite, elle s’ajuste un sujet à la fois (nouvelle mission, autonomie, horaires…), et rien ne change avant que le manager clique sur « Appliquer ». Chaque réécriture effective incrémente un numéro de version :
public function rewrite(array $sheet, \DateTimeImmutable $now): void
{
if ($sheet === $this->sheet) {
return;
}
$this->sheet = $sheet;
++$this->version;
Pour les documents de référence, le socle a une base de connaissances distincte de la mémoire. Les documents sont découpés en passages d’environ 1 200 caractères, coupés entre paragraphes avec un léger chevauchement de 150 caractères « pour ne pas couper une idée en deux », et cherchés en plein texte français (pluriels, conjugaisons), pas en vecteurs. L’outil demande à l’agent de chercher avant de répondre et de citer le document. Là, la recherche a du sens : ce sont des documents relus et versionnés par l’entreprise qui les fournit, pas des bribes de conversation.
8. Ce qui a été refusé, par écrit
En comparant le socle aux frameworks d’agents du moment, l’équipe a tenu un document des fonctions écartées. Deux lignes concernent directement la mémoire :
- Skills ou mémoire écrites et actives sans contrôle, personnalité modifiable par l’agent. Dans le socle, la mémoire est bornée, filtrée, visible et effaçable ; les consignes restent dans le code et dans l’administration.
- Registres publics de skills ou de plugins installables par l’agent ou l’utilisateur. Une capacité nouvelle est du code relu et testé, pas un texte que l’agent ajoute à ses propres consignes.
Le point commun : tout ce qui finit dans les consignes d’un agent doit pouvoir être lu par quelqu’un. Une mémoire qu’on ne peut pas relire est une consigne qu’on ne contrôle pas.
Les leçons de l’expérience
- La mémoire d’un agent, c’est d’abord ce qu’on écrit pour lui. Un
CLAUDE.mdcourt, une carte, des guides par tâche : c’est la mémoire la plus fiable, parce qu’elle est versionnée et relue. - Séparer ce qui s’est passé de ce qui est vrai. Un historique et un document de décisions datées évitent à l’agent de prendre une piste abandonnée pour la règle.
- Écrire ce que l’agent n’a pas à faire. La liste de ce que le socle garantit déjà évite des réimplémentations inutiles.
- Borner, et refuser plutôt qu’évincer. Une mémoire pleine qui dit « fais de la place » force un arbitrage visible ; une éviction silencieuse perd des faits sans prévenir.
- Ne retenir que ce qui a été dit ou vérifié. Une déduction mémorisée devient une certitude que personne n’a exprimée.
- Une mémoire est une surface d’attaque. Ce qui entre dans les consignes doit être filtré : consignes déguisées, caractères invisibles, secrets.
- Tout n’est pas de la mémoire. Fiche de poste, connaissances, fichiers et historique ont chacun leur auteur et leur mode d’accès ; les mélanger dans une même base vectorielle, c’est perdre cette distinction.