Un agent unique à qui l'on confie « compare ces trois serveurs d'inférence à partir des 40 documents » lit, lit encore, et chaque tour renvoie au modèle tout ce qu'il a déjà lu. L'invite grossit à chaque tour, le modèle confond la fiche fournisseur de février et le banc d'essai de juillet, et la facture de chaque tour croît avec l'historique. Découper ne règle ce problème que si le découpage est fait proprement : contextes réellement séparés, plafond de dépense par branche, et une étape qui recolle les morceaux sans perdre les désaccords.
Le mécanisme : trois rôles, trois contextes
| Rôle | Ce qu'il voit | Ce qu'il produit | Modèle |
|---|---|---|---|
| Planificateur | la demande + le catalogue (id, date, type de source, titre) | un Plan : sous-tâches, documents attribués, documents écartés | gemini-3.8-flash |
| Sous-agent | sa question + son périmètre de documents, rien d'autre | un Constat : affirmations sourcées, lacunes | gemini-3.5-flash-lite |
| Synthèse | la demande + le dossier de preuves (constats + métadonnées des sources) | une Synthese : contradictions tranchées, dossier Markdown | gemini-3.8-flash |
Le contexte isolé d'un sous-agent se définit par ce qu'il ne reçoit pas : ni la demande globale, ni les questions des autres sous-agents, ni leurs documents. L'isolation n'est pas une phrase dans l'invite, c'est l'outil lire qui refuse un document hors périmètre.
sequenceDiagram
participant O as Orchestrateur
participant P as Planificateur
participant S as Sous-agents (x5)
participant Y as Synthèse
O->>P: demande + catalogue (40 lignes)
P-->>O: Plan (JSON validé)
par une branche par sous-tâche
O->>S: question + périmètre + budget
S-->>O: Constat ou échec
end
O->>Y: dossier de preuves
Y-->>O: contradictions + dossier
O->>O: contrôles (citations, arbitrages)
Le corpus : 40 documents, quatre pièges
Les documents (files/corpus/doc-01.md à doc-40.md) sont fictifs mais construits comme un vrai fonds documentaire : 31 documents utiles sur cinq axes (performances, coûts, sécurité, exploitation, pérennité) et 9 documents d'autres projets (messagerie, habilitations électriques, imprimante du site de Lens). Quatre contradictions sont plantées, chacune avec une bonne réponse défendable :
| # | Version ancienne ou moins fiable | Version à retenir | Règle |
|---|---|---|---|
| C1 | Kestrel : p95 de 120 ms (fiche fournisseur, 5 req/s) | 340 ms (banc d'essai interne, 40 req/s) | mesure interne > fournisseur |
| C2 | Tamaris sous Apache 2.0, gratuit (blog, 2025) | licence TSL, 4 200 € par GPU et par an au-delà de 8 GPU (annonce officielle) | officiel et plus récent |
| C3 | ORV-SA-2026-004 sans correctif (bulletin d'avril) | corrigée en 3.4.2 (notes de version d'août) | plus récent |
| C4 | « Kestrel ne sera plus maintenu après 2026 » (billet anonyme) | fondation, LTS jusqu'en 2029 (annonce officielle) | officiel > rumeur |
Ces pièges servent la grille de qualité de la leçon 5 : un dossier qui recopie 120 ms comme latence de Kestrel est faux, même s'il cite sa source.
Les contrats d'échange
Tout ce qui circule entre les rôles est un modèle pydantic. C'est ce qui permet de valider, de journaliser et de tester sans modèle réel.
class SousTache(BaseModel):
id: str = Field(description="st-1, st-2, ...")
question: str = Field(description="La question précise à instruire, autonome")
doc_ids: list[str] = Field(description="Documents attribués (doc-XX), 8 au maximum")
class Affirmation(BaseModel):
sujet: str = Field(description="Ex. 'Kestrel - latence p95'")
enonce: str = Field(description="Le fait, chiffré si possible")
sources: list[str] = Field(description="doc-XX qui l'établissent")
class Contradiction(BaseModel):
sujet: str
retenu: str
ecarte: str
sources_retenues: list[str]
sources_ecartees: list[str]
regle: strLe dépôt
| Fichier | Rôle | Leçon |
|---|---|---|
| corpus.py | chargement, catalogue, Perimetre (isolation) | 2, 3 |
| planificateur.py | invite et validation du plan | 2 |
| sous_agent.py, budget.py | boucle d'outils, budget | 3 |
| orchestrateur.py, journal.py, rapport.py | parallélisme, reprise, trajectoire | 4 |
| synthese.py, evaluation.py, grille.json | agrégation, contrôles, grille | 5 |
| version_adk.py | la version ADK Workflow | 6 |
| run.py | make run, make e2e | 4, 7 |
Mise en route
cd files
make setup # .venv, dépendances, .env copié depuis .env.example
make test # 21 tests, sans clé ni réseauRenseignez ensuite GOOGLE_API_KEY dans .env pour les leçons suivantes.
Résultat obtenu (2026-10-15)
$ make test
..................... [100%]
21 passed in 5.92sCe qui casse en production
- Découper ce qui n'avait pas besoin de l'être. Symptôme : le dossier coûte deux fois plus cher qu'un agent unique pour une qualité égale. Dans nos mesures (leçon 7), planification et synthèse occupent de 56 à 86 % du temps total. Parade : en dessous de quelques documents par axe, un seul agent avec un bon outil de recherche fait mieux.
- Une contradiction qui traverse deux sous-tâches. Si le bulletin d'avril part chez le sous-agent « sécurité » et les notes de version d'août chez « exploitation », aucun des deux ne voit le conflit. Parade : la consigne du planificateur regroupe les documents qui parlent du même sujet (leçon 2), et la synthèse reçoit les dates et types de source (leçon 5).
- Des sous-agents qui partagent un état mutable. Un dictionnaire partagé où chacun écrit « le dernier chiffre trouvé » ne garde que le dernier écrivain. Parade : chaque sous-agent rend une valeur ; seul l'orchestrateur agrège.
La règle de décision
Utilisez des sous-agents quand la tâche se découpe en axes indépendants, que chaque axe demande plusieurs lectures, et que le contexte d'un agent unique dépasserait ce que le modèle exploite bien. Ne le faites pas pour une question à une seule source, ni quand les axes dépendent les uns des autres en chaîne (un pipeline séquentiel suffit). Surveillez la part du temps et du coût hors sous-agents : si elle domine, le découpage ne paie pas.
Pratique
Un sous-agent « coûts » doit calculer le coût sur 3 ans de Tamaris. Il a besoin du nombre de GPU prévu, qui figure dans un compte rendu de dimensionnement. Où ce document doit-il aller ?
Un sous-agent isolé ne dialogue pas avec ses pairs ni avec le planificateur : tout ce dont il a besoin doit être dans son périmètre au départ. Le contexte partagé ruine l'isolation (et le coût d'entrée de chaque sous-agent). Reporter le calcul à la synthèse est tentant, mais elle ne verra que des constats déjà résumés, sans le chiffre de départ si personne ne l'a lu.
Votre dossier de veille porte sur 3 documents d'une page. Un collègue propose le pipeline planificateur + sous-agents + synthèse « pour être prêt à grandir ». Que répondez-vous ?
Avec trois pages, le contexte d'un agent unique reste petit ; planification et synthèse coûteraient plus que tout le reste. Le parallélisme ne gagne que sur la phase des sous-agents, qui serait ici minuscule. Il n'y a pas de seuil magique à 100 documents : le critère est la taille du contexte et l'indépendance des axes.
Exercice. Ouvrez files/corpus/ et repérez, sans regarder le tableau ci-dessus, un cinquième désaccord entre documents qui n'est pas dans la grille. Décidez quelle version retenir et selon quelle règle.
Voir la solution
Le document doc-29 (note commerciale Tamaris, février) revendique « la meilleure latence du marché » sans protocole ; le banc d'essai interne doc-03 mesure Tamaris à 410 ms au p95, derrière Kestrel (340 ms) et Orvet (290 ms). Règle 1 : une mesure interne au protocole commun l'emporte sur une donnée fournisseur. Autre candidat : doc-07 (fuite mémoire, contournement par redémarrage) contre doc-08 (corrigée en 2.8), qui relève de la règle « le plus récent », avec une nuance : la 2.8 est sous licence payante. Les vrais modèles ont relevé ces deux désaccords lors des exécutions de la leçon 6.
- Je sais dire ce qu'un sous-agent ne doit pas voir, et pourquoi
- Je sais justifier le choix de modèle par rôle
- Je sais reconnaître une tâche qui ne mérite pas de sous-agents
-
make testpasse sur ma machine