AccueilAuteursContact

La mémoire des agents IA, de la fenêtre de contexte au rappel épisodique

Par Siraj ACHABBAK
June 14, 2026
5 min de lecture
La mémoire des agents IA, de la fenêtre de contexte au rappel épisodique

Un agent qui repart de zéro à chaque session n’est pas vraiment un agent, c’est une fonction sans état déguisée. Le moment où ça devient gênant arrive vite : l’agent refait deux fois la même erreur dans la même journée, oublie une décision qu’il a prise dix minutes plus tôt, ou recharge l’intégralité d’un historique de 200 messages dans son prompt parce qu’il ne sait pas trier ce qui compte. Le problème n’est presque jamais le modèle. C’est l’architecture de mémoire autour du modèle.

Cet article décrit comment structurer cette mémoire de façon concrète : ce qu’on garde en contexte court terme, ce qu’on persiste, comment on retrouve un épisode passé pertinent sans tout recharger, et comment optimiser la base vectorielle qui sert de socle. L’angle est architectural, pas magique.

Contexte court terme et mémoire persistante : deux choses différentes

La confusion la plus courante consiste à traiter la fenêtre de contexte du modèle comme une mémoire. Ce n’en est pas une, c’est un buffer de travail.

Le contexte court terme, c’est ce que le modèle voit dans son prompt à l’instant T : la requête courante, les quelques derniers tours de conversation, les résultats d’outils récents. Il est volatile, borné par la taille de la fenêtre, et entièrement reconstruit à chaque appel. Tout ce qui en sort est perdu, sauf si vous l’avez écrit ailleurs.

La mémoire persistante, elle, survit aux sessions. Elle vit dans un stockage externe (base relationnelle, store clé-valeur, base vectorielle) et n’entre dans le contexte que sur demande, par récupération sélective. C’est la distinction structurante : le contexte est poussé vers le modèle à chaque appel, la mémoire persistante est tirée à la demande quand elle devient pertinente.

En pratique on combine plusieurs couches. Une mémoire de travail (l’état de la tâche en cours, souvent un simple objet en RAM ou en session). Une mémoire à long terme factuelle (préférences utilisateur, faits stables, ce qu’on appelle parfois mémoire sémantique). Et une mémoire épisodique, qui est le sujet le plus intéressant et le plus mal géré.

Le rappel épisodique : retrouver, pas tout recharger

Un épisode, c’est une trace d’expérience vécue par l’agent : “j’ai tenté cette action, dans ce contexte, voici ce que j’ai observé, voici le résultat”. Le rappel épisodique consiste à retrouver les quelques épisodes passés pertinents pour la situation présente, au lieu de réinjecter l’historique complet.

La différence est pratique. Réinjecter tout l’historique, c’est saturer la fenêtre, payer des tokens pour du bruit, et noyer le signal utile au milieu de centaines de lignes sans rapport. Le rappel épisodique inverse la logique : on stocke chaque épisode durablement, et au moment de raisonner, on récupère les k plus pertinents par rapport à la situation courante.

Concrètement, chaque épisode mérite sa propre table. Voici un schéma minimal qui marche bien :

CREATE TABLE episodes (
    id           BIGSERIAL PRIMARY KEY,
    agent_id     TEXT        NOT NULL,
    session_id   TEXT        NOT NULL,
    action       TEXT        NOT NULL,   -- l'action tentée
    observation  TEXT,                   -- ce que l'agent a vu en retour
    outcome      TEXT,                   -- success | failure | partial
    summary      TEXT        NOT NULL,   -- résumé court, c'est lui qu'on indexe
    embedding    VECTOR(1024),           -- embedding du summary
    metadata     JSONB       NOT NULL DEFAULT '{}',
    created_at   TIMESTAMPTZ NOT NULL DEFAULT now()
);

Deux détails qui comptent. D’abord, on n’embedde pas l’épisode brut mais un résumé (summary) : le texte brut d’un appel d’outil est souvent verbeux et bruité, un résumé orienté “intention plus résultat” donne de bien meilleurs voisins. Ensuite, le champ outcome n’est pas décoratif : pouvoir filtrer sur les échecs passés permet à l’agent d’éviter de retenter une approche qui n’a pas marché.

Le rappel se fait alors en deux temps : on encode la situation courante en vecteur, on cherche les épisodes les plus proches, puis on injecte uniquement ceux-là dans le contexte. Le reste de l’historique reste sur disque.

Optimiser la base vectorielle, là où tout se joue

La qualité du rappel dépend presque entièrement de la base vectorielle. C’est là que la plupart des agents se cassent les dents, et c’est aussi là qu’on a le plus de leviers.

Embeddings et chunking

L’embedding transforme un texte en vecteur dense. Deux règles de bon sens trop souvent ignorées : utiliser le même modèle d’embedding à l’écriture et à la lecture (sinon les vecteurs ne vivent pas dans le même espace), et normaliser la granularité. Un épisode trop gros dilue le sens dans le vecteur, un épisode trop petit perd le contexte. Pour des épisodes, le résumé joue déjà ce rôle de chunk naturel. Pour des documents, découpez en passages cohérents avec un léger recouvrement plutôt qu’à taille fixe aveugle.

Index : HNSW ou IVF

Au-delà de quelques milliers de vecteurs, le scan exhaustif devient trop lent et on passe à un index de recherche approximative (ANN). Les deux familles courantes :

CritèreHNSWIVF
Structuregraphe de navigation multi-niveauxpartitionnement par clustering
Entraînementaucunrequis (apprend les centroïdes)
Paramètres clésM, ef_construction, ef_searchnlist (partitions), nprobe (partitions sondées)
Mémoireplus gourmandplus léger
Profilexcellent rappel, écritures plus coûteusesplus compact, sensible au réglage de nprobe

