Relais Encadrer des agents IA
Un seul point d’accès aux agents IA de ma machine.
Plusieurs de mes outils confient du travail à des agents Claude Code et Codex. Relais les lance à leur place : il isole chaque abonnement, en surveille la capacité, décide des permissions et garde les conversations. Je l’ai conçu et développé seul, en Rust et en Angular.
- 1 011 décisions de permission en trois jours de service Registre des correctifs du dépôt, du 21 au 23/09/2026
- 52 cas d’audit du périmètre de fichiers : 48 refus et 4 autorisations attendus Audit des permissions du dépôt, 20/09/2026
- 373 tests du serveur en Rust Code du dépôt, révision bdf041f, relevé le 14/10/2026
- Besoin
- Donner aux outils de ma machine un seul point d’accès local aux agents IA, avec des comptes isolés et chaque permission décidée par Relais.
- Ma part
- J’ai conçu et développé seul le serveur en Rust et l’interface Angular, avec leurs tests et leur documentation.
- Rôle
- Conception et développement
- Période
- Depuis septembre 2026
- Équipe
- Projet personnel, seul
- Statut
- Outil personnel, en usage sur ma machine
- Liens publics
-
Aucun : le code est dans un dépôt privé.
Un seul point d’accès pour tous mes outils
Sur ma machine, plusieurs outils confient du travail à des agents IA : Sillage orchestre des équipes d’agents, Karl Scraper automatise des tâches. Sans point commun, chacun lancerait et surveillerait lui-même son agent, avec ses propres comptes et ses propres droits.
Relais leur ouvre une seule porte : une API qui n’écoute que la machine, derrière une clé d’accès. Il lance lui-même Claude Code et Codex, dans des versions qu’il fixe, et garde les conversations dans SQLite.
Les outils de la machine
- Sillage orchestre des équipes d’agents
- Karl Scraper automatise des tâches
- Un script par l’API, avec la clé
- La console de Relais une session lancée à la main
une API locale, sur 127.0.0.1, derrière une clé
Relais
- un dossier de configuration par abonnement
- le périmètre de fichiers et les permissions
- la capacité de chaque abonnement
- un frein sur les lancements
- les conversations, dans SQLite
lance sa propre version de chaque agent
Les agents
- Claude Code
2.1.281 - Codex
0.157.1
Chaque lecture et chaque écriture passent par Relais
Un outil peut confier à l’agent un dossier où écrire et d’autres à lire seulement. En mode strict, l’agent n’a pas de terminal : Relais décide de chaque lecture et de chaque écriture. Sur ses trois premiers jours de service, il a pris 1 011 décisions de permission.
Ici, l’agent demande à lire un fichier d’un autre projet. Relais refuse, et le refus revient à l’agent avec son motif. C’est un contrôle de chaque appel d’outil, pas un bac à sable du système.
La capacité de chaque abonnement, avant chaque session
Relais ne devine pas ce qu’il reste : il lit les quotas que communique le fournisseur, jamais déduits du nom de la formule.
-
Voir
Chaque abonnement montre sa fenêtre de cinq heures et celle de sept jours, leur réinitialisation et le repère de son seuil de protection.
Le quota de cinq heures de l’abonnement « Personnel » : 35,8 %, sous le repère de son seuil de protection. Les trois abonnements de démonstration sont disponibles. -
Admettre
Avant d’ouvrir une session, Relais ajoute au quota ce que consommeront celles qui tournent déjà ; si le total dépasse le seuil, 95 % par défaut, la nouvelle session est refusée. Une session ouverte n’est jamais coupée.
Le seuil de protection : nouvelles sessions refusées dès 95 % du quota, par défaut. Une session déjà ouverte n’est jamais coupée.
Relire chaque appel
Relais garde les conversations, 90 jours par défaut après leur fin : le fil horodaté à la seconde, les outils et leurs résultats, les décisions de permission. Chacune s’exporte en Markdown ou en JSON, et ses métriques restent après sa suppression.
L’analyse mesure, pour les agents et la période choisis, la durée des tours, leur débit et leurs erreurs, et s’exporte en CSV ou en JSON.
Toutes ses fonctions, une ligne chacune
De la session à l’analyse : un clic déplie chaque fonction.
-
Lancer une session, pour un outil ou à la main
Une session se demande par l’API, ou depuis la console : l’abonnement, le modèle, le dossier de travail, l’effort, la permission et la durée de vie. L’outil qui l’a demandée se déclare par son nom, et le tableau de bord le montre.
-
Lire et piloter une conversation
La conversation en plein écran : chaque étape horodatée à la seconde, chaque outil réuni avec son résultat, les demandes de permission et les questions de l’agent à traiter. Un panneau de pilotage ramène au contexte, aux outils ou au tour voulu ; jusqu’à dix instructions attendent leur tour dans une file, et la palette de commandes s’ouvre au clavier.
-
Rejoindre la session depuis un terminal
Un terminal se connecte à la même conversation, dans la console ou depuis un shell de la machine. Ce n’est ni une seconde conversation, ni un shell du système : il envoie des messages, interrompt un tour, se déconnecte sans arrêter la session.
-
Des abonnements isolés, reconnus seuls
Chaque abonnement a son propre dossier de configuration. Relais en reconnaît l’identité et les modèles en interrogeant l’agent, sans génération, et signale deux abonnements liés au même compte.
-
Les quotas lus chez le fournisseur, la consommation comptée
Les fenêtres de cinq heures et de sept jours, avec leur réinitialisation et leur fraîcheur, telles que le fournisseur les donne. À côté, les tokens comptés par Relais et un coût estimé, qui n’est pas une facture. Une donnée absente ou périmée n’est jamais lue comme un zéro.
-
Analyser chaque appel
Des filtres croisés par agent, modèle, outil, abonnement, application et période : l’évolution de la consommation, la comparaison des coûts, la médiane et le P95 des tours, le cache, les erreurs. Le périmètre filtré s’exporte en CSV ou en JSON.
-
Des serveurs MCP confiés session par session aperçu
Un outil peut donner à sa session jusqu’à huit serveurs MCP, chacun avec la liste exacte de ses outils permis, d’un à cent. Relais refuse tout outil non listé, et le retire de ce que voit l’agent, qui sinon l’appelait pour rien.
JSON, forme simplifiée écrite pour cette page : le code est privé { "mcp_servers": { "catalogue": { "url": "http://127.0.0.1:9500/mcp", "allowed_tools": ["lookup"] } } } -
Une bibliothèque et des instructions par abonnement
Des skills et des commandes, importés, écrits ou désactivés par abonnement, s’appellent d’une barre oblique dans la conversation. Des instructions permanentes, communes ou propres à un abonnement, s’ajoutent au prompt système des nouvelles conversations.
-
Un stockage qui se recycle seul
Le poids des données par catégorie, par conversation et par abonnement. Les conversations terminées sont compressées après 7 jours, puis supprimées après 90 ; les métriques restent. Une conversation compressée se relit à l’identique.
-
Diagnostiquer, sans jamais rien installer
Le moteur, le port, la durée de fonctionnement et les agents actifs d’un regard, puis les journaux filtrés. Une carte compare la version de Claude Code fixée par Relais à la dernière publiée : Relais ne l’installe jamais lui-même, et une version nouvelle reste « pas encore validée ».
Sous le capot
L’architecture, puis quatre choix qui ne se voient pas à l’écran, le dernier né d’un incident, et ses limites. Le code est privé : les extraits sont des formes simplifiées, écrites pour cette page.
Architecture
-
Rust possède les processus, Angular n’est qu’un client aperçu
Le serveur, en Rust (Axum, Tokio, SQLite embarqué), possède les processus des agents, les règles de permission, l’état des sessions et la persistance. L’interface Angular passe par la même API que les autres outils de la machine, avec la même clé ; les identifiants des abonnements ne quittent jamais le serveur.
Schéma, forme simplifiée écrite pour cette page : le code est privé interface Angular outils de la machine │ clé + JSON ▼ API Rust (Axum) ├▶ SQLite └▶ sessions et collecteur └▶ adaptateur Claude Code · Codex └▶ agent fixé par Relais ├ configuration, abonnement A └ configuration, abonnement B -
Deux protocoles d’agent, un seul modèle de session aperçu
Avec Claude Code, Relais échange des messages JSON en flux sur l’entrée et la sortie standard ; avec Codex, il parle JSON-RPC à son serveur d’application. Les événements d’origine sont gardés tels quels, outils et demandes de permission compris, et la console relit le journal par morceaux.
Schéma, forme simplifiée écrite pour cette page : le code est privé Claude Code ⇄ stream-json, stdin et stdout Codex ⇄ JSON-RPC, codex app-server ↓ événements d’origine, gardés tels quels SQLite ├ sessions · événements └ permissions · audit -
Une durée de vie dure, un arrêt progressif
Chaque session a une échéance tenue par le serveur, même entre deux messages ; un signe de vie la prolonge, dans une borne maximale. À l’arrêt, Relais prévient l’agent, puis le coupe après 3 s : sous Unix, tout son groupe de processus ; sous Windows, un objet de tâche qui regroupe l’agent et ses descendants.
Décisions
-
Une version fixée de chaque agent, un dossier par abonnement aperçu
- Contrainte
- Plusieurs abonnements sur une même machine, alors que Claude Code et Codex lisent par défaut la connexion et les variables d’environnement de l’utilisateur.
- Choix
- Relais lance sa propre version de chaque agent, fixée dans son dossier, jamais celle installée sur la machine, avec un dossier de configuration par abonnement et un environnement vidé, puis rempli depuis une liste blanche.
- Effet
- Aucune clé ni variable d’un abonnement ne passe à un autre, et deux abonnements liés au même compte sont signalés.
Configuration, forme simplifiée écrite pour cette page : le code est privé exécutable runtime/ de Relais, version fixée (jamais celui du PATH) environnement vidé, puis rempli depuis une liste blanche CLAUDE_CONFIG_DIR le dossier de l’abonnement ANTHROPIC_CONFIG_DIR le dossier de l’abonnement -
Le chemin réel du fichier, pas celui que l’agent écrit aperçu
- Contrainte
- Les permissions de l’agent ne suffisent pas à le garder dans les dossiers confiés : un chemin peut remonter hors du dossier, passer par un lien ou désigner un fichier qui porte un second nom ailleurs.
- Choix
- Relais vérifie le chemin réel du fichier, pas celui que l’agent écrit : les chemins qui remontent hors du dossier, les liens qui en sortent et les fichiers à plusieurs liens physiques sont refusés.
- Effet
- L’audit de 52 cas a trouvé un défaut sur les fichiers à plusieurs liens physiques, corrigé après signalement ; les 52 cas passent. Recoupés avec les paramètres des appels, les 69 refus de lecture et de recherche des trois premiers jours de service ont montré des recherches refusées à tort : j’ai assoupli les règles des recherches, sans rouvrir les chemins hors du périmètre.
Règle, forme simplifiée écrite pour cette page : le code est privé chemin demandé → chemin réel (canonique) remonte hors du dossier confié → refusé lien qui sort du dossier → refusé fichier à plusieurs liens physiques → refusé dans un dossier confié → admis, en lecture ou en écriture le refus revient à l’agent avec son motif -
Admettre une session selon la charge réelle aperçu
- Contrainte
- Un seuil fixe laisse entrer de nouvelles sessions alors que celles qui tournent consomment encore : huit agents lancés en parallèle peuvent faire passer un petit abonnement de 90 % à plus de 100 % de son quota avant que le premier ait fini.
- Choix
- Avant d’admettre une session, Relais réserve ce que consommeront celles qui tournent et la nouvelle, au rythme qu’il apprend des 40 dernières sessions.
- Effet
- La réserve suit l’usage réel de chaque abonnement, et l’abonnement refuse avant d’atteindre son seuil, au lieu de le laisser dépasser par les sessions déjà lancées.
Pseudo-code, forme simplifiée écrite pour cette page : le code est privé admettre la session si quota lu chez le fournisseur + réserve des sessions en cours + réserve de la nouvelle session ≤ seuil (95 % par défaut) réserve : au rythme appris des 40 dernières sessions une session déjà ouverte n’est jamais coupée -
Un frein sur les lancements, né d’un incident aperçu
- Contrainte
- Le 27/09/2026, un outil a recréé une session par minute pendant sept heures, sur un abonnement où chacune mourait en deux secondes ; Relais n’enregistrait qu’un code d’erreur, sans message.
- Choix
- Un frein par application et par abonnement : vingt lancements d’affilée, puis un toutes les trois secondes. Trois échecs d’affilée au démarrage suspendent l’abonnement, et l’erreur cite la dernière ligne d’erreur de l’agent.
- Effet
- Tant que l’abonnement est suspendu, un lancement qui le nomme est refusé avec une attente conseillée d’une minute, doublée à chaque refus jusqu’à une heure ; l’abonnement rouvre dès qu’une de ses sessions répond, ou d’un clic sur « Réessayer ».
HTTP, forme simplifiée écrite pour cette page : le code est privé POST /api/sessions (21e lancement d’affilée) → 429 Too Many Requests Retry-After: 3 { "error_code": "rate_limited", "retry_after_seconds": 3 }
Garde-fous, tests et limites
-
La boucle locale, une clé, et des modes de permission
Relais n’écoute que la machine, derrière une clé aléatoire, sans CORS ouvert. En lecture seule, l’agent n’a que Read, Glob, Grep et ses questions ; commandes, sous-agents, MCP et hooks du projet sont coupés. En écriture, chaque demande de permission se traite dans la console.
-
Des faux agents pour tout tester sans abonnement
373 tests du serveur en Rust et 54 scripts de vérification, dont des parcours Playwright avec contrôle d’accessibilité. Des faux Claude Code, Codex, navigateur, GitHub et registre npm, déterministes, remplacent les vrais : aucun abonnement consommé. L’intégration continue tourne sous Windows et sous macOS, sur processeurs Apple et Intel.
-
Ses limites, écrites
Le contrôle des permissions n’est pas une isolation du système : l’agent tourne sous mon compte. Les conversations survivent à un redémarrage, pas les processus. Sous Unix, le nettoyage après un arrêt brutal de Relais n’est pas garanti. Un seul utilisateur, sur la machine : l’accès distant demanderait une authentification par appelant, un vrai bac à sable et TLS.
En une phrase
Un seul point d’accès où les agents de ma machine sont lancés, encadrés et relus : Sillage et Karl Scraper y confient les leurs, et tout outil qui a la clé peut en faire autant.
Sources et méthode : chiffres, dates, méthode et crédits
Le projet. Dépôt privé, présenté sans lien. Relu le 14/10/2026 à la révision bdf041f de sa branche de développement : version 0.2.0, 260 commits du 18/09 au 14/10/2026, tous de ma main, et 373 tests du serveur en Rust. Versions fixées par Relais : Claude Code 2.1.281 et Codex 0.157.1.
Chiffres. Les 1 011 décisions de permission, et les 69 refus de lecture et de recherche parmi elles, viennent du registre des correctifs du dépôt : la base de l’instance en service après trois jours, du 21 au 23/09/2026. Les 52 cas et le défaut des liens physiques viennent de l’audit des permissions du 20/09/2026 ; les 69 refus ont été recoupés avec les paramètres des appels, pas rejoués un à un sur la base en service. Le frein des lancements et l’incident du 27/09/2026 viennent de son code et du correctif du 05/10/2026. Le seuil de 95 % et la suppression des conversations après 90 jours sont des valeurs par défaut, réglables.
Captures. Relais 0.2.0 lancé en local le 14/10/2026, avec des données de démonstration : trois abonnements, des projets et des conversations inventés, aucun compte réel. Un agent de démonstration remplace Claude Code : il rejoue des tours écrits à l’avance, sans inférence ni appel réseau. Les décisions de permission, refus compris, sont celles de Relais. Les chiffres des écrans (tokens, coûts, durées, quotas) sont calculés par Relais sur ces données et ne décrivent aucun usage réel. Aucune retouche ; la vignette de la vitrine recadre le panneau de pilotage de la conversation.
Limites. Le mode strict contrôle chaque appel d’outil ; ce n’est pas un bac à sable imposé par le système. Relais n’écoute que la machine locale : l’accès distant et le multi-utilisateur sont hors de son périmètre.
Fonctions et sous le capot. Relus le 15/10/2026 à la même révision : l’architecture, le contrat de l’API, les serveurs MCP par session, la conversation, les diagnostics et le code. Les extraits sont des formes simplifiées, écrites pour cette page. 54 scripts de vérification et les faux agents des tests sont comptés à la même révision.