Aller au contenu
Sommaire

Sillage Orchestrer des agents IA

Confier un long travail à des agents, sans perdre la main.

Sillage orchestre sur ma machine des agents IA qui écrivent du code. Je décris le travail comme un graphe : qui fait quoi, dans quel ordre, avec quels dossiers et quel livrable. Sillage suit les agents, leur fait corriger une réponse mal formée et reprend le travail après une coupure. Je l’ai conçu et développé seul.

Une exécution en direct, sur un projet de démonstration. Un clic montre l’écran entier.
Besoin
Confier un long travail de développement à plusieurs agents IA sans perdre la main.
Ma part
J’ai conçu et développé seul le serveur en Rust, l’interface Angular et leurs tests.
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é.

Discutons de ce projet

Le principe

Une tâche, c’est un graphe d’agents

Dans Sillage, je décris une tâche comme un graphe. Certains agents ont une place fixe ; d’autres coordonnent et créent leurs sous-agents en cours de route. Chacun reçoit sa mission, ses dossiers et le livrable qu’il doit rendre.

Sillage ne démarre pas lui-même les sessions des agents : il les confie à Relais, mon point d’accès local aux agents, par son API. Karl Scraper y pousse aussi ses plans, pour qu’un agent en compose les tâches.

La page d’un projet rassemble ses tâches et ce qui tourne : ici, un assistant compose une tâche pendant qu’une autre s’exécute.

La page d’un projet : une tâche en composition, une en cours, une interrompue, une terminée.
La page d’un projet : une tâche en composition, une en cours, une interrompue, une terminée.

Composer une tâche

Un agent compose la tâche, Sillage la vérifie

Je peux dessiner le graphe à la main, ou décrire ce que je veux à un assistant. Il compose alors la tâche par les outils que Sillage lui ouvre (MCP), un agent par appel, dans un brouillon que je vois se remplir.

Chaque ajout passe par les validations de Sillage. Ici, la relecture arrive avant l’équipe dont elle dépend : elle est refusée. L’assistant ajoute l’équipe, puis la relecture. Pour cette demande, il ne lit que le projet et ne lance rien sans moi.

L’assistant de création compose une tâche dans Sillage : un agent est refusé parce que sa dépendance n’existe pas encore, puis ajouté dans le bon ordre.
Une relecture refusée : elle dépend d’une équipe pas encore ajoutée.

Reprendre après une coupure

Une coupure ne fait pas tout recommencer

Une exécution peut s’arrêter en route : un redémarrage du serveur, une coupure. Sillage propose alors de la reprendre là où elle en était.

Les agents qui avaient fini gardent leur résultat. Celui qui travaillait reprend sa session, encore ouverte chez Relais, sans en ouvrir une nouvelle ; les étapes suivantes repartent ensuite. Si j’ajoute des consignes de reprise, il repart dans une nouvelle session qui les reçoit.

« Construire l’index » reprend sa session ; « Analyser la recherche » garde son résultat.
« Construire l’index » reprend sa session ; « Analyser la recherche » garde son résultat.

Le résultat

À la fin, je sais où est le résultat

Quand l’exécution se termine, le récapitulatif dit où se trouve le résultat final : le dossier, la branche, le commit. Il dit aussi ce que sont devenus les worktrees, les copies de travail Git où chaque agent a écrit : ceux qui restent à fusionner, ceux qui ont été supprimés.

Puis, agent par agent, ce qu’il a rendu : un résumé, ses décisions, ses contrôles et la suite qu’il propose. C’est le résultat court que chaque agent doit tenir, et ce que reçoivent les agents qui le suivent.

Le résultat final, les worktrees, puis ce que chaque agent a rendu. Un clic montre le panneau entier.
Le résultat final : le dossier, la branche, le commit.

Toutes ses fonctions, une ligne chacune