HNSW est souvent le défaut raisonnable pour une mémoire d’agent : pas d’étape d’entraînement, bon rappel, ajout incrémental d’épisodes. On accepte en échange une empreinte mémoire plus élevée. IVF devient intéressant quand le volume explose et que la mémoire compte. Dans les deux cas, le réglage est un curseur rappel contre latence : monter ef_search (HNSW) ou nprobe (IVF) améliore le rappel mais ralentit la requête. Il n’y a pas de valeur universelle, ça se mesure sur vos données.

Métrique de similarité

Encore un piège classique. La métrique doit correspondre à la façon dont le modèle d’embedding a été entraîné. La plupart des modèles modernes sont entraînés pour la similarité cosinus. Avec pgvector, attention aux opérateurs, ils sont faciles à confondre : <=> correspond à la distance cosinus, <-> à la distance euclidienne (L2), <#> au produit scalaire négatif. Choisir le mauvais opérateur donne des résultats qui semblent “presque bons”, ce qui est le pire des cas parce que personne ne s’en rend compte tout de suite.

Filtrage par métadonnées

Une recherche vectorielle pure ramène les voisins sémantiques, mais ignore les contraintes dures. On veut presque toujours croiser les deux : “les épisodes les plus proches, mais seulement pour cet agent, récents, et qui ont échoué”. D’où l’intérêt du JSONB et du outcome dans le schéma. Avec pgvector et l’extension HNSW :

SELECT id, summary, outcome, created_at
FROM episodes
WHERE agent_id = $1
  AND outcome  = 'failure'
  AND created_at > now() - INTERVAL '30 days'
ORDER BY embedding <=> $2     -- $2 = embedding de la situation courante
LIMIT 5;

Un avertissement de prod : combiner filtre et index ANN n’est pas gratuit. Si le filtre est très sélectif, l’index approximatif peut renvoyer trop peu de candidats après filtrage et dégrader le rappel. Certaines bases gèrent le filtrage pendant la traversée du graphe, d’autres après. Vérifiez le comportement de votre moteur avant de supposer que le filtre est “transparent”.

Recherche hybride

Le vecteur dense capture le sens mais rate parfois les correspondances exactes : un identifiant, un nom de fonction, un code d’erreur précis. La recherche hybride combine la recherche dense avec une recherche lexicale creuse (type BM25), puis fusionne les deux classements. La méthode de fusion la plus simple et robuste est la fusion de rangs réciproques (Reciprocal Rank Fusion, RRF), qui combine les positions plutôt que des scores hétérogènes difficiles à comparer. Pour une mémoire d’agent qui manipule des identifiants techniques, c’est souvent ce qui fait passer le rappel de “à peu près” à “fiable”.

TTL et compaction

Une mémoire qui ne fait que grossir finit par devenir lente et incohérente. Deux mécanismes l’évitent. Un TTL sur les épisodes périmés (les traces volatiles n’ont pas vocation à vivre éternellement), et une compaction qui fusionne des épisodes redondants en un souvenir consolidé. Concrètement, dix tentatives quasi identiques peuvent être résumées en un seul épisode “cette approche échoue systématiquement dans ce contexte”. On gagne en signal et on réduit le volume à indexer. Ce travail tourne idéalement en tâche de fond, pas dans le chemin critique de la requête.

L’objectif réel : un historique cohérent dans le temps

Tout ça sert un but unique : permettre à l’agent de raisonner sur le temps long avec un historique logique et cohérent, pas une collection de fragments contradictoires.

La cohérence ne vient pas que de la qualité du rappel. Elle demande une discipline sur l’horodatage (un épisode est toujours daté, pour distinguer une décision périmée d’une décision actuelle), sur la traçabilité (savoir de quel épisode vient une croyance de l’agent), et sur la résolution des conflits (que faire quand deux épisodes se contredisent : privilégier le plus récent, le plus fiable, signaler l’ambiguïté). Une base vectorielle parfaitement réglée qui ramène un souvenir obsolète sans le marquer comme tel produira un agent confiant et faux, ce qui est exactement ce qu’on cherche à éviter.

Le piège de fond à garder en tête : la mémoire d’un agent n’est pas un dossier où l’on jette tout en espérant que la recherche fera le tri. C’est un système avec un cycle de vie. On écrit (quoi garder, sous quelle forme résumée), on récupère (quoi remonter, filtré et borné), et on oublie (quoi expirer ou consolider). Négliger la troisième étape est l’erreur la plus fréquente, parce qu’elle ne se voit pas au début, seulement quand la base a grossi et que le rappel s’est silencieusement dégradé.

Commencez simple : une table d’épisodes, un index HNSW, un filtre par métadonnées, et un TTL. Ajoutez la recherche hybride et la compaction quand le besoin se manifeste, pas avant. Une mémoire d’agent, ça se construit par couches, et chaque couche doit gagner sa place.


Tags

#ia#agents#rag#vectordb#architecture
Article précédent
Outbox et Circuit Breaker - fiabiliser la communication entre services event-driven
Siraj ACHABBAK

Siraj ACHABBAK

Software engineer

Sommaire

1
Contexte court terme et mémoire persistante : deux choses différentes
2
Le rappel épisodique : retrouver, pas tout recharger
3
Optimiser la base vectorielle, là où tout se joue
4
L'objectif réel : un historique cohérent dans le temps

Liens rapides

À proposDevenir auteurContact

Social Media