Orchestrer des agents spécialisés : choisir, synthétiser, montrer ce qui se passe

Un agent avec quarante outils finit par se tromper d'outil. Plusieurs agents spécialisés derrière un orchestrateur tiennent mieux, à quatre conditions : choisir avant d'appeler, recevoir des constats structurés, savoir dire « je ne sais pas » et afficher un état réel. Ce que j'en ai retenu en construisant Chimera.

La première version d'un agent, c'est un modèle avec une poignée d'outils, et ça marche. Vers le dixième outil, ça se dégrade : le modèle choisit moins bien ses outils, le contexte se remplit de schémas qui ne servent pas pour la question posée, et quand la réponse est fausse, impossible de savoir quelle partie a échoué.

L'étape suivante, en général, c'est un ensemble d'agents étroits, chacun bon dans son domaine, derrière un orchestrateur. C'est ce que j'ai fait avec Chimera, le super-agent de mon projet Quant. La direction est bonne, et elle amène quatre problèmes qu'il vaut mieux connaître avant de construire.

La boucle

Boucle d'orchestration — une requête est dirigée vers une partie des agents, leurs constats structurés sont rassemblés, et une synthèse produit la réponse ou s'abstientrequêteune questionsélectionquels agentspeuvent savoir ?agent Aagent Bagent Cagent D · ignorésynthèselit des constatspas la sortieréponseou ⊘
Figure 1. La sélection se fait avant l'appel. L'agent D n'est pas sollicité, et c'est voulu : le coût d'un orchestrateur dépend du nombre d'agents qu'il réveille, et la réponse se dégrade à mesure que des constats hors sujet s'accumulent.

1. Choisir avant d'appeler

L'orchestrateur naïf interroge tous les agents et laisse la synthèse faire le tri. C'est simple, et ça coince sur trois points à la fois : la latence est celle de l'agent le plus lent, le coût est la somme de tous les agents, et la qualité de la réponse baisse à mesure que des constats hors sujet noient les bons.

