aller au contenu
FRFlo
Table des matières

Un agent IA ne se résume pas à un modèle qui reçoit un prompt et renvoie du texte. Dès qu’il doit rester disponible, répondre depuis une messagerie, accéder à des outils et conserver un environnement d’exécution, il devient un système distribué.

Dans mon infrastructure, Hermes Agent joue le rôle de gateway et d’orchestrateur. Il reçoit les messages Discord, construit les conversations et appelle un modèle compatible OpenAI. Les capacités externes ne sont pas ajoutées directement à Hermes : elles passent par Executor, une couche d’intégration auto-hébergée qui expose un endpoint MCP.

Cette séparation est le point important de l’architecture. Hermes raisonne et dialogue ; Executor centralise l’accès aux outils ; les serveurs MCP fournissent des capacités spécialisées. Le tout tourne dans une stack Docker, avec des services isolés des accès extérieurs directs.

Les trois couches du système

flowchart LR
    User["Utilisateur Discord"] -->|message| Hermes["Hermes Agent\ngateway run"]
    Hermes -->|appel du modèle| Models["Modèle IA"]
    Hermes -->|MCP HTTP + OAuth| Executor["Executor\nMCP toolkit Hermes"]
    Executor --> GTFS["GTFS-MCP"]
    Executor --> Moodle["Moodle-MCP"]
    Executor --> Storage["Executor /data\nvolume persistant"]

Hermes : la couche agent

Hermes est déployé avec l’image nousresearch/hermes-agent:latest. Le conteneur démarre avec gateway run, et non comme une simple session interactive. Cette différence est fondamentale : le processus reste actif, écoute les événements Discord et maintient les sessions de conversation.

Sa configuration est montée depuis config/hermes/config.yaml dans /opt/data/config.yaml. Elle décrit notamment :

  • le fournisseur de modèle ;
  • le répertoire de travail /workspace ;
  • l’interface Discord et ses règles d’autorisation ;
  • le serveur MCP distant auquel Hermes doit se connecter.

Le gateway Discord est volontairement restreint. La configuration autorise un utilisateur et un canal précis, désactive les mentions générales et n’exige pas de mentionner le bot dans ce canal. Ce sont des choix de routage et de confiance, pas des propriétés intrinsèques du modèle.

Le modèle : une dépendance séparée

Hermes n’héberge pas le modèle. La configuration pointe vers :

model:
provider: custom
default: gemini-pro-agent
base_url: https://<cliproxyapi host>/v1
api_key: not-needed
api_mode: chat_completions

Le service cli-proxy-api tourne lui aussi dans Docker, avec une configuration versionnée séparée. Il sert de façade compatible avec plusieurs fournisseurs et évite de coupler Hermes à une implémentation particulière de modèle.

Executor : le plan d’intégration

Executor est déployé avec ghcr.io/rhyssullivan/executor-selfhost:latest. Il centralise les intégrations et expose une surface MCP consommable par Hermes.

Son état est conservé dans le volume Docker executor, monté sur /data. La persistance est importante : les intégrations, la configuration et l’état du service ne doivent pas disparaître à chaque recréation du conteneur.

Hermes ne référence pas l’interface générale d’Executor, mais un toolkit MCP dédié :

mcp_servers:
executor:
url: https://<executor-host>/mcp/toolkits/hermes
auth: oauth

Le nom executor devient donc une frontière de capacités dans Hermes. L’agent ne connaît pas nécessairement l’implémentation de chaque outil en aval ; il découvre une surface MCP publiée par Executor.

MCP comme frontière de capacités

Le Model Context Protocol standardise la façon dont un client découvre et appelle des outils externes. Dans ce setup, Hermes est le client MCP et Executor est le serveur MCP visible par Hermes.

Hermes distingue les serveurs locaux et les serveurs MCP distants. Mon intégration Executor utilise un endpoint distant authentifié avec auth: oauth.

Cette organisation apporte une séparation utile :

  1. Hermes conserve la logique de conversation et de décision.
  2. Executor présente une surface d’outils cohérente à l’agent.
  3. Les serveurs spécialisés peuvent rester des services indépendants.
  4. Les identifiants et politiques d’intégration peuvent être centralisés dans Executor.

La configuration Hermes ne déclare explicitement qu’Executor. C’est donc Executor qui présente à Hermes la liste unifiée des intégrations et des outils disponibles.

Les MCP exposés à Hermes

Voici les intégrations actuellement exposées par le toolkit Hermes d’Executor :

