série partie 1 / 3 · daté 2026-08-26

Vibrating Memory, partie 1 — Donner une vraie mémoire à un agent Claude, sans base de données

Le problème qu'on essaie tous de résoudre

Si vous avez construit un agent conversationnel avec l'API Claude — ou n'importe quel LLM —, vous avez probablement buté sur la même question : comment lui donner une mémoire qui dépasse la fenêtre de contexte d'une seule session, sans exploser les coûts ni la latence ?

La réponse la plus commune se résume souvent à deux techniques : un system prompt statique, et des fichiers de contexte qu'on relit au besoin. C'est un bon début, mais ça laisse de côté des questions très concrètes. Comment gérer plusieurs projets et plusieurs clients en parallèle sans les mélanger ? Comment éviter de payer le prix fort à chaque appel pour du contexte qui ne change presque jamais ? Comment permettre à l'agent d'aller chercher une information précise sans lui donner tout, tout le temps ?

Voici l'architecture qu'on a conçue pour répondre à ces questions, dans le cadre d'un assistant de gestion de projet personnel qui suit une cinquantaine de dossiers actifs chez plusieurs clients. On l'a nommée Vibrating Memory.

Une origine qui s'étale sur plusieurs mois

Le principe de base — utiliser le mécanisme de cache d'un LLM pour réduire le coût de relecture du contexte — vient d'un terrain d'expérimentation antérieur : des avatars conversationnels vidéo en direct (LiveKit, cache par préfixe côté Groq), un chantier qui roule depuis mars 2026. C'est de là que vient l'intuition de base : séparer ce qui ne change presque jamais de ce qui change à chaque tour.

La formalisation de cette intuition en une architecture unifiée et nommée — pensée spécifiquement pour le mécanisme de cache explicite de l'API Claude, avec ses cartes, ses lettres, ses règles de maintenance — date du 26 août 2026. C'est le point de départ documenté de Vibrating Memory comme système cohérent, construit et versionné depuis, session après session, entièrement en fichiers texte (Markdown), sans base de données ni infrastructure vectorielle.

Cette première partie couvre le socle : les six premières cartes, celles qui portent directement sur le cache de l'API Claude. Les parties suivantes couvriront les cartes de faits plus larges (portrait, conscience, interlocuteurs, tâches, compétences...) puis la partie la plus expérimentale du système : la mémoire sensorielle et temporelle.

Trois contraintes volontaires, pas des limitations

Avant d'entrer dans l'architecture, trois choix méritent d'être nommés clairement — parce que ce sont eux qui rendent le système réellement accessible, pas seulement élégant sur papier.

Aucun moteur de base de données. Pas de PostgreSQL, pas de vecteurs, pas de Pinecone ou de Chroma. Tout Vibrating Memory vit dans des fichiers texte ordinaires — Markdown pour les cartes, JSONL pour les journaux d'événements, logs bruts pour le contrôle technique. Ce n'est pas un raccourci pris par manque de temps : c'est un choix délibéré. Un fichier texte se lit à l'œil, se corrige à la main, se versionne avec n'importe quel outil, et surtout ne demande aucune infrastructure à faire tourner, surveiller ou payer. Pas de serveur de base de données à maintenir, pas de schéma à migrer, pas de driver à installer.

Ça fonctionne avec des LLM grand public, du moment qu'ils suivent des instructions. Le système ne dépend d'aucune capacité exotique ou propriétaire — pas de fine-tuning, pas de modèle spécialisé entraîné pour l'occasion. Il repose entièrement sur la capacité, déjà largement répandue chez les modèles actuels, à lire des règles écrites en langage clair et à les respecter de façon cohérente. Si un LLM peut suivre des consignes, il peut porter Vibrating Memory.

Tout est en langage naturel — aucun code requis pour faire fonctionner la mémoire elle-même. Les cartes ne sont pas des structures de données à interpréter par un parseur maison : ce sont des textes qu'un LLM lit et comprend directement, de la même façon qu'il comprendrait des notes rédigées par un collègue. Le code n'intervient qu'à la périphérie — pour lire un fichier, en écrire un, gérer le cache d'appel API — jamais pour encoder la logique de la mémoire elle-même.

Ensemble, ces trois choix veulent dire une chose simple : n'importe qui avec un accès à une API LLM et un espace de stockage de fichiers peut reproduire ce système. Pas besoin d'être une multinationale, ni d'avoir une équipe d'ingénierie de données.

