Une mémoire capable de changer d'avis

Le mois dernier, votre client a migré sa base de commandes de Postgres vers MariaDB. Vous l’avez dit à l’agent, et il l’a noté. Ce mois-ci, vous demandez, en passant, quelle base utilise le service de commandes — et il répond Postgres sans hésiter. Quand vous allez voir, le fait plus récent est bien là, l’ancien aussi, et rien dans l’un ou l’autre ne dit lequel croire. Le plus dur dans la mémoire n’a jamais été le stockage. C’est changer d’avis : le monde bouge, une note s’avère fausse, une affirmation cesse de tenir — et « oublier » ne devrait pas vouloir dire « le texte est toujours dans le fichier ».
Le magasin de faits local holographic a passé les dernières semaines à combler précisément cette moitié. Il vivait autrefois dans l’arborescence de Hermes comme provider intégré ; le 11 octobre, il est passé dans le dépôt propre de son mainteneur et a commencé à être distribué comme plugin du catalogue, puis, le 13 octobre, il a été porté en 0.13.0. Cette mise à niveau a apporté bien plus qu’un changement d’adresse.
De l’écrasement à la révision : cinq actions
Jusqu’à récemment, on pouvait à peu près faire deux choses avec un fait mémorisé : en ajouter un, ou le supprimer puis l’ajouter à nouveau. La seconde option changeait discrètement l’id du fait, si bien que tout ce qui pointait vers cet id cassait. Un fait possède désormais son propre historique, et les actions se répartissent en cinq :
| Action | Quand l’utiliser | Ce qu’elle signifie |
|---|---|---|
change |
le monde a bougé (même chose, nouvelle réponse) | une nouvelle version du même fait ; l’id reste |
correct |
la note était fausse au moment où elle a été écrite | une correction ; la formulation remplacée cesse d’apparaître |
end |
ça ne tient plus, mais ce n’était pas faux | clôturer, conserver l’historique |
revert |
vous voulez annuler la dernière modification | retour à la version précédente |
history |
vous voulez voir ce que ce fait a traversé | liste toutes les versions |
La compatibilité est assurée : les anciennes formulations fonctionnent encore. add supersedes est traité comme change (et ne change plus l’id), update content comme correct, et remove comme forget. Vos scripts existants n’ont pas besoin d’être réécrits.
Demander « qu’est-ce qu’on pensait à l’époque » : as_of
Dès qu’un historique existe, une nouvelle question surgit : voulez-vous savoir ce qui est vrai maintenant, ou ce que vous croyiez le 10 septembre ? Les deux réponses peuvent différer, et pendant un incident, c’est généralement la seconde dont vous avez besoin.
La recherche et la liste acceptent donc un argument as_of tel que as_of: 2026-09-10. Elle ne répond qu’à partir des versions qui tenaient à cette date et renvoie une liste undetermined distincte pour les faits dont l’état à cette date ne peut être établi. Un début inconnu est signalé comme inconnu plutôt qu’inventé, et c’est la partie qui mérite qu’on s’y arrête. La recherche par défaut ne voit toujours que les faits courants : le texte historique vit dans sa propre table et son propre index, si bien qu’il ne pollue jamais les résultats du quotidien.
Chaque version enregistre aussi où elle a été écrite — plateforme, id de chat ou de fil, id de session, ainsi que l’id et le nom de l’auteur du tour. Les titres de chat ne sont jamais stockés, si bien que la provenance ne traîne pas discrètement vos noms de groupe dans la base.
Oublier pour de vrai
Sur beaucoup de systèmes, « supprimer » bascule un drapeau tandis que le texte reste dans le fichier et dans les sauvegardes. forget va plus loin : le fait et chacune de ses versions sont retirés, les deux index plein texte sont reconstruits, l’opération s’exécute avec secure_delete, puis VACUUM et tronque le WAL — l’objectif étant que le texte quitte le fichier, et pas seulement les résultats de requête.
Ce qui subsiste est une pierre tombale contenant l’id et un hachage à clé, jamais le texte. Cela empêche l’extraction automatique de ressusciter le fait et permet à d’autres outils de nettoyer leurs propres copies par id. Le coût mérite d’être dit clairement : cette opération est irréversible.
Un bot, plusieurs groupes sans rapport : scope: chat et scope: thread
Si votre bot siège dans plusieurs groupes clients, entasser chaque fait dans une seule base est un risque. scope: chat donne à chaque conversation sa propre base ; scope: thread descend d’un cran, par sujet de forum. Les deux s’appuient sur les id de chat et de fil que le cœur transmet déjà aux providers de mémoire — aucune modification du cœur et aucune logique de routage de votre côté.
Trois lignes de sécurité : identifiants, images, texte non fiable
Un magasin de mémoire a une surface de risque facile à négliger : tout ce qu’il contient est injecté dans chaque tour suivant. Écrire ne suffit donc pas — le contenu est aussi vérifié à la sortie.
- Les identifiants accompagnés d’une valeur ne sont jamais stockés. Un mot désignant un identifiant suivi de sa valeur (
password hunter2,API key sk-…) est refusé avec un motif ; le mot seul reste un fait légitime (« j’utilise un gestionnaire de mots de passe »). La 0.13.0 a élargi la fenêtre à trois mots tout en réduisant les fausses alertes :the token is 0.125 USDest un prix, pas un mot de passe. - Une image n’est pas un fait. La syntaxe d’image Markdown ou HTML n’est jamais traitée comme un fait, car le client qui la rend va lui-même chercher cette adresse, et des données peuvent voyager dans le chemin ou la chaîne de requête.
- Le rappel vérifie à nouveau avant d’injecter. En 0.13.0, un fait est réexaminé à la sortie : un balisage de rôle chat ou d’appel d’outil, une formulation qui ressemble à une instruction, un identifiant accompagné de sa valeur, des caractères invisibles et des images maintiennent un fait hors du rappel, avec une journalisation unique par processus. À noter que cela ne supprime rien —
search,listethistoryle montrent toujours, parce que vous avez posé la question et que vous avez le droit de le corriger ou de l’oublier.
Un piège à connaître : les écritures depuis cron
Si vous exécutez une maintenance de la mémoire selon un calendrier — un rangement nocturne, par exemple — un bug est resté silencieux longtemps : depuis la 0.2.0, les écritures de mémoire issues d’une tâche cron ne prenaient tout simplement pas effet. Le cœur transmet agent_context: "cron", et le plugin traitait chaque contexte de ce type comme en lecture seule, si bien que votre tâche de maintenance continuait à signaler un succès tout en ne stockant rien. Le plugin de consolidation nocturne fait partie des choses qui tombent dessus.
C’est désormais dissocié : les appels explicites fact_store / fact_feedback depuis cron écrivent à nouveau (cron_writes, activé par défaut), tandis que les écritures automatiques — extraction automatique, mise en miroir, comptages de rappel — y restent désactivées. Un script de rangement manuel peut faire son travail sans accumuler discrètement des faits sans surveillance.
À propos du déménagement : il n’y a rien à faire de votre côté
Holographic vivait autrefois dans l’arborescence du cœur (plugins/memory/holographic/) ; depuis le 11 octobre, c’est un plugin du catalogue maintenu par itpartypattaya. La bonne nouvelle, c’est que seul le code a changé d’adresse :
- le nom du provider est inchangé —
memory.provider: holographicfonctionne toujours ; - la section de configuration est inchangée — toujours
plugins.hermes-memory-store; - la base est inchangée — toujours
$HERMES_HOME/memory_store.db, ou ledb_pathque vous avez défini ; - les outils sont inchangés.
Le chemin de mise à niveau est automatique : hermes update installe le plugin du catalogue pour chaque dossier de profil qui nomme le provider, et si vous mettez à jour via l’application de bureau, l’agent l’installe et vous le signale au premier démarrage. Si l’installation ne peut pas avoir lieu, vous ne restez pas silencieusement sans mémoire — avec security.allow_lazy_installs: false, hors ligne, ou une installation refusée, l’avertissement nomme la commande exacte hermes plugins install holographic pour ce profil. Deux commandes confirment l’état :
hermes memory status
hermes plugins list
Le flux complet d’installation et de bascule :
hermes plugins install holographic # depuis le catalogue de plugins
hermes memory setup # choisir un provider de façon interactive
# ou le définir directement :
hermes config set memory.provider holographic
La mécanique du déménagement correspond à ce que nous décrivions dans les providers de mémoire quittent le cœur ; la différence cette fois, c’est ce que le plugin a gagné ensuite. (Si vous avez installé la copie intermédiaire de Nous Research depuis son propre dépôt, hermes plugins update holographic vous fait passer sur l’entrée du catalogue et vos données restent en place.)
Comment ça se compare
| Option | Ce qu’elle stocke | Idéale pour |
|---|---|---|
| MEMORY.md / USER.md intégrés | préférences et faits que vous voulez toujours chargés | tout le monde (toujours actif) |
| holographic (cet article) | un magasin de faits SQLite local avec historique de versions et scores de confiance | entièrement local, quand vous avez besoin de révisions et d’une vraie suppression |
| Mémoire sémantique (LanceDB) | mémoire à long terme récupérée par similarité vectorielle | rappel par le sens plutôt que par le fait |
| Consolidation nocturne (dreaming) | corrobore des faits candidats pendant la nuit et propose ce qu’il faut garder | vous tenez déjà un magasin de faits et voulez le faire converger |
Le rappel multilingue a lui aussi progressé. Le chinois simplifié et traditionnel sont reconnus l’un comme l’autre, les variantes d’orthographe japonaises se correspondent, les composés allemands se découpent dans les deux sens, les mots russes de même racine viennent d’un dictionnaire, et les formes fléchies en anglais, espagnol, français et portugais sont couvertes — données issues d’Open English Wordnet, jieba, SudachiDict, Wikidata Lexemes et DerivBase.Ru, sous licences respectives CC BY 4.0, MIT, Apache-2.0 et CC0. Les chiffres du mainteneur sur un ensemble à l’aveugle : les questions chinoises écrites dans l’autre graphie passent d’un rappel de 33 % à 100 %, et les questions russes de même racine de 83 % à 92 %. Ces chiffres sont les mesures du mainteneur lui-même — utiles, mais pas parole d’évangile. Si vous voulez moins de bruit, recall_indicator (activé par défaut) et auto_extract (désactivé par défaut) sont les deux interrupteurs à actionner ; la confiance évolue de +0,05 pour un retour utile et de −0,10 pour un retour inutile.
La version courte
- Le monde change et les notes s’avèrent fausses. Une mémoire capable de se réviser mérite son nom :
change/correct/end/revertconservent les versions, etas_ofvous ramène à ce qui tenait un jour donné. - Oublier est une opération destructrice : chaque version, chaque index, chaque reste dans le fichier, ne laissant qu’une pierre tombale sans texte — et c’est irréversible.
- Revérifier le contenu avant l’injection, voilà ce qui rend ce magasin digne de confiance : identifiants, images et textes à consonance impérative ne passent jamais inaperçus dans le tour suivant.
- Si holographic est déjà configuré, la mise à niveau ne vous demande rien. Sinon, c’est désormais un plugin du catalogue et une seule commande suffit à l’installer.