Plus besoin de redémarrer : Hermes sert à chaud les profils créés pendant que la passerelle tourne

Il est deux heures du matin et vous venez de terminer la mise en place d’un troisième bot : hermes profile create, le token collé, un petit bonjour sur Telegram — et rien. Le bureau affiche toujours la passerelle de ce profil comme arrêtée. Vous cherchez la réponse dans la documentation : « redémarrez la passerelle ». Sauf que les deux autres profils sont au milieu de tâches longues, et un redémarrage signifie les interrompre tous les deux.
Ce dilemme n’existe plus. La PR #109239, fusionnée dans main le 2026-09-12, apprend à une passerelle multiplex en cours d’exécution à repérer les profils qui apparaissent sous elle et à les servir immédiatement — sans redémarrage et sans dégâts collatéraux pour les profils qui travaillent déjà.
Ce qu’est réellement une passerelle multiplex
Par défaut, un profil signifie une configuration indépendante plus un bot, et garder ce bot en ligne suppose de lancer un processus de passerelle rien que pour lui : hermes -p nom gateway run. Plus de profils, plus de processus — plus de mémoire, plus de journaux, plus de ports à surveiller.
Une passerelle multiplex procède autrement : un seul processus de passerelle héberge les adaptateurs de bot de plusieurs profils à la fois. On l’active avec gateway.multiplex_profiles: true dans la configuration, et ensuite vous ne démarrez plus un processus par profil. Tout partage une passerelle, tandis que chaque profil garde son propre environnement d’exécution isolé — sa mémoire, sa base SQLite, son cache d’agents.
Le prix de cette conception se paie au moment de la découverte. Le multiplexeur n’énumérait le répertoire profiles/ qu’une seule fois, au démarrage : _start_secondary_profile_adapters construisait les adaptateurs à partir de la liste telle qu’elle existait à cet instant, _record_served_profiles notait qui était servi, et cron réutilisait le même instantané profile_homes. Un profil créé après ce moment n’était pas dans la liste : aucun adaptateur, aucun sondage, son bot ne pouvait jamais se connecter, et le bureau signalait la passerelle de ce profil comme arrêtée. À l’inverse, un profil supprimé restait indéfiniment dans served_profiles.
Dans un monde où un bot égale un processus, ce n’est pas gênant : un nouveau bot obtient un nouveau processus. Avec le multiplexage, en revanche, profiles/ est un répertoire qui change, et la passerelle n’y avait jeté qu’un seul coup d’œil. Créer un profil devrait suffire à ce qu’il fonctionne, sans vous demander de redémarrer toute la passerelle — et d’interrompre le travail long des autres — à cause d’un adaptateur qui n’a jamais été construit.
Trois situations, trois chemins
La PR #109239 (fusionnée le 2026-09-12, +641 / −43 sur 27 fichiers) fait passer le multiplexeur d’un « énumérer une fois au démarrage » à un « réconcilier en continu ». Une passerelle en cours d’exécution compare sans arrêt le répertoire profiles/ à l’ensemble qu’elle sert déjà, puis agit sur la différence. Trois situations couvrent la quasi-totalité des cas.
| Situation | Déclencheur | Ce que fait la passerelle |
|---|---|---|
| Profil créé | hermes profile create, le POST /api/profiles du tableau de bord, « New profile » dans le bureau |
Construit l’adaptateur et le sert aussitôt ; en plus, elle envoie un ping au socket de contrôle via un nouveau verbe, rescan-profiles |
| Identifiants ajoutés après coup | Modification du config.yaml ou du .env d’un profil servi |
Le changement de signature déclenche un rescan ; l’adaptateur est construit dans la portée d’exécution propre à ce profil. Les plateformes déjà actives sont ignorées, les tokens en double rencontrent la même protection |
| Profil supprimé | Retiré du répertoire profiles/ |
Démontage de l’adaptateur, arrêt du routage, libération des descripteurs pairing / busy / cache d’agents / SQLite / mémoire |
Créé : servi immédiatement. Les trois voies fonctionnent. La commande hermes profile create, le POST /api/profiles du tableau de bord et le parcours « New profile » du bureau envoient un ping au socket de contrôle après la création, en utilisant le nouveau verbe rescan-profiles pour que la passerelle regarde à nouveau maintenant plutôt qu’au tour suivant.
Identifiants après coup. Créer d’abord le profil et coller le token ensuite est l’ordre habituel, et ces identifiants comptent comme une configuration apparue après le démarrage. Ce cas est détecté par les changements de mtime sur le config.yaml ou le .env du profil servi : la modification déclenche un rescan, et l’adaptateur est construit dans la portée d’exécution du profil. Les plateformes déjà actives sont ignorées, et un token en double tombe exactement sur la même protection contre les identifiants dupliqués qu’au démarrage : le second est mis en attente avec un avertissement et n’obtient jamais son propre poller, car deux pollers sur un même token se disputent les mêmes messages.
Supprimé : démonté et retiré du routage. Les reconnexions sont annulées, les descripteurs pairing / busy / cache d’agents / SQLite / mémoire sont libérés, les chemins /p/nom/ de ce profil disparaissent et served_profiles est mis à jour en conséquence. Aucun adaptateur à moitié mort ne reste à occuper de la mémoire ou à retenir un token de bot.
Le rescan de secours toutes les 30 secondes
Le ping sur le socket de contrôle est le chemin rapide, et les chemins rapides échouent : la passerelle est peut-être en train de démarrer, le socket de contrôle n’écoute peut-être pas encore, ou il n’y a simplement aucune réponse. C’est pourquoi la modification embarque aussi un watcher supervisé qui relit profiles/ toutes les 30 secondes (la constante du code est _PROFILE_RESCAN_INTERVAL_SECS = 30.0). Le service immédiat est un meilleur effort ; la correction est garantie par la passe périodique en dessous.
Le client du socket de contrôle est rescan_gateway_profiles(home, timeout=8.0), qui envoie rescan-profiles et renvoie normalement un résultat contenant served_profiles, added, removed et d’autres champs. Le point intéressant est la dégradation volontaire : si aucune passerelle ne répond, ou si celle qui répond est une version ancienne, l’appel renvoie None. L’appelant ne tombe pas en erreur : il se rabat sur le rescan périodique, ce qui, en ligne de commande, revient à conserver le rappel de redémarrage habituel. Dans l’autre sens, c’est tout aussi tolérant : une installation Hermes ancienne ne s’effondre pas parce qu’un client plus récent lui pose une question qu’elle ne comprend pas.
Les rescans sont peu coûteux parce que la détection de signature ne parcourt pas le contenu du répertoire : elle examine exactement deux fichiers, config.yaml et .env, et compare leur (mtime_ns, size). Ce sont les constantes _PROFILE_SIGNATURE_FILES = ("config.yaml", ".env"). C’est aussi pourquoi coller des identifiants déclenche une reconstruction : vous enregistrez le fichier, le mtime bouge, la signature change. Tout le reste aux alentours, un nouveau journal ou un cache oublié, ne provoquera pas de fausse alerte.
L’implémentation vit dans un nouveau module, gateway/run_profile_reconcile.py, rattaché à l’environnement d’exécution de la passerelle sous le nom GatewayProfileReconcileMixin — davantage un réconciliateur qui garde un œil sur le répertoire profiles/ qu’une couche de gestion de processus supplémentaire.
cron, découverte MCP et routage des journaux suivent le mouvement
Un nouveau profil, ce n’est pas seulement un bot de plus. Les minuteries cron sont passées ici à un énumérateur vivant, si bien que les tâches planifiées d’un profil fraîchement créé se déclenchent réellement au lieu d’être ignorées parce que le profil n’était pas dans l’instantané de démarrage. Les nouveaux profils bénéficient aussi de la découverte MCP et du routage des journaux. Ce sont ces détails qui rendent honnête la formule « ça marche dès la création » ; sans eux, votre nouveau bot répondrait aux messages pendant que ses propres tâches planifiées resteraient immobiles.
Si vous voulez que chaque profil fasse tourner cron avec son propre bot, le guide cron par profil contient l’exemple complet.
Rien d’autre n’est interrompu
La vraie question à poser sur le service à chaud est de savoir s’il redémarre discrètement tous les autres au passage. Non. Pendant toute la passe de réconciliation, les autres profils servis restent totalement intacts : même pid, mêmes compteurs de sondage, et les conversations en cours ne sont pas interrompues. La réconciliation ne touche que la différence — ajouter ce qui est nouveau, démonter ce qui a disparu, laisser exactement tel quel tout ce qui est déjà correct.
C’est là la véritable différence avec un redémarrage de la passerelle. Un redémarrage abat le processus et tous ses adaptateurs, puis reconstruit l’ensemble. La réconciliation ne change que la partie qui doit changer. Pour une passerelle multiplex, c’est précisément ce que devrait signifier le mot « à chaud ».
Ce que vous verrez dans l’interface
Le signal le plus visible est une bannière qui cesse d’apparaître. Le point d’entrée de configuration des plateformes (un PUT sur /api/messaging/platforms/ avec l’identifiant de la plateforme) renvoie désormais un champ hot_served. Quand il vaut true, le bureau (dans les six langues) comme le tableau de bord sautent la bannière « redémarrage nécessaire ».
hermes profile create confirme également le service à chaud directement. Le rappel de redémarrage n’est conservé que lorsque le multiplexeur n’a réellement pas pris le profil en charge — par exemple si aucune passerelle ne tourne, ou si le socket de contrôle n’a pas répondu.
Comment l’utiliser
- Vérifiez que le multiplexage est actif :
gateway.multiplex_profiles: true. - Créez le profil :
hermes profile create nightshift. - Placez le token du bot dans son
.envou sonconfig.yaml. Les deux ordres conviennent ; si vous le collez après coup, le changement de signature construit l’adaptateur pour vous. - Vérifiez avec
hermes gateway statusque le profil apparaît bien parmi les profils servis. - S’il n’apparaît pas : laissez jusqu’à 30 secondes au rescan de secours. S’il manque toujours,
hermes gateway restartreste la sortie de secours. Une passerelle ancienne ne connaît pas le verberescan-profiles, et dans ce cas le redémarrage est la seule voie — vérifiez donc d’abord que votre Hermes est assez récent pour contenir cette modification.
En résumé
Cette modification n’ajoute aucune commande. Elle change la façon dont la passerelle multiplex réagit aux changements : énumérer une fois au démarrage devient réconcilier en cours d’exécution. Les nouveaux profils sont servis immédiatement, des identifiants tardifs reconstruisent l’adaptateur, les profils supprimés sont démontés et retirés du routage, un rescan toutes les 30 secondes couvre l’échec du chemin rapide, et les profils déjà servis ne sont jamais touchés. Pour le vérifier vous-même, tests/gateway/test_multiplex_hot_serve.py contient trois cas qui correspondent aux trois chemins : un profil créé est servi, des identifiants ajoutés construisent un adaptateur, et un profil supprimé voit son routage annulé.
Pour la vue d’ensemble de plusieurs profils sur une même machine, voir faire tourner plusieurs profils en parallèle ; pour contrôler quels profils peuvent servir des bots, la liste d’autorisation de profils de la passerelle entre dans le détail.
Une note de version, parce qu’elle compte : ceci est arrivé sur main le 2026-09-12 et fait partie du travail postérieur à v0.21.2, publiée le 2026-09-11. Ce n’est pas encore sorti dans une version étiquetée, donc si vous le voulez aujourd’hui, il vous faut main.