Mémoire persistante pour agents IA avec Elasticsearch
19 juin 2026 · 7 min de lecture · Guides
Freelance intégration IA · Spécialiste LLM, RAG · 11+ réalisations clients
Les agents IA ont un problème de mémoire. Pas au sens de la RAM, mais au sens de la continuité : dès que la session se ferme, tout ce qu'un utilisateur a dit, tenté ou résolu disparait. La fenêtre de contexte est un tampon de travail, pas un système de mémoire.
Réponse directe : une mémoire persistante pour agent IA, c'est un store externe structuré en plusieurs types (épisodique, sémantique, procédural), requêtable par contenu et par temps, avec isolation stricte des données par utilisateur. L'équipe Elasticsearch Labs a publié une implémentation complète sur ce sujet, atteignant un R@10 de 0,89 sur 168 questions avec zéro fuite entre tenants.
Pourquoi la fenêtre de contexte ne suffit pas
Injecter l'historique complet des échanges passés dans le contexte semble une solution simple. Elle se casse rapidement en production pour trois raisons.
Coût et latence. Chaque appel grossit à mesure que les sessions s'accumulent. Pour un assistant en production avec des centaines d'utilisateurs actifs, le coût d'inférence devient un problème réel.
L'effet "lost in the middle". Les modèles ont tendance à ignorer les informations placées loin des bords de la fenêtre de contexte. Un fait critique mentionné il y a trois sessions peut tout simplement disparaitre de l'attention du modèle.
La non-persistance. Un crash, une déconnexion, une session expirée : tout est perdu. Pour un assistant qui accompagne un client sur plusieurs semaines, c'est rédhibitoire.
Les trois indices : épisodique, sémantique, procédural
L'architecture repose sur trois indices Elasticsearch distincts, inspirée du modèle COALA de la psychologie cognitive.
| Type | Contenu | Durée de vie |
|---|---|---|
| Episodique | Chaque message utilisateur, horodaté | Court terme, décroissance par decay |
| Sémantique | Faits stables sur l'utilisateur ("Sarah a un Hub v2") | Long terme, mis à jour par supersession |
| Procédural | Playbooks multi-étapes avec compteurs succès/échec | Long terme, affiné par feedback |
Cette séparation permet de donner à chaque type de mémoire son propre cycle de vie : la mémoire épisodique s'accumule vite et décroit, la mémoire sémantique est curatée et mise à jour, la mémoire procédurale s'améliore avec les retours utilisateurs.
À côté de ces trois indices, un quatrième est consulté en lecture seule : le catalogue produit ou la base de connaissances de l'entreprise. L'agent le requête via le même pipeline que ses mémoires, sans friction supplémentaire.
Le pipeline de rappel : hybrid retrieval + cross-encoder
Chaque requête de rappel passe par deux étapes.
Étape 1 : retrieval hybride avec RRF.
Le document est indexé deux fois depuis une seule écriture : le texte brut alimente l'index inversé BM25, et le même texte est routé via copy_to vers un champ semantic_text qui génère automatiquement des vecteurs denses Jina v5. Les deux legs sont fusionnés par Reciprocal Rank Fusion (RRF) avec un rank_constant=30, ce qui donne plus de poids aux positions hautes que la valeur par défaut d'Elasticsearch (60).
BM25 ancre les correspondances littérales (codes erreur, numéros de version, noms propres). Les vecteurs denses capturent la forme sémantique d'une question dont la réponse utilise des mots différents. Ni l'un ni l'autre seul ne couvre tous les cas : les deux ensemble oui.
Étape 2 : reranker cross-encoder Jina v2.
Le retriever hybride sur-fetche 80 candidats par leg. Ces candidats sont ensuite reordonnés par un cross-encoder Jina v2, qui score chaque paire (requête, document) en tandem plutôt que de comparer des embeddings indépendants. C'est le même principe que dans mon guide sur les rerankers cross-encoders : on sobre-fetche rapidement, on reclasse précisément.
Ce pipeline atteint un R@10 de 0,89 sur un jeu d'évaluation de 168 questions.
Isolation multi-tenant avec DLS
C'est le point que je trouve le plus important pour une utilisation en entreprise : l'isolation des données entre utilisateurs.
Elasticsearch Document Level Security (DLS) permet d'attacher des restrictions directement aux clés API. Chaque utilisateur dispose d'une clé qui ne peut requêter que ses propres documents. Cette isolation est appliquée au niveau de l'index, pas dans le code applicatif. Résultat : zéro fuite entre tenants sur l'ensemble des tests, sans surcharge de développement.
# Chaque requête est automatiquement filtrée par user_id via DLS
# Pas besoin de filtres applicatifs manuels
recall_results = es.search(
index="agent_memory_semantic",
query=hybrid_query,
knn=dense_query
# Le DLS ajoute automatiquement : filter: { term: { user_id: current_user } }
)Pour un contexte RGPD, cette isolation au niveau du moteur de stockage est bien plus solide qu'une isolation applicative : même un bug dans le code ne peut pas exposer les données d'un utilisateur à un autre.
Écriture et consolidation
Écriture épisodique. Chaque message utilisateur est écrit dans l'index épisodique avant que le LLM réponde. Les réponses de l'agent ne sont pas stockées : elles sont portées par l'historique de conversation et dilueraient le rapport signal/bruit.
Consolidation. Périodiquement (ou à chaque tour en mode démo), un LLM de consolidation examine les épisodes récents et en extrait :
- De nouveaux faits sémantiques avec leurs
supporting_episode_ids - De nouveaux playbooks procéduraux si une résolution multi-étapes n'a pas de match existant
- Des mises à jour de compteurs (
success_count++/failure_count++) si l'utilisateur confirme ou rejette un fix
Supersession. Quand un fait entre en contradiction avec un nouveau message ("j'ai déménagé à Édimbourg"), l'agent ne supprime pas le fait précédent. Il le marque superseded_by=nouveau_id et superseded_at=maintenant. Le recall standard filtre automatiquement les facts supersédés (filter must_not exists field=superseded_by). L'audit trail reste intact dans l'index pour les requêtes de type "où a-t-elle vécu ?".
Ce que ça donne en production
Cette architecture rend les agents beaucoup plus utiles sur des interactions longues : l'agent sait ce qui a été tenté, ce qui a fonctionné, et les préférences stables de l'utilisateur. Il ne repart pas de zéro à chaque session.
L'implémentation complète est disponible en open source sur GitHub (lien dans l'article Elasticsearch Labs). Elle expose ses tools via le protocole MCP, ce qui la rend compatible avec n'importe quel runtime d'agent.
Les points de vigilance pour la mise en production :
- La consolidation per-turn double les appels LLM par message. En production, un job batch toutes les 24h ou au-delà d'un seuil N d'épisodes est plus économique.
- Le decay des épisodes évite que l'index episodique ne devienne un foin. Configurer le
decay_factorselon la durée de vie souhaitée. - Les compteurs
success_count/failure_countdes playbooks procéduraux ne sont pas encore utilisés pour biaiser le ranking dans l'implémentation initiale. En production, les connecter au score de retrieval permet de faire remonter automatiquement les playbooks qui ont fonctionné.
TL;DR
Une mémoire d'agent robuste repose sur trois indices séparés (épisodique, sémantique, procédural), un retrieval hybride BM25 + dense + cross-encoder reranker, et une isolation DLS par tenant. C'est constructible sur Elasticsearch avec une implémentation open source existante. Le résultat : R@10 = 0,89, zéro fuite entre utilisateurs.
Si vous intégrez des agents IA dans votre entreprise et que la mémoire multi-session ou l'isolation des données sont des contraintes, parlons-en.
À propos de l'auteur
Pierre KasparianÉtudiant ingénieur en fin de cursus à l'UTT (Université de Technologie de Troyes) et freelance en intégration IA. Il déploie des LLM, pipelines RAG et agents IA pour des PME françaises et européennes, avec une attention sur le RGPD et hébergement européen. 11+ réalisations clients, dont Pretto et LiveSession.