Multiplexage des profils : le gateway activé par défaut

Lundi matin, et personne ne répond dans le groupe. Sur une seule machine, vous faites tourner trois profils Hermes — default, coder, research — et chacun possède son unit systemd, son port et son propre hermes -p coder gateway start que vous êtes censé ne pas oublier. Le redémarrage de la nuit dernière n’en a ramené que deux, et le token Telegram d’un profil s’est retrouvé interrogé par deux processus à la fois : chaque message recevait donc deux réponses. Vous n’avez rien changé — vous avez simplement une chose de plus à surveiller à chaque bot ajouté. Hermes répond à cela avec un seul processus gateway qui dessert tous les profils de la machine, et depuis le 2026-09-16 c’est le comportement par défaut, avec une garde pour qu’aucune installation existante ne bascule par surprise.
Ce qu’est un gateway multiplexé
Trois mots d’abord. Un profil est un agent Hermes autonome : sa propre configuration, ses identifiants, sa mémoire, ses skills et ses tâches cron, rangés sous ~/.hermes/profiles/<name>. Le gateway est le processus de longue durée qui garde vos bots connectés : il interroge votre bot Telegram, répond à votre webhook, réveille les tâches cron et confie chaque message entrant à un tour d’agent. Le multiplexage consiste à laisser un seul processus gateway desservir plusieurs profils.
Jusqu’ici, la forme standard était un processus par profil (ce que la documentation appelle standalone, et ce que restaure --standalone) : chaque profil a son unit, son port et son fichier PID. Un multiplexeur remplace cette flotte par un processus unique — le gateway du profil default devient le seul processus d’entrée et dessert les messages de tous les profils de la machine, en routant chaque message vers le profil auquel il appartient. Les profils restent des agents distincts ; seul le processus est partagé.
La forme un processus par profil reste entièrement prise en charge, et le guide des profils multi-instances détaille la cohabitation de plusieurs profils.
Ce qui a changé : activé par défaut, mais tranché à chaque démarrage
gateway.multiplex_profiles est désormais activé par défaut. Le point à lire deux fois, c’est ce qui se passe si vous ne l’avez jamais défini : un flag non défini est traité comme une demande, pas comme un verdict, et le gateway par défaut tranche cette demande une fois à chaque démarrage.
Au démarrage, il exécute la même pré-vérification que hermes gateway migrate --multiplex, et ne multiplexe que si le regroupement aurait été sûr :
- le profil default existe et la machine compte au moins deux profils ;
- aucun profil secondaire ne fait encore tourner son propre gateway, ni comme processus vivant, ni comme service installé ;
- deux profils ne partagent pas un même identifiant de bot ;
- aucune plateforme qui occupe un port n’est privée de son ingress
/p/<profile>/; - la machine est d’un type que la migration comprend : pas un conteneur s6, pas les Windows Scheduled Tasks.
Si l’un de ces points échoue, le gateway démarre exactement comme avant, en ne desservant que le profil default, et écrit un WARNING qui nomme le blocage et vous donne la ligne hermes gateway migrate --multiplex. Rien n’est modifié sur le disque.
Une valeur explicite n’est jamais remise en question :
gateway.multiplex_profiles: true(ce qu’écrit la migration) multiplexe sans tenir compte de la pré-vérification : la décision vient de vous ou de la migration ;gateway.multiplex_profiles: false(ce que restaure--standalone) conserve définitivement un gateway par profil ; quand il est à false, tout ce qui suit est inerte ;GATEWAY_MULTIPLEX_PROFILESdans l’environnement du processus prime sur les deux.
Le verdict est consigné, pas seulement journalisé : le gateway_state.json du home par défaut enregistre multiplex_standalone_reason, et hermes gateway status l’affiche sous la forme ⚠ Serving the default profile only (gateway.multiplex_profiles unset): <reason>, accompagné des deux remèdes. Un démarrage qui multiplexe vraiment efface cette mention.
Les autres processus cessent eux aussi de deviner le verdict à partir de la valeur par défaut fusionnée : hermes -p coder setup, le dashboard, la résolution de port au déclenchement du cron et hermes gateway migrate lisent d’abord l’enregistrement served_profiles du gateway en cours, et ne retombent sur le flag explicite que lorsqu’aucun gateway ne tourne.
Comment savoir dans quel mode vous êtes
Une commande répond à la question :
hermes gateway status
- Si une ligne commence par
Serving the default profile only, vous êtes en mode standalone, et le texte après le deux-points indique pourquoi la garde de démarrage s’est retenue. - Si cette ligne est absente, le gateway tourne en multiplexeur. Son propre enregistrement —
served_profilesdans legateway_state.jsondu home par défaut — liste chaque profil desservi, et c’est cet enregistrement que lisent les autres outils.
Dans le dashboard, ces informations se trouvent sur la page System, et côté API /api/status?profile=coder les renvoie sous le nom gateway_shared_with (null lorsque ce profil a son propre gateway).
Vous pouvez aussi le vérifier empiriquement : essayez de démarrer le gateway d’un profil secondaire. En mode multiplexeur, la CLI refuse ; en mode standalone, il démarre.
Un seul gateway, ou un processus par profil ?
Le multiplexage est payant lorsque :
- vous déployez dans un conteneur ou sur un VPS où N units supervisor, N ports et N fichiers PID pèsent ;
- vous avez beaucoup de profils à faible trafic qui ne justifient pas chacun un processus complet ;
- vous voulez une seule chose à démarrer, surveiller et redémarrer.
Ajouter un profil coûte alors un token de bot — le gateway en cours le prend en compte — au lieu d’un service supplémentaire à surveiller. Notre guide sur la desserte de profils sur un gateway en marche couvre ce chemin à chaud.
Restez en un processus par profil si vous voulez un cloisonnement fort au niveau des processus : empreintes mémoire séparées, domaines de panne indépendants et possibilité de redémarrer un profil sans toucher aux autres. Quand un skill emballé dans un profil peut entraîner tout le processus avec lui, cela compte davantage que quelques units économisées.
Regrouper la flotte volontairement
Plutôt que de redémarrer le gateway par défaut en espérant que la garde soit d’accord, lancez la migration :
hermes gateway migrate --multiplex
Dans l’ordre : elle écrit gateway.multiplex_profiles: true sur le profil default, arrête et désinstalle chaque unit installée des profils secondaires, démarre le gateway par défaut en multiplexeur, puis confirme à partir de l’enregistrement served_profiles en direct de ce gateway que chaque profil migré est bien desservi.
La migration est transactionnelle. Le flag est posé en premier, si bien qu’une interruption à n’importe quel point ultérieur est reprise possible : relancer la commande lit le manifest écrit par la migration et reprend depuis l’état réel — le served_profiles du gateway par défaut en direct doit couvrir chaque profil migré du manifest avant qu’elle se considère terminée. Si une étape ultérieure échoue (arrêt d’un profil secondaire, daemon-reload après suppression d’une unit, écriture de la configuration), les secondaires déjà retirés sont réinstallés et le flag revient en arrière. Un rollback qui ne va pas au bout conserve le manifest et le signale, pour que vous puissiez finir à la main.
Elle refuse aussi tôt, avant d’arrêter le moindre gateway en fonctionnement, lorsque le plan montre déjà que le regroupement est impossible : une flotte d’units système lancées en root sans User= enregistré à reproduire, un utilisateur enregistré que le système ne sait pas résoudre, ou un config.yaml non inscriptible. Le User= d’une unit système est préservé : la migration le lit avant de retirer quoi que ce soit et le transmet au démarrage du gateway par défaut comme au rollback.
Si vous partez de zéro plutôt que de migrer, c’est plus simple : installez Hermes, laissez démarrer le gateway par défaut, et la pré-vérification de démarrage fait le reste.
Ce qui se comporte différemment quand c’est activé
Le multiplexeur est le seul processus d’entrée : un second gateway pour le même profil lierait deux fois les plateformes de ce profil. Tout ce qui suit est automatique et devient inerte dès que le flag est à false.
Un profil secondaire ne peut pas démarrer son propre gateway. hermes -p coder gateway run, start, install et restart sont une erreur franche avec un code de sortie 78, qui vous renvoie au multiplexeur : « The default gateway is running as a profile multiplexer and already serves profile ‘coder’. » Le refus a lieu dans la CLI avant qu’aucun gestionnaire de services soit touché : un profil desservi ne se retrouve donc jamais avec une unit systemd définitivement en échec ni avec une boucle de respawn launchd. hermes -p coder gateway stop refuse de la même manière (sortie 78) quand coder n’a pas de gateway propre — il n’y a rien à arrêter hormis le multiplexeur, que hermes gateway stop sur le profil default arrête pour tous les profils desservis.
Le dashboard et le Desktop suivent la CLI. Pour un profil desservi, Start et Stop répondent 409 avec la même explication, affichée comme avis en ligne sur la page System, et Restart redémarre le multiplexeur — le processus qui dessert réellement le profil — au lieu de lancer un restart -p coder qui ne pourrait qu’échouer. Comme ce redémarrage reconnecte tous les bots de la machine, les deux applications demandent d’abord : « Restart the shared gateway? All bots on this device reconnect: default, coder, research » — la liste est le served_profiles du gateway en cours — puis annoncent « Shared gateway restarted (3 bots) ». Un profil standalone conserve le redémarrage habituel. Côté API, /api/status?profile=coder renvoie cette même liste sous gateway_shared_with (null pour un gateway standalone).
Le setup saute le service d’arrière-plan. hermes -p coder setup gateway, hermes -p coder setup, hermes -p coder gateway setup et hermes -p coder import configurent toujours les bots de ce profil, mais sautent l’étape « installer le service d’arrière-plan du gateway » pour un profil desservi, en affichant « Profile ‘coder’ is already served by the default multiplexer » au lieu d’enregistrer une unit ou un plist qui resterait inerte. Ajoutez le token du bot, et le multiplexeur en cours le prend en compte.
Les plateformes qui occupent un port passent sous un préfixe d’URL. Une plateforme qui écoute sur un port est desservie sur l’écouteur du gateway par défaut sous /p/<profile>/ : un webhook qui pointait auparavant vers le port propre à ce profil pointe désormais vers l’écouteur partagé suivi de ce préfixe, sous une forme comme /p/<profile>/webhooks/.... C’est exactement ce que vérifie la pré-vérification de démarrage : « aucune plateforme occupant un port sans son ingress /p/<profile>/ ».
Les tokens restent propres à chaque profil, et les identifiants ne sont jamais partagés. Chaque profil desservi monte ses plateformes avec ses propres identifiants de bot, et chaque tour résout la configuration, les skills, la mémoire, le SOUL et les clés de provider du profil routé. Un profil desservi n’hérite jamais non plus des identifiants du profil de lancement, flag activé ou non : un processus enfant routé vers un autre home voit les identifiants Tier-1/Tier-2 du profil de lancement retirés avant que son propre périmètre soit superposé, et une lecture d’identifiants sans périmètre pour un secondaire lève une erreur au lieu de renvoyer silencieusement la valeur du profil par défaut. Donnez à chaque profil son propre token de bot : deux profils qui en partagent un, c’est précisément ce que la pré-vérification refuse.
--force existe toujours. run, start, install et restart acceptent --force si vous voulez délibérément un processus séparé pour un profil, ce qui n’est pas recommandé tant que le multiplexeur tourne. Et le script d’enveloppe de cycle de vie inter-profils des installations standalone n’est pas utilisé en mode multiplexeur : vous ne gérez que le gateway par défaut.
Désactiver durablement, ou forcer
Réglez le flag sur le profil default — c’est lui qui possède le multiplexeur — puis redémarrez son gateway :
hermes config set gateway.multiplex_profiles false
hermes gateway restart
De façon équivalente, dans le ~/.hermes/config.yaml du profil default :
gateway:
multiplex_profiles: false
(Le flag est aussi accepté au premier niveau sous la forme multiplex_profiles: true, par commodité.)
false conserve définitivement un gateway par profil : un false sur le disque est respecté comme un rollback délibéré, et tous les comportements décrits plus haut deviennent inertes. true force le multiplexage même là où la pré-vérification se serait retenue, parce que la décision vous appartient. GATEWAY_MULTIPLEX_PROFILES dans l’environnement du gateway par défaut prime sur les deux — c’est le levier commode dans un conteneur où vous maîtrisez l’environnement plutôt que le fichier.
Il existe un levier de plus sur le chemin non surveillé : hermes update peut regrouper la flotte dans le gateway par défaut de lui-même, et la clé qui le gouverne est gateway.auto_multiplex_migration ; hermes config set gateway.auto_multiplex_migration false rend ce refus explicite. Un false du périmètre géré l’emporte sur un true de l’utilisateur, et la mise à jour refuse de regrouper une flotte dans une unit système par défaut dont elle ne peut pas résoudre le User=.
Dépannage et résumé
hermes gateway statusindique qu’un secondaire fait encore tourner son gateway. Arrêtez-le et désinstallez-le — un PID vivant ou une unit installée, voilà ce que la garde attend — puis relancezhermes gateway migrate --multiplex.- Deux profils partagent un identifiant de bot. Donnez son propre token à l’un des deux ; la pré-vérification ne va pas prendre des tokens qu’un autre processus détient encore.
- Une plateforme qui occupe un port n’a pas d’ingress
/p/<profile>/. Faites pointer son webhook vers l’écouteur par défaut avec ce préfixe, ou restez en standalone. - Rien ne se regroupe dans un conteneur s6 ni sous Windows Scheduled Tasks. Cette machine n’est pas d’un type que la migration comprend : la garde de démarrage ne peut pas le faire pour vous, gardez un gateway par profil.
- Vous obtenez le code de sortie 78 en démarrant un secondaire. C’est le contrat, pas un bug : gérez le gateway par défaut avec
hermes gateway restart, et ne recourez à--forceque si vous voulez vraiment un processus séparé. - Une migration est morte à mi-chemin. Relancez
hermes gateway migrate --multiplex; elle reprend depuis le manifest qu’elle a écrit, et un rollback incomplet conserve le manifest et vous dit ce qui reste.
En bref : le multiplexage est activé par défaut, mais sur une machine qui n’y est pas prête rien ne change — un flag non défini est tranché à chaque démarrage, le verdict est consigné et affiché dans hermes gateway status, et un true ou false explicite l’emporte toujours. Si vous faites tourner plusieurs bots sur une même machine, hermes gateway status est désormais la commande qui vous dit dans quel monde vous êtes. La liste complète des flags figure dans la référence de la commande hermes gateway.