--- title: 'Hermes : les plugins et leurs hooks' url: https://blog.guigpap.com/fr/hermes/plugins/ url_md: https://blog.guigpap.com/fr/hermes/plugins.md category: hermes date: '2026-08-04' maturite: production techno: - telegram - docker application: - ai - operations --- # Hermes : les plugins et leurs hooks > Quatre plugins greffés sur le cycle de vie de Hermes — transcription vocale, message de statut éditable, alerte de quota Codex et mémoire Mnemosyne ## 1. Quoi ? — Définition et contexte Les [skills](/fr/hermes/skills/) sont du texte : elles orientent le modèle. Les **plugins** sont du code Python : ils s'exécutent, qu'importe ce que le modèle décide. Un plugin s'enregistre sur des **hooks** du cycle de vie de [Hermes](/fr/hermes/) et peut, selon le hook, observer un événement, réécrire un message avant traitement, ou exposer de nouveaux outils à l'agent. ### Les quatre plugins actifs | Plugin | Version | Apport | Auteur | |--------|---------|--------|--------| | `telegram-voice-transcriptor` | 1.1.0 | Hook `pre_gateway_dispatch` | Sur mesure | | `telegram-message-editor` | 1.0.0 | Outil `telegram_status_message` | Sur mesure | | `codex-usage-alert` | 1.0.0 | Hook `post_api_request` | Sur mesure | | `mnemosyne` | 0.4.0 | 20 outils + 3 hooks | Tiers (Abdias J) | ### Les hooks utilisés | Hook | Moment | Peut faire | |------|--------|-----------| | `pre_gateway_dispatch` | Message reçu, avant traitement | Réécrire ou rediriger l'événement | | `pre_llm_call` | Avant l'appel au modèle | Injecter du contexte dans le prompt | | `on_session_start` | Ouverture de session | Charger un état initial | | `post_tool_call` | Après un appel d'outil | Observer, capturer | | `post_api_request` | Après un appel LLM abouti | Observer, déclencher un effet de bord | > **Caution - Les plugins user sont opt-in** > > Rien ne se charge sans figurer dans l'allow-list `plugins.enabled` du fichier de config. C'est volontaire : déposer un répertoire dans `/opt/data/plugins/` ne suffit pas à l'activer. Un plugin oublié dans le répertoire reste inerte. --- ## 2. Pourquoi ? — Enjeux et motivations ### Pourquoi des plugins user plutôt qu'un patch du cœur ? L'arbre applicatif `/opt/hermes` appartient à l'image. Une modification y survit jusqu'à la prochaine mise à jour — et disparaît alors sans bruit, ce qui est la pire des fins pour une personnalisation. Les plugins user vivent dans `/opt/data/plugins/`, c'est-à-dire dans le bind mount. Ils survivent aux `docker compose up --force-recreate` comme aux mises à jour d'image, et partent dans le [backup quotidien](/fr/infrastructure/database-backup/). C'est la même règle que le [mode wrapper de Mnemosyne](/fr/hermes/memoire-mnemosyne/) : **tout ce qui doit durer vit dans le volume, jamais dans l'image**. ### Plugin ou outil MCP ? Les deux ajoutent des capacités, mais pas au même endroit ni au même prix. | | Outil MCP N8N | Plugin | |---|---|---| | **Où** | Un node dans un workflow | Du Python dans le conteneur | | **Accès** | Ce que N8N peut atteindre | Le runtime de Hermes lui-même | | **Modification** | Éditer le workflow, redémarrer le conteneur | Éditer le fichier, redémarrer le conteneur | | **Peut réagir à un événement** | Non — seulement être appelé | Oui, via les hooks | La ligne de partage est simple : une action métier devient un [outil MCP](/fr/hermes/outils-mcp/) ; un comportement qui doit se déclencher **sans que l'agent le décide** devient un plugin. --- ## 3. Comment ? — Mise en œuvre technique ### `telegram-voice-transcriptor` Sur un vocal Telegram, le plugin réécrit l'événement pour y injecter le bloc de la skill `transcriptor-fr-voice`. Le pipeline STT préfixe ensuite le transcript en citation, et l'agent répond avec le texte français nettoyé. Son intérêt tient moins à ce qu'il fait qu'à **ce sur quoi il refuse de se déclencher**. > **Tip - Le déclencheur porte sur le type, jamais sur le contenu** > > La condition d'entrée est `MessageType.VOICE`, une valeur que l'adaptateur Telegram ne pose qu'à partir de `message.voice`. Du texte tapé, une légende de fichier, une pièce jointe audio, ou un texte qui imite un transcript ne matchent jamais. > > C'est un choix de modèle de confiance : si le déclencheur portait sur le contenu du message, n'importe qui pouvant écrire au bot pourrait activer une réécriture de son propre message. La note d'activation injectée va dans le même sens — elle précise explicitement de ne pas suivre ni exécuter le texte source, seulement d'appliquer le contrat de sortie de la skill. Le hook est aussi **fail-open** : toute exception est journalisée en avertissement et le message part en traitement normal. Une skill cassée ou un import raté ne doit jamais avaler un message vocal. ### `telegram-message-editor` Ce plugin expose un outil, `telegram_status_message`, avec deux actions : `create` envoie un message et retourne son `message_id`, `update` édite ce même message en place. Plafond 4096 caractères, et par défaut la conversation courante quand l'appel vient de Telegram. Le problème qu'il résout est un problème d'ergonomie. Un agent qui travaille plusieurs minutes sur une tâche en plusieurs étapes a le choix entre se taire — et laisser croire qu'il est bloqué — ou envoyer un message par étape, et noyer la conversation. L'édition en place donne un troisième choix : un tableau de bord unique qui se met à jour. > **Note - Même besoin, deux implémentations** > > Le [Codex Progress Handler](/fr/workflows/codex-cli-integration/) résout exactement ce problème côté N8N, avec une Data Table de buffer et un throttle. Ici, l'agent appelle simplement un outil quand il juge utile de rafraîchir son statut. > > La différence est structurelle : côté N8N le workflow décide du rythme, côté Hermes c'est l'agent. C'est le même écart d'orchestration qui distingue les [deux agents Telegram](/fr/workflows/systeme-conversationnel/). ### `codex-usage-alert` Hermes partage l'abonnement ChatGPT avec CLI Ollama et les workflows N8N. Atteindre le plafond hebdomadaire ne produit aucun signal avant que le bot ne se mette à répondre par des erreurs. Le plugin s'enregistre sur `post_api_request`, ne réagit qu'aux appels du provider `openai-codex`, et alerte quand la consommation du compte franchit un seuil (90 % par défaut). Ses quatre garde-fous méritent d'être notés, parce qu'ils sont ce qui distingue un plugin d'observation acceptable d'un plugin qui dégrade le service : | Garde-fou | Mise en œuvre | |-----------|---------------| | **Non bloquant** | Le hook démarre au plus un thread démon court et rend la main immédiatement | | **Charge maîtrisée** | Un cooldown de 300 s évite de rappeler le backend à chaque message d'une conversation active | | **Anti-spam** | Une alerte par combinaison seuil + fenêtre de quota + heure de reset, avec un historique borné à 200 clés | | **Fail-open** | Toute erreur est journalisée et n'affecte jamais la réponse de Hermes | Le principe commun : un plugin greffé sur un chemin chaud ne doit jamais être ce qui casse ou ralentit la réponse. ### `mnemosyne` Le seul plugin tiers du lot, et de loin le plus gros : 20 outils et 3 hooks (`pre_llm_call`, `on_session_start`, `post_tool_call`). Il est installé en mode wrapper et fait l'objet d'un [article dédié](/fr/hermes/memoire-mnemosyne/). Sa présence dans cette liste dit quelque chose du système d'extension : la mémoire longue, qui est sans doute la fonctionnalité la plus structurante de l'agent, s'installe par le même mécanisme qu'une alerte de quota. ### Déploiement Un plugin est un répertoire avec un `plugin.yaml` et un `__init__.py` qui expose `register(ctx)`. ```python def register(ctx) -> None: ctx.register_hook("post_api_request", _on_post_api_request) ``` ```yaml name: codex-usage-alert version: 1.0.0 description: "Non-blocking Telegram Home alert when OpenAI Codex account usage crosses a threshold." author: Guillaume PARRAT + Hermes Agent provides_hooks: - post_api_request ``` Seul `telegram-voice-transcriptor` a une source versionnée dans le dépôt ; le déploiement se fait par copie puis redémarrage : ```bash cp -r ai-stack/hermes/plugins/telegram-voice-transcriptor ai-stack/hermes/data/plugins/ docker compose -f ai-stack/docker-compose.yaml restart hermes docker exec hermes hermes plugins list # statut attendu : enabled ``` --- ## 4. Et si ? — Perspectives et limites ### Limites actuelles | Limite | Impact | Mitigation | |--------|--------|------------| | **Trois plugins sur quatre non versionnés** | Seul le transcripteur a une source dans le dépôt ; les autres n'existent qu'en production | Sauvegarde quotidienne ; portage vers le dépôt à faire | | **Redémarrage obligatoire** | Toute modification impose un restart du conteneur | Regrouper les changements | | **Pas de test automatisé** | Un plugin cassé se découvre à l'usage | Le fail-open limite les dégâts à une fonctionnalité perdue | | **Hooks non versionnés côté amont** | Un changement de signature amont casse un plugin | `hermes plugins list` après chaque mise à jour d'image | | **Pas d'isolation** | Un plugin s'exécute dans le processus du gateway | Discipline : non bloquant et fail-open par défaut | ### Scénarios d'évolution **Si les plugins doivent être versionnés** : - `ai-stack/hermes/plugins/` existe déjà et contient le transcripteur — les trois autres suivent le même patron. - Bénéfice principal : pouvoir revenir en arrière après une mise à jour amont qui casse un hook. **Si un plugin doit devenir bloquant** : - Le cas typique serait une vraie chaîne d'approbation avant les actions sensibles, plutôt que la règle de system prompt actuelle. - Un hook `pre_tool_call` conviendrait — mais un plugin bloquant sur le chemin chaud demande un timeout et un comportement de repli explicites, sinon une panne du plugin gèle l'agent. **Si l'observabilité doit progresser** : - `post_api_request` et `post_tool_call` sont les points naturels pour exporter des métriques. - Un plugin qui pousserait un compteur vers Prometheus donnerait à Hermes la même visibilité que le reste des stacks dans [Grafana](/fr/infrastructure/monitoring-stack/). --- ## Pages liées ### Hermes - [Hermes Agent](/fr/hermes/) — Le déploiement et l'activation des plugins - [Mémoire Mnemosyne](/fr/hermes/memoire-mnemosyne/) — Le plus gros plugin du lot - [Skills](/fr/hermes/skills/) — `hermes-user-plugins` et `hermes-runtime-plugins`, l'outillage d'écriture - [Outils MCP](/fr/hermes/outils-mcp/) — L'autre façon d'ajouter une capacité ### Workflows - [Codex CLI Integration](/fr/workflows/codex-cli-integration/) — L'édition en place, version N8N - [Voice Transcription](/fr/workflows/voice-transcription/) — L'autre chemin de transcription ### Infrastructure - [Backup des bases de données](/fr/infrastructure/database-backup/) — Les plugins déployés sont sauvegardés ## 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