Le principe de base : séparer le « moteur » de la « mémoire »

La première distinction, et la plus structurante, tient à une différence de nature entre ce qui rend l'agent capable d'agir intelligemment — son identité, ses règles de comportement, les outils dont il dispose — et le contenu sur lequel il opère — les faits, l'historique, les décisions passées.

On appelle la première catégorie A + B :

  • A (Persona) — qui est l'agent, comment il doit se comporter, avec qui il travaille. Contrairement à un system prompt générique unique, ce bloc est spécifique par client : l'agent qui gère les dossiers du client X n'a pas exactement le même persona que celui qui gère le client Y, même s'ils partagent une base commune.
  • B (Rules) — les règles techniques du système de mémoire lui-même : quels outils l'agent a à sa disposition (lire une fiche, en écrire une, chercher dans l'historique), comment et quand les utiliser. Ce bloc est identique peu importe le client.

A et B changent rarement — ils forment donc un excellent candidat pour le prompt caching de l'API Claude (cache_control), qui réduit le coût de lecture d'environ 90 % et la latence tant que le contenu reste identique.

La seconde catégorie — la mémoire proprement dite — se décompose en quatre couches, chacune avec un rythme de changement différent :

  • I (Index) — une liste vivante de ce qui existe dans la mémoire longue du client actif (quels dossiers, quelles sections dans chacun), pour que l'agent sache où chercher sans deviner. Change occasionnellement.
  • S (Synthèse) — un résumé compact de l'activité récente, régénéré périodiquement (par exemple tous les 30 échanges), qui capture l'essentiel sans accumuler le bruit conversationnel brut.
  • C (Chat) — l'historique conversationnel récent, tel quel. Change à chaque tour.
  • E (Mémoire longue) — des fiches détaillées, une par dossier ou projet, jamais injectées automatiquement dans le prompt. L'agent y accède via un appel d'outil, seulement quand le sujet s'y prête.

Pourquoi séparer I des blocs A+B

Une question naturelle : pourquoi ne pas simplement inclure la liste des dossiers actifs dans le bloc de règles (B), puisque B est déjà mis en cache ?

La réponse tient à la mécanique du cache : si I — qui change occasionnellement — est fusionné avec B — qui ne change presque jamais —, chaque petite mise à jour de l'index invaliderait le cache de l'ensemble, y compris la partie qui, elle, n'avait pas changé. En les séparant en checkpoints de cache distincts, un changement dans I n'affecte pas la validité du cache de A+B.

Pourquoi I est nécessaire — et pas seulement des outils « à la demande »

On pourrait se demander pourquoi ne pas simplement donner à l'agent des outils génériques (« liste les dossiers », « cherche dans telle fiche ») et le laisser explorer librement, sans index pré-construit — c'est essentiellement ce que font des outils comme Cursor avec leurs fichiers de règles et leur indexation de code.

La différence tient à la continuité de session. Dans un environnement où la conversation reste ouverte longtemps, un appel d'outil précédent reste visible dans le reste de la session : l'agent « se souvient » de ce qu'il a découvert plus tôt, simplement parce que ça fait partie de son contexte courant. Mais dans une architecture où chaque nouvelle session peut démarrer sans continuité garantie avec la précédente — le cache expirant après quelques minutes d'inactivité, par exemple —, un agent sans index de départ est complètement aveugle au démarrage : il ne sait même pas qu'une information existe quelque part tant qu'il n'a pas déjà fait une recherche pour la découvrir. Un problème classique d'œuf et de poule.

L'index (I) résout ça : il donne à l'agent une carte suffisamment détaillée — titres de sections, mots-clés, résumés courts — pour décider intelligemment quoi aller chercher, dès le premier message d'une nouvelle session.

Qui maintient l'index à jour ?

Une décision de conception qui a plus d'impact qu'il n'y paraît : quand l'agent écrit une nouvelle information dans une fiche de mémoire longue (E), qui met à jour l'entrée correspondante dans l'index (I) ?

Deux options semblent raisonnables a priori : un processus séparé côté serveur qui scanne le contenu après coup et en déduit une entrée d'index, ou l'agent lui-même, qui fournit l'entrée d'index dans le même appel qui écrit le contenu.

