--- title: 'Hermes : la mémoire longue Mnemosyne' url: https://blog.guigpap.com/fr/hermes/memoire-mnemosyne/ url_md: https://blog.guigpap.com/fr/hermes/memoire-mnemosyne.md category: hermes date: '2026-08-04' maturite: production techno: - docker - telegram application: - ai - knowledge --- # Hermes : la mémoire longue Mnemosyne > Provider mémoire externe en SQLite local, recherche hybride vecteur + FTS5, installé en mode wrapper pour survivre aux mises à jour d'image ## 1. Quoi ? — Définition et contexte Un agent qui oublie tout entre deux conversations n'est qu'un chatbot avec des outils. Ce qui distingue [Hermes](/fr/hermes/) d'un appel LLM ponctuel, c'est qu'il **capitalise** : ce qui est dit lundi reste disponible jeudi. [Mnemosyne](https://github.com/mnemosyne-oss/mnemosyne) est le provider mémoire externe qui assure cette persistance — une base SQLite locale avec recherche hybride vecteur + FTS5 et capture en tâche de fond à chaque tour. ### Ce que remplace Mnemosyne La mémoire native de Hermes est un fichier `MEMORY.md` réinjecté dans le prompt système. Simple et lisible, mais elle plafonne vite. | | `MEMORY.md` natif | Mnemosyne | |---|---|---| | **Stockage** | Un fichier Markdown | Base SQLite | | **Recherche** | Aucune — tout est réinjecté | Hybride : vecteur + FTS5 | | **Budget** | Plafond de caractères dans le prompt | Rappel sélectif selon la requête | | **Capture** | Écriture explicite | Tâche de fond à chaque tour | | **Structure** | Texte libre | Épisodes, triplets temporels, graphe | Le fichier natif n'est pas supprimé pour autant : il reste en place et redevient la mémoire active si le provider externe est désactivé. ### Configuration active ```yaml memory: memory_enabled: true user_profile_enabled: true memory_char_limit: 2200 user_char_limit: 1375 provider: mnemosyne nudge_interval: 10 flush_min_turns: 6 ``` Deux budgets distincts : `memory_char_limit` pour ce que l'agent a retenu, `user_char_limit` pour le profil utilisateur qu'il construit au fil des échanges. --- ## 2. Pourquoi ? — Enjeux et motivations ### Pourquoi le mode wrapper plutôt qu'une image custom ? C'est la décision structurante de cette installation. Trois voies étaient possibles : | Voie | Coût | Problème | |------|------|----------| | **Image custom** | Un `Dockerfile` qui étend l'image upstream | Casse le flux DIUN : plus de détection automatique des mises à jour amont, rebuild manuel à chaque version | | **Patch de `/opt/hermes`** | Modifier l'arbre applicatif dans le conteneur | Écrasé à chaque mise à jour d'image | | **Mode wrapper** | Venv latéral + plugin, entièrement sous `/opt/data` | Survit aux recreate **et** aux mises à jour d'image | Le mode wrapper gagne parce que `/opt/data` est un bind mount : tout ce qui y vit est hors du cycle de vie de l'image. Le conteneur reste strictement l'image upstream, DIUN continue de détecter les nouvelles versions, et rien n'est à reconstruire. > **Note - Le prix à payer** > > La limite mémoire du conteneur passe de 2 à 3 Go — le profil `mnemosyne-memory[embeddings]` embarque fastembed et ses modèles ONNX, qui tournent en local. Sur un VPS à 16 Go, c'est le poste le plus cher de l'ai-stack après Qdrant et CLI Ollama. En pratique le conteneur reste sous 500 MiB au repos. ### Pourquoi local-first ? La capture tourne à chaque tour, sur tout ce qui passe dans la conversation : notes de réunion, décisions techniques, informations sur des contacts. Envoyer ce flux à un service de vectorisation externe reviendrait à exporter en continu le contenu des échanges. Mnemosyne calcule ses embeddings localement et stocke tout dans un SQLite du volume de données. Aucune donnée de conversation ne sort du VPS pour être indexée. --- ## 3. Comment ? — Mise en œuvre technique ### Où vit quoi | Élément | Chemin | |---------|--------| | Venv latéral (`mnemosyne-hermes` → `mnemosyne-memory[embeddings]`) | `/opt/data/.mnemosyne/venv` | | Shim de plugin + manifeste (découverte par Hermes) | `/opt/data/plugins/mnemosyne/` | | Skill embarquée | `/opt/data/skills/memory/mnemosyne-memory-override/` | | Base SQLite | `/opt/data/mnemosyne/data/mnemosyne.db` | L'activation tient en une ligne : `memory.provider: mnemosyne` dans le fichier de config. ### Les outils exposés Le plugin déclare **20 outils** et **3 hooks** (`pre_llm_call`, `on_session_start`, `post_tool_call`) : | Famille | Outils | |---------|--------| | Mémoire | `mnemosyne_remember`, `mnemosyne_recall`, `mnemosyne_update`, `mnemosyne_forget`, `mnemosyne_invalidate` | | Graphe et triplets | `mnemosyne_triple_add`, `mnemosyne_triple_query`, `mnemosyne_graph_query`, `mnemosyne_graph_link` | | Bloc-notes | `mnemosyne_scratchpad_write`, `mnemosyne_scratchpad_read`, `mnemosyne_scratchpad_clear` | | Consolidation | `mnemosyne_sleep` | | Transfert | `mnemosyne_export`, `mnemosyne_import`, `mnemosyne_sync_push`, `mnemosyne_sync_pull`, `mnemosyne_sync_status` | | Diagnostic | `mnemosyne_stats`, `mnemosyne_diagnose` | Les hooks font le travail invisible : `on_session_start` charge le contexte pertinent, `pre_llm_call` injecte le rappel dans le prompt, `post_tool_call` capture ce qui mérite d'être retenu. > **Tip - La consolidation par « sommeil »** > > `mnemosyne_sleep` déclenche une passe de consolidation : regroupement d'épisodes, déduplication, promotion des faits récurrents. Par défaut elle n'utilise pas de LLM. L'option `MNEMOSYNE_HOST_LLM_ENABLED=true` route ces appels vers le client Codex de Hermes — plus fin, mais ça consomme le quota ChatGPT partagé, d'où le choix de la laisser désactivée. ### Exploitation ```bash # Le provider est-il bien actif ? docker exec hermes hermes memory status # → Provider: mnemosyne, available # Statistiques de la base docker exec --user hermes -e HOME=/opt/data -e HERMES_HOME=/opt/data hermes \ /opt/data/.mnemosyne/venv/bin/mnemosyne stats # Mise à jour docker exec --user hermes -e HOME=/opt/data hermes \ /opt/data/.mnemosyne/venv/bin/pip install --no-cache-dir -U mnemosyne-hermes docker compose -f ai-stack/docker-compose.yaml restart hermes ``` > **Caution - Le wrapper devient obsolète après un bump de Python** > > Le venv latéral pointe sur l'interpréteur de l'image. Si une mise à jour d'image fait passer Python d'une version mineure à la suivante, les `site-packages` ne sont plus importables et le provider tombe silencieusement en « stale ». La réparation est une réinstallation complète : > > ```bash > docker exec --user hermes -e HOME=/opt/data hermes \ > /opt/hermes/.venv/bin/python3 -m venv --clear /opt/data/.mnemosyne/venv > docker exec --user hermes -e HOME=/opt/data hermes \ > /opt/data/.mnemosyne/venv/bin/pip install --no-cache-dir mnemosyne-hermes > docker exec --user hermes -e HOME=/opt/data -e HERMES_HOME=/opt/data hermes \ > /opt/data/.mnemosyne/venv/bin/mnemosyne-hermes install --mode wrapper --force \ > --python /opt/data/.mnemosyne/venv/bin/python > docker compose -f ai-stack/docker-compose.yaml restart hermes > ``` > > C'est le revers du mode wrapper : il découple l'installation de l'image, mais pas de son interpréteur. > **Danger - memory off, jamais tools disable memory** > > Pour revenir à la mémoire native, la commande est `hermes memory off` — elle désactive le provider externe et laisse `MEMORY.md` prendre le relais. `hermes tools disable memory` fait tout autre chose : elle supprime l'intégralité de l'outillage mémoire, y compris natif. L'agent perd alors toute capacité de mémorisation, pas seulement Mnemosyne. ### Sauvegarde La base de données part dans le [backup quotidien](/fr/infrastructure/database-backup/). Le venv et le cache de modèles fastembed en sont exclus : ils pèsent lourd et se réinstallent en une commande. Conséquence à connaître pour une restauration : la base revient telle quelle, mais le venv est à recréer avant que le provider redevienne disponible. --- ## 4. Et si ? — Perspectives et limites ### Limites actuelles | Limite | Impact | Mitigation | |--------|--------|------------| | **Mémoire liée au conteneur** | Un second utilisateur partagerait la même mémoire et le même profil | Un conteneur par utilisateur plutôt qu'une allowlist élargie | | **Consolidation sans LLM** | Le regroupement d'épisodes reste mécanique | `MNEMOSYNE_HOST_LLM_ENABLED=true`, au prix du quota | | **Contenu opaque** | La base SQLite n'est pas lisible dans Obsidian | Export en notes markdown, prévu | | **Wrapper fragile au bump Python** | Panne silencieuse après une mise à jour d'image | Vérifier `hermes memory status` après chaque update | | **Pas de mémoire partagée avec le poste** | Ce que sait Hermes, l'assistant local l'ignore | Synchronisation bidirectionnelle, prévue | ### Scénarios d'évolution **Si la mémoire doit devenir lisible** : - Export des mémoires en notes markdown dans `vps-vault`, avec frontmatter de provenance. - L'intérêt dépasse la lecture : une mémoire versionnée dans Git devient auditable et corrigeable à la main. - La skill `mnemosyne-operations` couvre déjà la gouvernance de cet export. **Si la mémoire doit être unique entre l'agent et le poste de travail** : - Les outils `mnemosyne_sync_push` / `mnemosyne_sync_pull` existent déjà côté plugin. - Reste à choisir le sens de vérité en cas de conflit, et à décider si le chiffrement côté client est nécessaire. **Si le volume devient un problème** : - `mnemosyne_invalidate` et `mnemosyne_forget` permettent déjà un élagage ciblé. - Une passe de consolidation régulière compresse mieux qu'une suppression brutale. --- ## Pages liées ### Hermes - [Hermes Agent](/fr/hermes/) — Le déploiement et son modèle de sécurité - [Plugins](/fr/hermes/plugins/) — Mnemosyne est l'un des quatre plugins actifs - [Skills](/fr/hermes/skills/) — `mnemosyne-operations`, la procédure de gouvernance mémoire ### Infrastructure - [Backup des bases de données](/fr/infrastructure/database-backup/) — La base est sauvegardée, le venv non - [AI Stack](/fr/infrastructure/ai-stack/) — Qdrant, l'autre base vectorielle de l'infra ### Référence - [Glossaire](/fr/reference/glossary/) — Mémoire à long terme, Embeddings, Vector Database ## Métadonnées agent - Cet article est issu du blog GuiGPaP Lab. - Contexte global du blog: https://blog.guigpap.com/llms.txt - Contact auteur: https://odoo.guigpap.com/mon-cv - Licence: CC-BY-SA 4.0