Intégration Identifiant Executor Rôle dans le setup
GTFS gtfs Itinéraires et horaires de transports en commun.
Moodle moodle Accès à l’espace d’apprentissage Moodle.
Dockhand dockhand_api Gestion et orchestration de la stack Docker du VPS.
Cloudflare cloudflare_mcp Gestion des services réseau et des règles de sécurité Cloudflare.
Pocket ID pocket_id_api Interaction avec le fournisseur d’identité OIDC/SSO.
GitHub github_graphql Consultation et gestion des dépôts, issues et pull requests.
Pelican Application / Admin pelican_api_application Administration du panel Pelican et de ses nodes.
Pelican Client pelican_api_client Contrôle des serveurs hébergés par Pelican.
Spotify spotify Lecture en cours, recherche et gestion des playlists.
Firecrawl firecrawl_mcp Scraping, extraction de contenu et crawl de sites.
GrepApp grep_mcp Recherche de code dans les dépôts publics.
Excalidraw excalidraw_app_demo Création de schémas, maquettes et tableaux blancs.
Context7 context7_mcp Recherche de contexte et de documentation pour les outils utilisés.

Cette liste donne une image plus juste de ce que signifie « donner des outils à Hermes ». L’agent ne reçoit pas seulement un accès à un outil unique : il dispose d’un catalogue transversal couvrant la vie quotidienne, l’infrastructure, le développement, la documentation et la création de schémas.

La séparation reste nette : Hermes choisit quand utiliser un outil et présente le résultat dans la conversation ; Executor porte les intégrations et les autorisations nécessaires ; chaque service conserve sa logique métier.

Isolation et sécurité

Les composants sont isolés des accès extérieurs directs. Les services internes ne sont pas exposés comme des ports publics ; lorsqu’un accès externe est nécessaire, il passe par les mécanismes de contrôle et d’authentification prévus par l’infrastructure.

Cette séparation limite la surface d’attaque et évite que chaque serveur MCP doive devenir lui-même une application publique. Hermes ne voit que les outils qu’Executor lui expose, tandis que les services spécialisés restent derrière cette frontière.

Le chemin d’une requête

Une interaction typique suit cette chaîne conceptuelle :

  1. Un message arrive dans le canal Discord autorisé.
  2. Le gateway Hermes vérifie l’utilisateur et le canal.
  3. Hermes restaure la session correspondante et prépare le contexte.
  4. Le modèle analyse la demande et peut choisir un outil.
  5. Hermes envoie alors l’appel à la surface MCP Executor.
  6. Executor applique sa logique d’intégration et transmet éventuellement l’appel à un serveur spécialisé.
  7. Le résultat revient dans la boucle Hermes, qui peut poursuivre son raisonnement.
  8. La réponse finale est envoyée à Discord.

Le modèle ne devient donc pas directement un administrateur du VPS. Il opère dans un ensemble de surfaces d’outils exposées par Hermes et Executor. La qualité du système dépend autant de cette sélection de capacités que du modèle lui-même.

Ce que cette architecture rend possible

Le bénéfice principal est le découplage. Un nouvel outil peut être ajouté en aval sans transformer Hermes en monolithe. Un autre client MCP pourrait également consommer Executor, tandis que Hermes reste le point d’accès conversationnel orienté Discord.

La centralisation crée aussi un endroit naturel pour traiter les intégrations, leurs secrets et leur politique d’exposition. À l’inverse, elle ajoute une dépendance supplémentaire : si Executor est indisponible, les outils qu’il publie le sont également, même si Hermes et le modèle fonctionnent encore.

Enfin, l’usage d’images latest rend le déploiement simple mais moins reproductible. Pour documenter ou reproduire exactement cette installation, il faudrait conserver les versions ou digests des images utilisées, ainsi que la version d’Hermes et les versions des serveurs MCP. Le fichier actuel décrit donc une architecture opérationnelle, pas un lockfile complet de l’infrastructure.

En résumé

Hermes Agent est ici la couche d’interaction et d’orchestration : il reçoit les messages Discord, gère les sessions et pilote le modèle. Executor est la passerelle MCP qui expose à Hermes une surface d’outils centralisée. GTFS-MCP et Moodle-MCP sont les serveurs MCP spécialisés déployés en complément.

La valeur du setup ne vient pas d’un composant unique, mais des frontières entre eux. L’agent peut raisonner sans connaître chaque intégration ; les outils peuvent évoluer sans réécrire le gateway ; et l’infrastructure conserve le contrôle de la persistance et de l’exposition.