La mémoire des agents de code : stocker, c'est la moitié facile
Le billet sur le Harness de la semaine dernière montrait un vrai briefing de session, et une ligne dedans travaillait plus que toutes les autres :
- **MCP Server** [PITFALL] (claude-code/vincent, 1 day ago): every new ID argument
name must be added to idArgumentResolvers in authz.go, or the cross-org check
silently skips it.
Un agent qui lit ça économise l'après-midi que l'agent précédent a perdu. Bien. Maintenant, faites-lui prendre six mois. La même phrase, sur le même ton assuré, servie à un agent qui travaille sur un fichier que deux personnes ont réécrit entre-temps. Rien dans la ligne n'a l'air différent. L'agent n'a aucun moyen de le savoir, et vous non plus.
C'est ça, le vrai problème de la mémoire pour les agents de code, et ce n'est pas la partie que la plupart des outils construisent. Écrire les choses, c'est la moitié facile.
Pourquoi un tas de notes ne peut pas répondre à la question
Les formes courantes de la mémoire d'agent aujourd'hui, c'est un fichier markdown auquel l'agent ajoute des lignes, et un vector store dans lequel il écrit. Les deux stockent bien. Les deux retrouvent correctement. Ni l'un ni l'autre ne peut vous dire que le terrain sous une note a bougé, parce que ni l'un ni l'autre ne sait de quoi parle la note au sens structurel. Un vector store sait qu'une note est proche des mots "gateway" et "headers". Il ne sait pas que ApiGateway est un container de votre système, qu'il a un chemin dans les sources, et que le code à ce chemin a cessé de correspondre au modèle documenté il y a trois semaines.
Un modèle d'architecture sait les trois. C'est tout l'argument pour mettre la mémoire à côté d'un modèle, et c'est la seule partie de ce billet qu'un autre produit ne pourrait pas copier en un sprint.
La mémoire est dans Archyl maintenant, sur tous les plans. Voici ce qu'elle fait.
Une mémoire est accrochée à un élément, pas à une conversation
Une mémoire est un fait typé note, convention ou pitfall, attaché à un élément C4 ou au projet dans son ensemble. Les agents en écrivent via MCP ; les gens en écrivent dans l'Agent Hub ou dans le panneau de détail de n'importe quel élément du diagramme.
▶ remember(projectId: …, element: "ApiGateway", kind: "pitfall",
content: "The gateway strips custom headers longer than 8KB — payloads must go in the body.")
Il existe un quatrième type, session_outcome, écrit automatiquement quand une session de travail se termine. Une session qui tenait huit leases produit une mémoire attachée à huit éléments, pas huit copies du même paragraphe. La forme compte pour la récupération : un agent qui pose une question sur l'un de ces éléments reçoit le résultat une seule fois, plutôt que de se voir relire huit fois le même résumé parce que la session a touché huit choses.
Le contenu et les titres des mémoires sont chiffrés au repos, comme toutes les autres colonnes de contenu sensible du produit.
Le recall classe par le sens, pas par sous-chaînes partagées
recall mélange similarité sémantique et recouvrement de termes, pondérés 0.55 contre 0.45. Un agent qui pose une question sur le "rate limiting" récupère la note que quelqu'un d'autre a écrite sur le "throttling", le cas qu'une recherche par mots rate et qu'un collègue ne raterait jamais.
Les vecteurs sont best-effort par choix. Sans fournisseur d'IA configuré (compatible OpenAI ou Ollama), il n'y a pas de vecteurs et le scoring reste purement lexical, comme il se comportait avant. Ça se dégrade au lieu de casser, ce qui compte si vous vous auto-hébergez sans fournisseur. Et les mémoires écrites alors qu'aucun fournisseur n'existait ne restent pas de seconde zone pour toujours : un worker de fond rattrape leurs vecteurs dès qu'un fournisseur est configuré.
Écrire deux fois le même fait le confirme
Redire quelque chose que le projet sait déjà ne crée pas une deuxième copie. Au-dessus d'une similarité cosinus de 0.94, l'écriture confirme la mémoire existante à la place, et la réponse indique deduplicated: true. Un agent qui réaffirme ce qu'il a appris, c'est une preuve, pas du bruit.
Entre 0.82 et 0.94 se trouve la bande intéressante : proche, mais pas le même fait. Celles-là sont stockées, et les quasi-correspondances reviennent dans similarTo, pour que l'auteur puisse appeler remember(supersedes: "Old title") délibérément au lieu de contredire en silence une mémoire encore vivante et encore servie.
La mémoire apprend de l'usage
Chaque recall enregistre quelles mémoires il a servies à quelle session. Quand la session se termine, usedMemories nomme celles sur lesquelles elle s'est réellement appuyée.
Ces deux signaux ne sont délibérément pas pondérés pareil. Se faire servir une mémoire est circonstanciel. Dire qu'on l'a utilisée est un témoignage. Donc seules les citations font monter le rang d'une mémoire, en échelle logarithmique et plafonné à 1.8x, pour qu'une mémoire populaire ne puisse pas enterrer la plus récente qui la corrige. Une mémoire servie à cinq sessions sans une seule citation reçoit un multiplicateur de 0.75 et est traitée comme du bruit.
Traitée comme, pas supprimée. Rien dans la mémoire n'est jamais retiré par une heuristique. Les mémoires ignorées atterrissent dans une file de revue avec leur nombre d'impressions, et une personne décide. Le même principe traverse toute la fonctionnalité : corrigé, jamais effacé.
Une mémoire a un cycle de vie
La fraîcheur décroît sur une demi-vie de 45 jours à partir du moment où la mémoire a été connue vraie pour la dernière fois, c'est-à-dire sa création ou sa confirmation la plus récente. confirm_memory remet ce compteur à zéro et incrémente le nombre de confirmations. remember(supersedes: …) remplace un fait qui a changé : l'ancienne version quitte la récupération mais reste dans l'historique et dans le graphe, pour que vous puissiez encore voir ce que le projet croyait l'an dernier.
Les poids par type s'ajoutent par-dessus, et ils sont assumés : un pitfall vaut 3.0, une convention 2.0, une simple note 1.5, un session outcome 1.0. Pour un agent sur le point de modifier du code, "ça va te mordre" passe devant "voilà ce qui s'est passé".
Ce qui invalide vraiment une mémoire, c'est le drift
Tout ce qui précède est de la comptabilité correcte. Cette section est la raison pour laquelle la mémoire a sa place dans un outil d'architecture.
Le temps est un mauvais indicateur de vérité. Une convention écrite il y a deux ans sur le fonctionnement de vos frontières de service est probablement encore juste. Une note écrite le mois dernier sur un fichier réécrit depuis est probablement fausse. La décroissance les traite de la même façon, parce qu'une horloge est tout ce qu'elle a.
Ce qui rend vraiment une mémoire suspecte, c'est le changement du code derrière son élément. Archyl calcule déjà ça, de façon déterministe : le drift score compare le modèle documenté au dépôt et nomme les éléments qui ne correspondent plus. Lancez-le depuis l'UI, depuis l'API, ou à chaque push avec la GitHub Action drift-score. La mémoire y est maintenant branchée.
Quand le drift trouve un élément désynchronisé, chaque mémoire attachée à cet élément est estampillée du moment où c'est arrivé. Une mémoire confirmée pour la dernière fois avant cette estampille décrit quelque chose qui a bougé sous elle depuis. Trois choses en découlent :
- Elle est rétrogradée dans le classement, par un multiplicateur de 0.6. Rétrogradée, pas cachée : c'est peut-être la seule chose que quiconque ait jamais écrite sur cet élément, et la cacher serait pire que la servir avec un avertissement.
- Elle apparaît dans la file de revue pour un humain.
- L'agent lit un avertissement, dans le briefing, en mots plutôt qu'en métadonnées :
- **ApiGateway** [PITFALL] [VERIFY — the element drifted since this was written]
(claude-code/sarah, 96 days ago): the gateway strips custom headers longer than 8KB.
Reconfirmer la mémoire efface le drapeau, parce qu'une confirmation répond directement à la question du drift : quelqu'un a regardé, et ça tient toujours.
Les deux moitiés de ce mécanisme vivent dans le même produit. La connaissance est ici, et la comparaison modèle-contre-code qui peut la remettre en cause aussi. Une couche de mémoire boulonnée sur un client de chat a la première moitié et aucun moyen d'obtenir la seconde.
Les mémoires se lient entre elles
Donnez un titre à une mémoire et elle devient adressable. N'importe quelle autre mémoire peut alors la référencer avec [[Title]] dans son contenu, à la façon d'Obsidian. La même syntaxe se résout vers les éléments C4 par leur nom ([[ApiGateway]]) et vers les décisions ([[ADR-17]]), et un lien vers un titre qui n'existe pas encore reste en attente et s'attache tout seul au moment où quelqu'un écrit cette mémoire.
Les liens ne servent pas qu'à la lecture. recall les suit : les meilleures correspondances entraînent leurs voisines liées, marquées via pour que vous voyiez ce qui les a amenées. Un pitfall sur la gateway qui pointe vers l'ADR expliquant pourquoi la frontière existe arrive avec le raisonnement attaché.
La knowledge map, et le graphe qu'on a jeté
La première version du panneau de mémoire était un graphe nœuds-liens. Il s'affichait, il faisait des clusters, il avait l'air du genre de chose qu'on met en capture d'écran. Il répondait à "quelle mémoire est liée à quelle mémoire", et ce n'est pas une question que quiconque posait.
Ce que les gens ont besoin de savoir, c'est quelles parties de leur architecture le projet comprend et quelles parties personne n'a jamais décrites. Alors on l'a remplacé. Le panneau montre maintenant une cellule par élément C4 : ce qu'on en sait, à quel point cette connaissance est fraîche, combien de pitfalls s'y trouvent, et, pour les éléments sans rien du tout, un trou visible. Ça produit un titre qu'aucun dashboard ne vous donnait avant :
3 of 19 elements documented
Cette phrase est inconfortable d'une façon utile. Le graphe ne l'était pas.
Ce qu'elle ne fait pas
Le recall sémantique a besoin d'un fournisseur d'IA. Pas d'endpoint compatible OpenAI et pas d'Ollama veut dire pas de vecteurs, et le classement retombe sur le recouvrement de termes. Tout le reste de cette page fonctionne quand même.
La mise en correspondance des éléments reste lexicale. La mémoire classe par le sens maintenant. L'étape d'avant, find_relevant_context qui choisit de quels éléments parle votre tâche, score toujours par recouvrement de mots sur les noms, les descriptions, les tags et les chemins. Une tâche sur le "checkout" ne fera toujours pas remonter un component appelé OrderProcessor. On avait signalé cette limite dans plusieurs agents, une seule architecture et c'est toujours vrai.
Le signal d'utilité n'existe que si les agents citent ce qu'ils ont utilisé. Le skill archyl-harness apprend à l'agent à passer son sessionId à recall et à nommer usedMemories quand il termine. Rien ne l'y force. Un agent connecté sans le skill produit des impressions et aucune citation, ce qui se lit exactement comme une mémoire que personne n'a trouvée utile.
La mémoire est à la portée du projet. Une convention valable pour toute l'organisation doit être écrite dans chaque projet qui en a besoin. C'est la prochaine chose qu'on corrige.
Et la réserve honnête d'ensemble : la mémoire vient tout juste de sortir. On n'a pas de chiffres d'adoption, pas de benchmark, et aucun client pour vous dire qu'elle lui a fait gagner quoi que ce soit. Ce qui est au-dessus, c'est ce que fait le code, et vous pouvez en vérifier chaque morceau sur votre propre projet.
Par où commencer
Si vous faites déjà tourner le Harness, la mémoire est déjà active. remember, recall et confirm_memory sont trois des seize tools du profil coding. La version 0.8.0 du plugin Claude Code est la pièce qui apprend à un agent les deux habitudes dont dépend le classement : passer son sessionId à recall, et nommer ce qu'il a utilisé quand il termine.
La première chose qui vaut le coup n'est pas d'écrire des mémoires. C'est d'ouvrir la knowledge map et de lire la ligne de couverture. Quelle que soit la fraction affichée, c'est la fraction de votre architecture qui survit au départ en vacances de la personne qui la comprend. Devinez le nombre avant de regarder, puis regardez.
Ensuite, prenez l'élément qui a le plus de trafic et le moins d'écrit, et écrivez le piège que vous raconteriez à une nouvelle recrue son premier jour. C'est la mémoire dont le prochain agent a besoin, et tant que personne ne la tape, aucune quantité de récupération ne la trouvera.
La mémoire fait partie de l'Archyl Harness : les sessions de travail, le preflight gate, le hook Guard et la Fleet console. Le plugin, les skills et le hook Guard ainsi que les GitHub Actions sont open source, et la référence complète est dans le guide du Harness. À lire aussi : les sessions de travail, plusieurs agents, une seule architecture, et pourquoi vos agents ont un fichier de règles et pas un modèle.