Orchestration multi-agents
Faire travailler dix agents en parallèle, c'est spectaculaire. C'est aussi environ quinze fois plus cher. Voici quand ça vaut le coup.
Temps de lecture : 16 min | Niveau : Avancé
Ce que tu sauras faire après
- Reconnaître les cinq patrons d'orchestration et choisir le bon.
- Monter un fan-out puis une synthèse sur 30 modèles dbt.
- Mettre en place une vérification adversariale pour filtrer les faux positifs.
- Utiliser un panel de juges quand il n'y a pas de bonne réponse unique.
- Chiffrer le surcoût du multi-agents et dire non quand il ne se justifie pas.
1. Les cinq patrons, du plus simple au plus libre
Anthropic décrit cinq patrons. Les trois premiers sont des workflows (ton code tient le plan), les deux derniers laissent la main au modèle.
Patron 1 — Prompt chaining (enchaînement)
Découper une tâche en étapes fixes, la sortie de l'une alimente la suivante.
Utile « when the task can be easily and cleanly decomposed into fixed subtasks » pour « trade off latency for higher accuracy ».
Schema de la table -> Generation du SQL -> Verification syntaxique -> Explication metierQuand : tu connais les étapes d'avance et elles sont toujours les mêmes.
Patron 2 — Routing (aiguillage)
Classer l'entrée, puis l'envoyer vers un traitement spécialisé.
« Classifies an input and directs it to a specialized followup task », ce qui permet « separation of concerns, and building more specialized prompts ».
Ticket data entrant
|-- "les chiffres sont faux" -> agent audit-qualite-donnees
|-- "c'est trop lent" -> agent optimisation-requetes
|-- "je n'ai pas acces" -> agent droits-et-permissionsQuand : tes entrées sont hétérogènes et un prompt unique fait des compromis médiocres.
Patron 3 — Parallelization (parallélisation)
Deux variantes d'après Anthropic :
| Variante | Principe | Exemple data |
|---|---|---|
| Sectioning | Découper en sous-tâches indépendantes lancées en même temps | Auditer 30 modèles dbt, un agent par modèle |
| Voting | Lancer la même tâche plusieurs fois et comparer | Faire estimer trois fois le risque d'une migration, garder le consensus |
Utile « when multiple perspectives or attempts are needed for higher confidence ».
Quand : les sous-tâches ne dépendent pas les unes des autres. C'est le cas le plus fréquent en data.
Patron 4 — Orchestrator-workers (chef d'orchestre et ouvriers)
« A central LLM dynamically breaks down tasks, delegates them to worker LLMs, and synthesizes their results. »
Différence clé avec le patron 3 : le découpage n'est pas connu d'avance. Le chef d'orchestre le décide en lisant le problème.
ORCHESTRATEUR
(lit, decoupe, delegue, synthetise)
|
+----------------+----------------+
| | |
Worker 1 Worker 2 Worker 3
stg_commandes int_marges mart_ca_mensuel
| | |
+----------------+----------------+
|
SYNTHESEQuand : tu ne sais pas combien de sous-tâches il y aura. Une migration de dépôt, un audit de code, une enquête.
Patron 5 — Evaluator-optimizer (générateur et critique)
« One LLM call generates a response while another provides evaluation and feedback in a loop. »
Particulièrement efficace quand il existe des « clear evaluation criteria ».
Generateur : ecrit la requete
|
v
Critique : "le plan d'execution fait un seq scan de 12M lignes"
|
v
Generateur : ajoute un filtre de date et un index
|
v
Critique : "OK, cout estime divise par 40" -> on sort de la boucleQuand : tu as un critère mesurable (coût d'exécution, tests qui passent, taille de sortie).
2. Le fan-out puis synthèse : le patron qui sert le plus en data
C'est le patron 3 (sectioning) suivi d'une agrégation. Trois phases.
PHASE 1 - DECOUVERTE (1 agent)
Lister les 30 fichiers models/**/*.sql
PHASE 2 - FAN-OUT (30 agents en parallele)
Chaque agent audite UN fichier. Contexte isole.
Sortie structuree imposee.
PHASE 3 - SYNTHESE (1 agent)
Reçoit les 30 rapports, deduplique, classe par gravite,
rend UN rapport unique.Pourquoi c'est efficace
| Raison | Détail |
|---|---|
| Temps | La durée totale est celle du plus lent, pas la somme des 30 |
| Contexte | Aucun des 30 fichiers n'entre dans ta conversation principale |
| Qualité | Chaque agent voit un seul fichier : il ne se disperse pas |
Anthropic a mesuré l'effet sur son système de recherche : faire lancer « 3-5 subagents in parallel rather than serially », combiné à des appels d'outils parallèles, a permis de « cut research time by up to 90% for complex queries ».
La règle d'or du fan-out
C'est le point sur lequel Anthropic est le plus insistant. Chaque sous-agent a besoin de :
« an objective, an output format, guidance on the tools and sources to use, and clear task boundaries »
Sans ça, les agents se marchent dessus. Anthropic est direct : « Without detailed task descriptions, agents duplicate work, leave gaps, or fail to find necessary information. » Une consigne vague du type « research the semiconductor shortage » suffit à produire exactement ça.
En clair : tu ne dis pas « audite ce modèle ». Tu dis exactement quoi chercher, avec quels outils, et sous quel format.
Template de prompt pour un worker de fan-out
OBJECTIF
Auditer UNIQUEMENT le fichier [CHEMIN_DU_FICHIER]. Rien d'autre.
PERIMETRE
- Tu peux lire ce fichier et ses dependances directes ([ref() / source()]).
- Tu ne lis AUCUN autre modele.
- Tu ne modifies rien.
CE QUE TU CHERCHES (et rien d'autre)
1. [CRITERE_1 : ex. jointure 1-N non agregee]
2. [CRITERE_2 : ex. absence de filtre de date]
3. [CRITERE_3 : ex. colonne sans test dbt]
FORMAT DE SORTIE (JSON strict, rien avant, rien apres)
{
"fichier": "[CHEMIN]",
"verdict": "ok | a_corriger | bloquant",
"problemes": [
{"critere": "[NUMERO]", "ligne": [N], "gravite": "bloquant|important|mineur",
"description": "[UNE_PHRASE]", "correction": "[SQL_CORRIGE]"}
],
"non_verifiable": ["[CE_QUE_TU_N_AS_PAS_PU_CONTROLER]"]
}
LIMITE
Maximum [N] problemes. Garde les plus graves.Le champ non_verifiable est important : il évite que l'agent invente pour remplir le format.
Template de prompt pour l'agent de synthèse
OBJECTIF
Tu recois [N] rapports d'audit au format JSON. Produis UN rapport unique.
CE QUE TU FAIS
1. Deduplique : le meme probleme trouve dans plusieurs fichiers devient
UNE entree avec la liste des fichiers concernes.
2. Classe par gravite, puis par nombre de fichiers touches.
3. Identifie les PATRONS : un probleme present dans plus de
[SEUIL] fichiers est un probleme de convention, pas un bug isole.
4. Ne recopie pas les rapports. Synthetise.
CE QUE TU NE FAIS PAS
- Tu n'ajoutes aucun probleme qui n'est pas dans les rapports recus.
- Tu ne juges pas la qualite des rapports.
FORMAT DE SORTIE
## Vue d'ensemble
[N] fichiers audites, [N] bloquants, [N] importants, [N] mineurs.
## Problemes de convention (a traiter en priorite)
| Probleme | Fichiers touches | Correction type |
## Bloquants fichier par fichier
| Fichier | Ligne | Probleme | Correction |
## Zones d'ombre
Ce que les agents n'ont pas pu verifier.3. Lancer un fan-out dans Claude Code
Deux voies selon l'échelle.
Voie A — Délégation turn-by-turn (quelques agents)
Tu demandes, Claude lance des sous-agents, et plusieurs peuvent tourner en même temps. Dans une session interactive, ils travaillent en arrière-plan : ta session reste disponible pendant ce temps. En mode non interactif (claude -p) et dans le SDK, Claude les lance en arrière-plan aussi, sauf quand il a besoin du résultat pour continuer son tour.
Lance un sous-agent auditeur-sql par fichier dans models/marts/.
Chaque agent audite un seul fichier et me rend le JSON du format impose.
Puis synthetise les resultats en un rapport unique classe par gravite.Limites par défaut documentées, réglables par variables d'environnement :
| Limite | Variable | Défaut |
|---|---|---|
| Profondeur d'imbrication | CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH | 3 niveaux |
| Sous-agents simultanés | CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS | 20 |
Voie B — Dynamic workflows (dizaines à centaines d'agents)
Pour les gros volumes, Claude Code propose les dynamic workflows : Claude écrit un script JavaScript que le runtime exécute en arrière-plan.
« A dynamic workflow is a JavaScript script that orchestrates many subagents at once. Claude writes the script for the task you describe, and a runtime executes it in the background while your session stays responsive. »
La différence fondamentale, telle que la documentation la formule : « A workflow moves the plan into code. [...] A workflow script holds the loop, the branching, and the intermediate results itself, so Claude's context holds only the final answer. »
Tableau de comparaison tiré de la documentation officielle :
| Sous-agents | Workflows | |
|---|---|---|
| Qui décide de la suite | Claude, tour par tour | Le script |
| Où vivent les résultats intermédiaires | Le contexte de Claude | Des variables du script |
| Ce qui est rejouable | La définition du worker | L'orchestration elle-même |
| Échelle | Quelques tâches par tour | Des dizaines à des centaines d'agents par exécution |
Pour déclencher, tu écris ta demande en langage naturel :
use a workflow to audit every route handler under src/routes/ for missing
authentication checks, and adversarially verify each finding before reporting itLe mot-clé ultracode dans ton prompt déclenche la même chose pour une seule demande. Pendant l'exécution, la commande /workflows ouvre la vue de progression : phases, nombre d'agents, tokens consommés. La touche p met en pause, x arrête, et s enregistre le script comme commande réutilisable dans .claude/workflows/.
Le squelette de script que Claude produit, d'après la documentation :
export const meta = {
name: 'audit-routes',
description: 'Audit every route handler for missing auth checks',
}
const found = await agent('List every .ts file under src/routes/.', {
schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
})
const audits = await pipeline(found.files, file =>
agent(`Audit ${file} for missing authentication checks.`, { label: file }),
)
return audits.filter(Boolean)Trois fonctions à connaître : agent() lance un sous-agent, pipeline() en lance un par élément d'une liste, parallel() lance un ensemble de tâches en même temps. Deux autres servent à l'affichage : phase() regroupe les agents sous un titre dans la vue de progression, log() écrit un message. Un agent() arrêté en cours de route renvoie null : c'est la raison du .filter(Boolean) à la fin de l'exemple.
Limites documentées du runtime :
| Contrainte | Valeur par défaut |
|---|---|
| Agents simultanés | 16, moins si la machine a peu de CPU. Réglable de 1 à 256 avec CLAUDE_CODE_WORKFLOW_MAX_CONCURRENT_AGENTS |
Éléments dans un parallel() ou pipeline() | 4 096 maximum |
| Agents au total par exécution | 1 000 |
| Avertissement « Large workflow » | Au-delà de 25 agents ou 1,5 million de tokens projetés |
4. La vérification adversariale
Le problème du fan-out : les faux positifs. Trente agents qui cherchent des problèmes vont en trouver, y compris là où il n'y en a pas.
La solution : un second agent dont le travail est de démolir chaque trouvaille.
Agent A (chercheur) -> "ligne 42 : jointure 1-N non agregee, le CA est double"
|
v
Agent B (avocat de la defense, contexte NEUF)
"Ouvre le fichier. Essaie de prouver que cette trouvaille est FAUSSE.
Tu as reussi si tu trouves pourquoi ce n'est pas un probleme."
|
+---------------------+---------------------+
| |
B echoue a refuter B refute
-> la trouvaille est confirmee -> on jette la trouvailleLa documentation de Claude Code décrit exactement ce mécanisme pour /deep-research : le rapport final arrive « with claims that didn't survive cross-checking already filtered out ». Et un détail honnête et important :
« When the verifier agents can't check a claim, such as after a rate limit or API error, the report lists that claim as unverified instead of counting it as refuted. »
Retiens la nuance : « non vérifié » n'est pas « faux ». Reproduis cette distinction dans tes propres prompts.
Template de vérificateur adversarial
ROLE
Tu es l'avocat de la defense. Une trouvaille a ete signalee.
Ton travail n'est pas de la confirmer : c'est d'essayer de la DEMOLIR.
TROUVAILLE A EXAMINER
Fichier : [CHEMIN]
Ligne : [NUMERO]
Affirmation : [TEXTE_DE_LA_TROUVAILLE]
METHODE
1. Ouvre le fichier et lis le contexte autour de la ligne.
2. Cherche une raison pour laquelle l'affirmation serait FAUSSE :
- une contrainte ailleurs qui rend le probleme impossible
- un test qui couvre deja le cas
- une hypothese erronee du chercheur
3. Si tu ne trouves aucune raison, dis-le clairement.
VERDICT (un seul mot, puis la justification)
- REFUTEE : j'ai une preuve que c'est faux -> [PREUVE, AVEC LIGNE]
- CONFIRMEE : je n'ai trouve aucune faille -> [CE_QUE_J_AI_VERIFIE]
- NON_VERIFIABLE : je n'ai pas pu acceder a [QUOI] -> ne pas compter comme refutee
INTERDIT
Ne propose pas de correctif. Tu juges, tu ne repares pas.5. Le panel de juges
La vérification adversariale marche quand il existe une vérité. Mais certaines questions n'ont pas de bonne réponse unique : « ce modèle dbt est-il bien conçu ? », « cette architecture tient-elle la charge ? ».
Là, on utilise un panel : plusieurs agents jugent selon des angles différents, puis on agrège. C'est la variante voting de la parallélisation.
MEME ARTEFACT A JUGER
|
+---------+-----------+-----------+---------+
| | | | |
Juge Juge Juge Juge Juge
PERFORMANCE QUALITE COUT MAINTENANCE METIER
(contexte DONNEES STOCKAGE
neuf)
| | | | |
+---------+-----------+-----------+---------+
|
AGREGATEUR
(note par critere + desaccords explicites)Les deux règles qui font la différence
- Contextes séparés. Si les juges se lisent entre eux, ils convergent et tu perds la diversité. C'est exactement ce que garantit l'isolation de contexte des sous-agents.
- Grille de notation identique. Sinon tu ne peux pas agréger. Impose la même échelle à tous.
Template de juge
ROLE
Tu es juge [ANGLE : PERFORMANCE / QUALITE_DONNEES / COUT / MAINTENABILITE].
Tu juges UNIQUEMENT sous cet angle. Les autres angles ne te concernent pas.
ARTEFACT
[CHEMIN_OU_CONTENU]
GRILLE (identique pour tous les juges)
Note de 1 a 5 :
5 = exemplaire | 4 = bon | 3 = acceptable | 2 = a corriger | 1 = bloquant
CRITERES DE TON ANGLE
1. [CRITERE_1]
2. [CRITERE_2]
3. [CRITERE_3]
FORMAT DE SORTIE (JSON strict)
{
"angle": "[ANGLE]",
"note": [1-5],
"justification": "[DEUX_PHRASES_MAXIMUM]",
"preuves": ["[LIGNE_OU_EXTRAIT_1]", "[LIGNE_OU_EXTRAIT_2]"],
"changement_qui_ferait_gagner_un_point": "[UNE_ACTION_CONCRETE]"
}
INTERDIT
- Ne juge pas hors de ton angle.
- Ne donne pas de note sans au moins une preuve citee.Et pour l'agrégateur : garde les désaccords visibles. Si le juge performance met 5 et le juge maintenabilité met 2, cette tension est l'information la plus utile du panel. Une moyenne à 3,5 la ferait disparaître.
6. Quand le multi-agents coûte plus qu'il ne rapporte
Les chiffres publiés par Anthropic, à connaître par cœur :
| Mesure | Valeur |
|---|---|
| Consommation d'un agent | ≈ 4 × celle d'une conversation |
| Consommation d'un système multi-agents | ≈ 15 × celle d'une conversation |
| Part de la variance de qualité expliquée par le volume de tokens | 80 % |
| Gain du système multi-agents sur leur évaluation interne de recherche | +90,2 % face à un agent seul |
Lis la ligne « 15 × » avant de lancer quoi que ce soit. Un audit qui coûterait 1 € en conversation coûtera environ 15 € en multi-agents.
Les cas où ça ne vaut pas le coup
Anthropic nomme explicitement les mauvais terrains : les domaines où tous les agents auraient besoin du même contexte, et ceux où les agents dépendent beaucoup les uns des autres. L'exemple qu'il donne te concerne directement :
« most coding tasks involve fewer truly parallelizable tasks than research, and LLM agents are not yet great at coordinating and delegating to other agents in real time »
| Situation | Pourquoi ça échoue | À faire à la place |
|---|---|---|
| Les sous-tâches dépendent les unes des autres | Chaque agent a besoin de ce qu'a trouvé le précédent. Le parallélisme n'existe pas | Un seul agent, en séquence |
| Écrire du code dans un même fichier à plusieurs | Les agents se marchent dessus | Un agent, ou un fichier par agent |
| Moins de 5 éléments à traiter | Le coût d'orchestration dépasse le gain | Une boucle simple |
| Le critère de succès n'est pas définissable | Les agents partent dans toutes les directions | Clarifier le critère avant |
| Tâche déterministe | Un script fait ça pour zéro centime | Écris le script |
Les 4 feux verts obligatoires
Il faut les quatre pour lancer un fan-out. Un seul « non » et tu restes sur un agent unique.
- Les sous-tâches sont vraiment indépendantes.
- Il y en a au moins 5.
- Tu sais écrire le format de sortie exact de chaque worker.
- Le résultat vaut ~15 × le coût d'une conversation.
(La grille de décision complète « agent ou pas agent » est dans 05-quand-ne-pas-utiliser-un-agent.md.)
7. AVANT / APRÈS : auditer 30 modèles dbt
❌ AVANT
Audite tous mes modeles dbt et dis-moi ce qui ne va pas.Ce qui se passe : Claude lit les fichiers un par un dans ta conversation. Au bout de 12 fichiers, le contexte est saturé, la compaction se déclenche, et les premiers fichiers sont résumés puis à moitié oubliés. Le rapport final est vague et tu n'as aucune idée de ce qui a vraiment été vérifié.
✅ APRÈS
Organise un audit en 3 phases sur mes modeles dbt.
PHASE 1 - Decouverte (1 agent)
Liste tous les fichiers models/marts/**/*.sql.
Sortie : JSON {"fichiers": [...]}
PHASE 2 - Fan-out (1 agent par fichier, en parallele)
Chaque agent :
- lit UNIQUEMENT son fichier et ses dependances directes
- cherche exactement ces 3 choses :
1. jointure 1-N non agregee qui fausserait une somme
2. absence de filtre de date sur une table de faits
3. colonne utilisee en aval mais sans test dbt (unique / not_null)
- rend ce JSON, rien d'autre :
{"fichier":"...","verdict":"ok|a_corriger|bloquant",
"problemes":[{"critere":1,"ligne":42,"gravite":"bloquant",
"description":"...","correction":"..."}],
"non_verifiable":[...]}
- maximum 5 problemes par fichier
PHASE 3 - Verification adversariale (1 agent par probleme BLOQUANT)
Pour chaque bloquant : un agent au contexte neuf essaie de le REFUTER.
Verdict REFUTEE / CONFIRMEE / NON_VERIFIABLE.
Les refutees sont jetees. Les non_verifiables sont listees a part.
PHASE 4 - Synthese (1 agent)
- deduplique
- un probleme present dans plus de 5 fichiers devient un "probleme de convention"
- tableau final classe par gravite puis par nombre de fichiers touches
- section "non verifie" a la fin
CONTRAINTE
Aucun agent ne modifie de fichier. Lecture seule.Pourquoi c'est mieux
| Changement | Effet |
|---|---|
| Phases numérotées | Tu sais ce qui tourne, tu peux arrêter à la phase 2 |
| Trois critères nommés | Les 30 agents cherchent la même chose : les résultats sont comparables |
| Format JSON strict | La synthèse est mécanique, pas approximative |
| Phase adversariale | Les faux positifs sont filtrés avant d'arriver chez toi |
| « Maximum 5 problèmes » | Un agent zélé ne noie pas le rapport |
Champ non_verifiable | L'agent dit « je ne sais pas » au lieu d'inventer |
| Lecture seule | Zéro risque sur ta branche |
À retenir
- Fan-out puis synthèse est le patron qui rend le plus en data : un agent par fichier, un agent pour agréger.
- Chaque worker a besoin de quatre choses : un objectif, un format de sortie, les outils à utiliser, des limites de périmètre claires. Sans ça, doublons et trous.
- La vérification adversariale filtre les faux positifs. Distingue toujours « réfuté » de « non vérifié ».
- Le panel de juges sert quand il n'y a pas de vérité unique. Garde les désaccords visibles, ne fais pas de moyenne.
- Multi-agents ≈ 15 fois le coût d'une conversation. Pose-toi la question du retour sur investissement avant.
- Le multi-agents échoue quand les sous-tâches dépendent les unes des autres. Anthropic le dit pour la plupart des tâches de codage.
Sources
- Building Effective Agents — Anthropic Engineering
- How we built our multi-agent research system — Anthropic Engineering
- Orchestrate subagents at scale with dynamic workflows — Claude Code Docs
- Subagents in the SDK — Claude Code Docs
- anthropics/claude-cookbooks — les cinq patrons de cette page codés en notebooks (
patterns/agents/basic_workflows.ipynb,orchestrator_workers.ipynb,evaluator_optimizer.ipynb) - anthropics/claude-agent-sdk-demos — un fan-out puis synthèse qui tourne vraiment : agent chef, chercheurs en parallèle, rédacteur final (
research-agent/)