Du projet au résultat : un clic déplie chaque fonction.

  1. Des projets, et les dossiers qu’ils confient

    Un projet donne ses permissions globales : les dossiers en lecture et en écriture que recevront toutes ses tâches, choisis avec le sélecteur du système. Une tâche peut ajouter ses propres dossiers, jamais en retirer, et ils ne changent pas pendant qu’elle s’exécute.

  2. Composer un graphe d’agents

    Chaque agent a sa mission, ses ressources, son livrable, son modèle et son effort. Un agent déterministe garde une place fixe ; un agent dynamique répartit son travail entre des sous-agents qu’il crée en cours de route. Les liaisons vont d’une sortie à une entrée, et les cycles sont refusés. Un contexte commun et une méthode de travail s’ajoutent au message de chaque agent.

  3. Estimer la durée avant de lancer

    À chaque agent, effort ou liaison changé, l’éditeur rejoue le graphe avec la session typique de chaque modèle et de chaque effort, tirée des exécutions passées, sous les limites de parallélisme : une durée typique et sa fourchette.

  4. Créer ou planifier avec un agent

    Un assistant compose la tâche par les outils MCP que Sillage lui ouvre, un agent par appel, dans un brouillon visible en direct. Un autre écrit un plan dans le dépôt du projet ; plan, création et exécution peuvent s’enchaîner sans moi.

  5. Suivre une exécution en direct

    Le graphe montre les agents actifs et les sous-agents dès leur création, avec leur consommation. Le suivi distingue les sessions, les attentes datées et leurs causes ; le journal des erreurs réunit ce qui a échoué ; les échanges montrent, dans l’ordre, le message exact reçu par chaque agent et sa réponse.

  6. Donner un navigateur aux agents

    Un agent dont la mission parle de navigateur reçoit un Chromium sans interface, à lui seul, par les outils de Playwright MCP : il ouvre les pages du projet, clique, saisit et capture l’écran. Les retours visuels montrent l’exécution en images, étape par étape.

  7. Reprendre, relancer, restaurer

    Après une coupure, un arrêt ou un échec, la reprise relance les étapes non abouties et se rattache aux sessions restées actives chez Relais. « Relancer depuis cet agent » repart de n’importe quelle étape ; « Voir ce qui a changé » compare la tâche à son exécution, et une définition exécutée se restaure.

  8. Retrouver le résultat et l’historique

    Le récapitulatif désigne le résultat final, worktree, branche et commit, puis ce que chaque agent a fait, et se copie en Markdown pour une pull request. Les exécutions se comparent et se regroupent en sprint ; l’historique du projet donne la durée, les tokens et l’équivalent API de chaque action.

  9. Un assistant pour chaque projet

    Une conversation gardée par projet : il répond sur le projet, ses tâches et ses exécutions, et ses actions s’affichent en cartes, une idée notée, un fait retenu, un plan ou une exécution lancés.

  10. Garder la machine éveillée, nettoyer derrière

    Tant qu’un agent travaille, Sillage empêche la mise en veille et le dit. À la fin d’une exécution aboutie, il supprime les worktrees propres et fusionnés, jamais les branches ; un panneau liste les autres, avec ce qui les retient.

Sous le capot

L’architecture, puis quatre choix nés d’un problème relevé, et ce qui les tient. Le code est privé : les extraits sont des formes simplifiées, écrites pour cette page.