La seconde option s'avère nettement supérieure, pour une raison simple : au moment où l'agent rédige une section de mémoire, il a déjà, dans son contexte immédiat, tout ce qu'il faut pour la résumer correctement — le contenu qu'il vient d'écrire, les mots-clés pertinents, pourquoi c'est important. Un processus externe qui scanne le texte après coup devrait, pour produire un résumé de qualité comparable, faire un second appel au modèle : un aller-retour redondant, puisque l'information était déjà disponible gratuitement dans le premier appel.

Concrètement, ça veut dire que l'outil d'écriture de mémoire longue prend un paramètre supplémentaire pour l'entrée d'index, rempli par l'agent lui-même dans le même appel :

write_memory_card(
  project: "...",
  old_text: "...",      # pour une édition ciblée, jamais une réécriture complète
  new_text: "...",
  index_entry: {         # fourni par l'agent, dans le même appel
    section_id: "...",
    keywords: [...],
    summary: "..."
  }
)

Le serveur qui persiste ces données n'a besoin de « comprendre » ni le contenu ni son importance — c'est de la mécanique d'écriture de fichiers, rien de plus.

Édition chirurgicale plutôt que réécriture complète

Un autre choix qui a un impact réel sur le coût et la fiabilité : quand l'agent modifie une fiche de mémoire, il ne renvoie jamais le fichier complet. Il cible une portion précise à remplacer — le même principe que les outils d'édition de code (str_replace), appliqué à la mémoire elle-même.

Ça évite deux problèmes : le coût croissant de renvoyer un fichier qui grossit avec le temps à chaque petite mise à jour, et le risque qu'une réécriture complète « oublie » accidentellement une section existante.

Observabilité : mesurer ce qui est réellement envoyé

Un point souvent négligé dans les tutoriels : sans instrumentation, il est très difficile de savoir concrètement combien chaque couche de la mémoire coûte, à chaque appel. Un système de cache mal compris peut donner l'illusion d'être économique alors qu'il recharge silencieusement tout à chaque fois — cache expiré, ou checkpoint mal placé.

La pratique retenue : logger, à chaque réponse, le nombre de tokens attribuable à chacune des couches (A, B, I, S, C, E séparément, pas un total agrégé), en combinant les champs natifs usage de l'API (input_tokens, cache_creation_input_tokens, cache_read_input_tokens) avec un suivi de quels outils ont été appelés pendant l'échange. Ça permet de repérer rapidement des patterns comme « le cache expire trop souvent » ou « l'agent relit une fiche complète à chaque fois alors que l'index devrait suffire ».

En résumé

CoucheRôleRythmeCache
A — PersonaIdentité de l'agent, par clientQuasi jamaisOui
B — RulesOutils disponibles, règles d'usageJamaisOui, avec A
I — IndexCarte de la mémoire longue disponibleOccasionnelOui, séparé
S — SynthèseRésumé périodique de l'activitéPériodiqueNon
C — ChatHistorique conversationnel récentÀ chaque tourNon
E — Mémoire longueFiches détaillées par sujetÀ la demandeHors prompt

Cette architecture n'invente pas un nouveau paradigme — elle s'inscrit dans une littérature de recherche déjà active sur la mémoire des agents LLM (MemGPT, Mem0, et d'autres systèmes de mémoire hiérarchisée). Ce qu'elle apporte, c'est une application concrète et éprouvée au mécanisme de cache spécifique de l'API Claude, dans un cas d'usage réel de gestion de projet multi-clients — pas un prototype de démonstration, un outil utilisé au quotidien.

Et surtout : aucun moteur de base de données, aucun modèle propriétaire, aucun code pour porter la logique de mémoire elle-même — seulement des fichiers texte et un LLM capable de suivre des règles. C'est ce qui fait la différence entre un article qui explique un concept, et un système que vous pouvez commencer à construire dès demain matin.

Vibrating Memory ne s'arrête pas à ces six cartes. La partie 2 couvre les cartes de faits qui donnent à l'agent un portrait de l'interlocuteur, une trace de ses propres apprentissages, et une mémoire des autres outils et agents avec lesquels il interagit. La partie 3 aborde le terrain le plus expérimental du système : une mémoire sensorielle, faite de perceptions instantanées plutôt que de faits accumulés — le concept qui donne son nom à l'ensemble.

Cette architecture a été co-conçue en collaboration avec Claude (Anthropic) au fil de plusieurs sessions de travail, documentées et versionnées depuis leur formalisation le 26 août 2026.