La fonctionnalité phare de Hermes Agent v0.2.0, ce n'était ni une intégration de modèle ni le système de skills. C'était le Gateway de messagerie multi-plateforme — un seul processus Hermes qui écoutait simultanément sur sept plateformes de chat : Telegram, Discord, Slack, WhatsApp, Signal, email (IMAP/SMTP) et Home Assistant. À la release du 8 avril, la liste en comptait treize, avec Matrix, Feishu, WeCom, Mattermost, DingTalk et les SMS (via Twilio) ajoutés en cours de route.
Ce qui est facile à rater ici, c'est que construire un bot Telegram n'est pas très compliqué. Faire tourner sept intégrations de chat simultanées qui partagent un seul agent, une seule mémoire et un seul registre d'outils — c'est là que le vrai travail d'architecture se concentre. Ce billet détaille comment Hermes s'y prend concrètement.
L'approche naïve, et pourquoi elle ne marche pas
Si on te demandait de construire « un bot IA qui répond sur Telegram et Discord », le premier réflexe serait de monter deux bots séparés. Chacun avec son processus, sa base de données, son état. Les deux appellent la même API de modèle de langue. L'utilisateur sur Telegram et celui sur Discord ont conceptuellement le même agent, mais en pratique ils font face à deux agents qui ne se connaissent pas.
C'est ce que font la plupart des projets de bots existants, et c'est catastrophique de façons qui mettent du temps à se révéler :
- •La mémoire diverge. Un utilisateur qui mentionne sur Telegram qu'il est allergique aux arachides n'aura plus cette info quand il posera une question de cuisine sur Discord. Il faut apprendre la même chose deux fois à l'agent.
- •L'état des outils dérive. Un cron job configuré via Slack n'apparaît pas quand l'utilisateur vérifie ses crons sur Telegram. L'historique de session est fragmenté. Les tokens d'autorisation pour les ressources partagées (une intégration Notion, par exemple) doivent être installés dans chaque bot séparément.
- •Le coût opérationnel se multiplie. N bots signifie N processus, N services, N flux de logs, N fichiers de config, N points de défaillance. La complexité croît linéairement avec les plateformes.
- •Les règles de sécurité se fragmentent. Si tu resserres la politique d'approbation des commandes dangereuses dans un bot, il faut penser à la mettre à jour dans les autres. La dérive sécuritaire est l'état par défaut.
Hermes a fait un autre choix : un seul processus agent, une seule base de données de sessions, un seul stockage mémoire, un seul registre d'outils. Les plateformes sont des adaptateurs — de fines portes d'entrée qui canalisent les messages vers et depuis l'agent partagé.
La forme du gateway
En interne, le gateway Hermes comporte trois couches.
Tout en bas, l'agent lui-même — le même cœur Hermes que celui qui tourne en mode CLI. Il ne sait rien des plateformes de chat. Il reçoit des messages, fait tourner sa boucle d'agent (appels LLM, appels d'outils, consultations mémoire, checkpoints) et produit des réponses. Sa seule interface avec l'extérieur est une API basée sur des files d'attente.
Au milieu, le cœur du gateway — gestion des sessions, routage utilisateur/plateforme, dispatch des approbations, planification cron, streaming, gestion des médias. C'est la couche qui transforme « un message est arrivé de la plateforme X, utilisateur Y, canal Z » en « une exécution de l'agent dans la session S avec ces permissions ». Elle gère aussi les préoccupations transversales : limites de débit, contrôle d'inondation, détection de doublons, timeouts d'inactivité, routage des boutons d'approbation, état cross-plateforme.
Tout en haut, les adaptateurs de plateforme. Un par plateforme : un adaptateur Telegram, un Discord, un Slack, et ainsi de suite. Le rôle d'un adaptateur est étroit — se connecter à sa plateforme (par polling, long-poll, WebSocket, webhook, ou ce que préfère le SDK de la plateforme), traduire les événements natifs entrants dans le format de message interne du gateway, et retraduire les réponses sortantes du gateway dans ce que la plateforme attend (Markdown, MarkdownV2, mrkdwn, embeds riches Discord, HTML Matrix, blocs Slack, MIME email).
Les adaptateurs sont volontairement petits. Ajouter une nouvelle plateforme (un contributeur communautaire a ajouté Mattermost en moins de 300 lignes de Python dans la v0.4.0) revient essentiellement à mapper les événements de son SDK vers le format de message interne du gateway, et inversement.
Comment fonctionnent les sessions entre plateformes
Une session Hermes est un fil de conversation avec sa propre fenêtre mémoire, son état d'outils et son historique d'exécution. Sur une seule plateforme, la correspondance est naturelle — une session par chat Telegram, une par channel Discord, une par thread Slack. Entre plateformes, les choses deviennent plus intéressantes.
Par défaut, Hermes traite chaque combinaison plateforme/chat comme une session distincte. Ta conversation privée avec le bot sur Telegram, ton thread avec le bot sur Slack et ton channel avec le bot sur Discord sont trois conversations séparées avec trois contextes séparés, mais elles partagent toutes la même mémoire à long terme via le provider mémoire interchangeable (Honcho par défaut à partir de la v0.7.0). Du coup, les informations que tu t'attends à voir suivre d'une session à l'autre — « l'utilisateur est allergique aux arachides », « l'utilisateur s'appelle Alice », « le projet de l'utilisateur s'appelle Atlas » — voyagent sur la couche mémoire, tandis que le contexte court terme de chaque conversation reste cantonné à la plateforme que tu utilises.
C'est ce design qui fait que le même assistant donne l'impression d'être le même assistant sur chaque plateforme, sans transformer chaque message en un broadcast global enchevêtré.
Pourquoi les sessions par utilisateur dans les threads comptent
Dans la v0.4.0, Hermes a ajouté une fonctionnalité appelée sessions par utilisateur dans les threads partagés par défaut — dans les chats de groupe, chaque utilisateur a sa propre session à l'intérieur du même thread. Ça paraît petit. C'est énorme pour quiconque a déjà essayé de faire tourner un bot multi-utilisateurs dans un groupe.
Sans sessions par utilisateur dans un chat de groupe, chaque message fait partie d'une seule conversation partagée. Si Alice pose une question au bot, et que Bob en pose une autre trente secondes plus tard, le contexte du bot est un mélange embrouillé des deux. Les réponses se croisent. La mémoire d'Alice se retrouve polluée par les données de Bob. Le mode gateway empire à mesure que les utilisateurs s'ajoutent.
Avec les sessions par utilisateur, Alice et Bob ont chacun leur session privée dans le thread. Ils voient les messages de l'autre dans le chat visible, mais l'agent maintient des contextes séparés et des écritures mémoire séparées par utilisateur. À la v0.8.0, c'est devenu le comportement par défaut sur toutes les plateformes du gateway. C'est le genre de correction qui est invisible tant qu'on n'a pas été brûlé par l'alternative — et à ce moment-là, on ne veut plus jamais revenir en arrière.
À quoi sert vraiment le gateway
Quand tu observes l'architecture assez longtemps, le gateway cesse de ressembler à « une façon de faire tourner des bots sur des plateformes de chat » et commence à ressembler à ce qu'il est vraiment : une couche de coordination entre des humains (sur l'app qu'ils utilisent à un instant donné) et un assistant IA unique avec une mémoire et des outils partagés.
Les plateformes de chat ne sont pas le produit. Ce sont les points d'entrée. Le produit, c'est l'assistant qui existe derrière, et le fait que tu n'as jamais à te demander par quel point d'entrée tu passes.
C'est ça que Hermes a livré dès le premier jour. Tout le reste est l'histoire de ce que cette couche de coordination a appris à faire au cours des quatre semaines suivantes.