La sélection peut se passer de modèle. Dans la plupart des systèmes, la question contient assez de signal (les entités qu'elle cite, son vocabulaire, l'écran d'où elle vient) pour un classifieur léger ou quelques règles explicites. Dans Chimera, la sélection se fait par domaine, intention et mots-clés, sans appel au LLM. Si un modèle est vraiment utile à cette étape, je lui fais renvoyer une liste courte et ordonnée, pour que l'orchestrateur applique lui-même son budget.

Deux propriétés à prévoir dès le départ.

Une sélection qu'on peut relire. Je journalise les agents envisagés, ceux qui ont été retenus, et pourquoi. « L'orchestrateur n'a pas interrogé l'agent qui avait la réponse » est un échec fréquent, et sans ce journal il est impossible à diagnostiquer.

Une sélection qu'on peut forcer. Un appelant qui sait quel agent il veut doit pouvoir le demander. Le routage reste une heuristique, et une heuristique a besoin d'une porte de sortie.

L'intuition mathématique : le plus lent décide

Quand on interroge n agents en parallèle, la réponse n'arrive que lorsque le plus lent a répondu : la latence de l'orchestrateur est un maximum. Le coût, lui, est une somme : chaque agent appelé se paie.

Le maximum a une propriété désagréable. Supposons que chaque agent soit lent une fois sur 20, c'est-à-dire qu'il dépasse son p95 dans 5 % des cas, indépendamment des autres. Pour que la réponse soit rapide, il faut qu'aucun agent ne soit lent, ce qui arrive avec une probabilité de 0,95 × 0,95 × … , soit 0,95^n. D'où :

P(au moins un agent lent) = 1 − 0,95^n

Animation. 12 agents interrogés en parallèle : la réponse attend le plus lent (pointillés or). À droite, la probabilité qu'au moins un agent soit lent quand chacun l'est 1 fois sur 20. En n'en sélectionnant que 3, elle tombe de 46 % à 14 %.

Avec 3 agents, une réponse sur 7 attend un agent lent (14 %). Avec 12 agents, presque une sur deux (46 %). À 12 agents, le p95 de chaque agent devient quelque chose qui arrive tout le temps. Choisir avant d'appeler réduit donc la facture, qui est une somme, et la latence ressentie, qui est un maximum. Le parallélisme borné et un délai d'expiration par agent servent ensuite à couper ce qui reste de traîne.

2. Des constats structurés en sortie des agents

La décision qui fait tenir l'architecture : un agent renvoie un constat structuré. Un paragraphe de texte libre est inexploitable pour la synthèse.

from dataclasses import dataclass
from typing import Literal

@dataclass(frozen=True)
class Finding:
    agent: str                     # qui l&#class="tok-num">39;a produit
    kind: Literal["fact", "anomaly", "absence"]
    statement: str                 # une seule affirmation, en langage naturel
    confidence: float              # class="tok-num">0..class="tok-num">1, calibrée par l&#class="tok-num">39;agent lui-même
    evidence: list[str]            # identifiants qu&#class="tok-num">39;on peut résoudre vers une source
    computed_at: str               # ISO-class="tok-num">8601 — la synthèse a besoin de l&#class="tok-num">39;âge
    inputs_digest: str             # ce que l&#class="tok-num">39;agent a regardé, pour reproduire

Chaque champ a une raison d'être.

kind="absence" est un vrai résultat. « J'ai cherché et il n'y a rien » est une information différente de « on ne m'a rien demandé » et de « j'ai planté ». Sans cette distinction, la synthèse ne sait pas séparer le silence d'une réponse négative, et elle devine.

evidence contient des identifiants. Un identifiant se résout, se vérifie et se montre à l'utilisateur. Une citation recopiée dans le constat n'est qu'une affirmation sur la source, et elle survit même quand la source est corrigée.

confidence vient de l'agent. La confiance qu'un modèle s'attribue à lui-même ne veut presque rien dire. Une confiance calculée par la logique de l'agent (combien de lignes concordent, un seuil franchi ou non, quelle part de données manquait) est exploitable. Quand un agent n'a aucun moyen de se calibrer, je préfère laisser le champ vide qu'inventer un chiffre.

3. La synthèse est un travail à part entière

Concaténer les constats ou demander au modèle de « résumer tout ça » ne suffit pas. La synthèse a ses propres façons d'échouer.

Les constats contradictoires se montrent. Deux agents en désaccord, c'est de l'information, souvent la plus utile de toute l'exécution. Un orchestrateur qui garde discrètement le constat le plus confiant la détruit.

L'âge se transmet. Un constat calculé il y a six heures et un autre calculé il y a trente secondes n'ont pas le même poids, et l'utilisateur doit voir l'âge de ce qu'on lui dit.

L'abstention reste possible. Si les agents choisis n'ont rien renvoyé d'exploitable, la bonne réponse est « je ne sais pas, voici ce que j'ai regardé », avec la liste. C'est le comportement le plus dur à garder, parce que n'importe quelle réponse fluide fait meilleure impression en démo.

Le prompt de synthèse ne doit pas inventer de preuves. Je l'ancre strictement sur les constats transmis, puis je vérifie que chaque identifiant cité figurait bien en entrée. Ce contrôle tient en quelques lignes et attrape l'erreur qui détruit la confiance le plus vite.

Dans Chimera, j'ai aussi prévu le cas où le LLM est hors ligne : l'orchestrateur renvoie quand même les constats réels des agents, avec un indicateur qui dit que la synthèse n'a pas pu être faite.

4. La fraîcheur, et quand relancer un agent

Les agents produisent leurs constats selon un calendrier, et une question arrive n'importe quand. L'orchestrateur doit donc décider, agent par agent, si le constat existant est encore valable ou s'il faut relancer l'agent.

La règle que j'applique : un budget de fraîcheur par agent, fixé d'après la vitesse à laquelle ses données sources changent vraiment. Ce qui vient d'un traitement nocturne a un budget d'une journée, ce qui vient d'un flux en direct, de quelques minutes. Une valeur globale par défaut ne convient à personne.

C'est en relançant des agents qu'un orchestrateur devient dangereux. Je l'encadre donc explicitement :

  • Sur demande. Répondre avec des données datées, en le disant, est plus sûr que lancer un calcul que personne n'a demandé.
  • Borné. Un plafond strict d'agents relançables par question. Dans Chimera, c'est 5. Sans plafond, une requête peut se transformer en une charge que personne n'a dimensionnée.
  • Asynchrone. L'utilisateur reçoit tout de suite la réponse, marquée comme datée, et le rafraîchissement servira à la question suivante.
  • Autorisé. Déclencher du calcul est une action privilégiée. Chez moi, c'est réservé à l'admin et désactivé par défaut.

5. Rendre l'état lisible

Un système qui réveille plusieurs agents, en attend certains, en saute d'autres et refuse parfois de répondre est opaque vu de l'extérieur. Deux secondes de silence puis un paragraphe : l'utilisateur ne sait pas si le système réfléchit, s'il est bloqué ou s'il n'avait rien.

Un affichage d'état en direct a sa place ici : un indicateur de progression, une ligne d'état, une animation liée à ce que fait le système. Dans Chimera, c'est un orbe 3D qui change selon l'état (travail, réflexion, anomalie, restitution). La forme compte moins que la règle d'ingénierie derrière.

Je n'affiche jamais un état que je ne mesure pas. Un indicateur piloté par une minuterie est une décoration qui ment sous charge, au moment où l'utilisateur a le plus besoin de savoir ce qui se passe. Si un état ne peut pas être observé, il n'apparaît pas.

Dégradé et hors ligne sont aussi des états. L'affichage doit savoir montrer « un agent est injoignable » et « réponse construite avec des données partielles ». Quand Chimera tourne sur son repli local, un bandeau DÉMO le dit clairement. Une visualisation qui sait seulement avoir l'air d'aller bien transforme une panne en confusion.

Ce que ça coûte

Cette architecture a un prix, et il est prévisible :

  • Plus de pièces à faire tourner. Chaque agent, c'est un déploiement, un calendrier, une façon d'échouer et une permission.
  • Les erreurs de sélection deviennent les plus fréquentes. Dans un système qui a vécu, une mauvaise réponse vient plus souvent de « on a interrogé les mauvais agents » que de « l'agent s'est trompé ». D'où l'obligation de journaliser la sélection.
  • La latence est celle de l'agent le plus lent parmi ceux choisis. Parallélisme borné et délais d'expiration par agent sont indispensables.
  • Les constats ont besoin de versions. Un changement de schéma sur un type de constat se propage jusqu'à la synthèse et à tout ce qui en a stocké.

Ça vaut le coup quand les domaines sont vraiment distincts, et que chacun demande ses propres outils, son propre accès aux données et ses propres droits. Avec trois outils et une seule source de données, un agent unique reste la bonne réponse.