Architecture

  1. Un serveur Rust, une interface Angular, un flux SSE aperçu

    Le serveur, en Rust (Axum et Tokio), garde l’état en mémoire et le persiste dans un SQLite embarqué. Il n’écoute que la boucle locale : toutes les routes de l’API demandent un jeton, et les en-têtes Host et Origin doivent être locaux. L’interface Angular reçoit l’état par un flux SSE, un instantané après chaque modification enregistrée, quatre envois par seconde au plus.

    Schéma, forme simplifiée écrite pour cette page : le code est privé
    interface Angular 22
     ↓ HTTP + jeton
     ↑ SSE : l’état,
       ≤ 4 envois par seconde
    serveur Rust (Axum, Tokio)
    ├▶ SQLite embarqué
    ├▶ Relais, par HTTP + jeton
    └▶ assistants, par outils MCP
       (création, plan)
    agents ◀ Playwright MCP :
       un navigateur chacun
  2. Un coordinateur planifie, le serveur vérifie

    Un agent dynamique inventorie les unités de travail de sa mission et les répartit entre le plus petit nombre de sous-agents utile. Avant d’en lancer un seul, le serveur contrôle le plafond, la couverture des unités, les champs délégués et les couples modèle et effort autorisés ; un plan refusé revient au coordinateur, dans la même session, deux fois au plus. Un sous-agent perdu rend le groupe partiel, sans perdre le travail des autres.

  3. Une session ne part jamais deux fois aperçu

    Chaque demande de session à Relais porte un identifiant choisi par Sillage. Si la réponse se perd, Sillage renvoie la même demande, et Relais rend la session déjà créée au lieu d’en lancer une seconde.

    HTTP, forme simplifiée écrite pour cette page : le code est privé
    POST /api/sessions                      (chez Relais)
    { "client_session_id": "<UUID v4>", "application_name": "Sillage",
      "model": "…", "effort": "…", "workspace": "…", "ttl_seconds": … }
    
    → 201  la première fois
    → 200  la même session, quand la demande est rejouée à l’identique
    → 409  le même identifiant pour une autre demande

Décisions

  1. Un résultat court, corrigé dans la même session aperçu
    Contrainte
    Les agents rendent de 10 000 à 27 000 caractères, quelle que soit la cible qu’on leur annonce, et une seule réponse mal formée peut casser la chaîne.
    Choix
    Chaque agent rend un résultat court et structuré : résumé, décisions, contrôles, blocages, suite. Une réponse hors du format attendu lui revient dans la même session, avec l’erreur, deux fois au plus.
    Effet
    Les agents suivants reçoivent des faits et des références, pas des conversations entières ; un blocage arrête la suite.
    Le récapitulatif
    JSON, forme simplifiée écrite pour cette page : le code est privé
    {
      "outcome": "partial",
      "summary": "Interfaces examinées ; raccordement restant.",
      "decisions": [],
      "checks": [{ "kind": "runtime_test", "status": "not_run" }],
      "blockers": [],
      "next_action": "Effectuer les essais dans le navigateur."
    }
  2. Sillage crée lui-même le worktree de l’agent
    Contrainte
    Des agents en parallèle dans un même dossier se gênaient : 26 commandes Git bloquées sur un verrou, des commits réécrits par un autre agent. Enfermés dans leur bac à sable, d’autres agents ne pouvaient ni committer, ni ouvrir un navigateur, ni joindre le réseau : 39 blocages en trois exécutions.
    Choix
    Quand un agent en a besoin (sa mission le demande, ou un autre agent écrit en même temps dans le même dossier), Sillage crée lui-même son worktree avant sa première session, le garde pour les suivantes, committe pour l’agent si besoin, puis fusionne.
    Effet
    Le même mécanisme committe pour les agents enfermés et sépare ceux qui écrivent en parallèle. Seuls les worktrees propres et fusionnés sont nettoyés, jamais les branches.
  3. Une fenêtre de compaction pour chaque session aperçu
    Contrainte
    À chaque appel, toute la conversation de l’agent était relue : 2,19 milliards de tokens, les unités de texte que lit le modèle, sur 79 sessions de trois tâches, et rien ne bornait une session.
    Choix
    Chaque session demande à Relais une fenêtre de compaction, de 300 000 tokens par défaut, réglable ou désactivable : au-delà, sa conversation est résumée.
    Effet
    Une session est résumée vers 270 000 tokens au lieu de grossir jusqu’à la limite du modèle.
    JSON annoté, forme simplifiée écrite pour cette page : le code est privé
    // Demande de session à Relais, réglage par défaut
    { "autocompact_tokens": 300000 }
  4. Relais n’expose que des capacités génériques aperçu
    Contrainte
    Des notions propres à Sillage étaient entrées dans Relais, et Sillage allait lire le jeton de Relais dans son dossier : trois lectures dans le code exécuté.
    Choix
    Relais n’expose que des capacités génériques. Sillage garde son schéma de création de tâche et ses validations, et reçoit le jeton par ses paramètres.
    Effet
    Plus aucune lecture du dossier voisin : deux applications qui s’installent séparément, et un point d’accès que d’autres outils utilisent.
    Relais
    JSON annoté, forme simplifiée écrite pour cette page : le code est privé
    // GET /api/status chez Relais : les capacités dont Sillage se sert
    { "capabilities": {
        "working_context": true, "filesystem_scope": true,
        "idempotent_session_creation": true, "mcp_http": true, "mcp_http_auto": true } }

Garde-fous, tests et limites

  1. Des consignes et des contrôles, pas une isolation

    Une tâche qui écrit donne aux agents un terminal, dont chaque commande passe par le classificateur de l’agent ; une tâche sans dossier d’écriture reste en lecture seule stricte, chaque lecture contrôlée par Relais. Les sous-agents héritent des permissions sans pouvoir les élargir. Aucun de ces modes n’isole le système des autres processus de la machine : c’est écrit.

  2. Une panne du fournisseur ne fait pas échouer l’agent

    Sur une erreur temporaire de l’API (529, 5xx), l’agent attend 30 s, puis le double, sans dépasser 240 s par défaut, et reprend dans la même session si elle le permet. Une authentification expirée ou un quota atteint met ses agents en attente : l’exécution repart seule à la reconnexion ou à la réinitialisation.

  3. 643 tests du serveur, et des parcours complets

    643 tests en Rust, 206 tests des scripts, 22 parcours d’interface Playwright et 14 scénarios de bout en bout, tous contre un faux fournisseur : aucun abonnement consommé. L’intégration continue les joue sous Windows et sous macOS, sur processeurs Apple et Intel.

Aujourd’hui

Neuf exécutions réelles en huit jours, 579 agents lancés, 63 500 appels d’outils, sept blocages durs relevés puis traités : Sillage tourne sur ma machine, avec Relais.

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 c256e76 du 13/10/2026 : un serveur en Rust (Axum, Tokio, SQLite embarqué) et une interface Angular 22, testés en intégration continue sous Windows et macOS, sur processeurs Apple et Intel. 783 commits d’un seul auteur, du 19/09 au 13/10/2026.

Chiffres. Les 579 agents et les 63 500 appels d’outils, dont 1 004 en échec, viennent du registre des blocages du dépôt (révision 9b4533a du 05/10/2026), qui en tire sept blocages durs ; il couvre neuf exécutions réelles, du 26/09 au 03/10/2026. Les 643 tests du serveur sont comptés dans son code à la révision c256e76 ; avec 206 tests Node, 22 parcours d’interface et 14 scénarios de bout en bout, aucun ne consomme d’abonnement : ceux qui parlent à un fournisseur passent par un fournisseur simulé.

Décisions. Les 10 000 à 27 000 caractères que rendent les agents, quelle que soit la cible annoncée, viennent des contrats de contexte (révision 480e358) ; les 26 commandes Git bloquées et les 39 blocages dus au bac à sable des agents, du registre des blocages ; les 2,19 milliards de tokens relus sur 79 sessions, de la mesure qui a motivé la fenêtre de compaction (révision ae2efd8 du 12/10/2026) ; le découplage de Relais et ses trois lectures du dossier voisin, du rapport d’architecture (révision ed4080b). Les deux corrections au plus, la fenêtre de 300 000 tokens et les cas où Sillage crée le worktree d’un agent sont lus dans le code.

Écrans. L’application lancée en local à la révision c256e76, contre le faux fournisseur des tests du dépôt, sur des projets, des tâches et des résultats de démonstration : aucun abonnement, aucune donnée ni tâche réelle. Les vues de téléphone sont capturées à 390 px de large. Leurs durées et leurs commits ne mesurent rien.

Fonctions et sous le capot. Relus le 15/10/2026 à la même révision : la documentation, le contrat de l’API, les contrats des agents et le code. Les extraits sont des formes simplifiées, écrites pour cette page. Tests comptés dans le code : 643 en Rust, 206 pour les scripts, 22 parcours d’interface et 14 scénarios de bout en bout.