Le problème
La demande paraît standard : vérifier un cas client et préparer une réponse courte.
Dans les traces, c'est différent : l'orchestrator a lancé 5 agents,
trois d'entre eux faisaient presque la même sous-tâche,
le nombre de handoffs entre agents est monté à 14 pour un seul run,
et la réponse finale n'a pas été produite avant le timeout.
Le système ne tombe pas immédiatement.
Il commence à faire du bruit : doublons, handoffs, queue et latency augmentent.
Analogie : imagine un service au restaurant où les serveurs n'ont pas réparti les tables. Trois personnes prennent la même commande pendant que les autres tables attendent. Il y a plus d'activité, mais un moins bon résultat. Le chaos multi-agent dans les systèmes IA fonctionne pareil : plus d'actions, mais moins de progrès utile.
Pourquoi ça arrive
Le chaos multi-agent n'apparaît pas à cause du nombre d'agents en soi, mais à cause de l'absence de coordination stricte entre eux.
En production, c'est souvent ceci :
- les rôles des agents se chevauchent et une sous-tâche a plusieurs owners ;
- la délégation avance sans limites claires de profondeur et de nombre de transferts ;
- il n'y a pas de règle unique d'arbitration pour la décision finale ;
- des
tool_calldupliqués par plusieurs agents multiplient la charge ; - sans stop reasons ni budget gates, le run converge trop tard.
Le problème n'est pas l'approche multi-agent elle-même.
Plusieurs agents agissent sans boucle de contrôle unique.
Pannes les plus fréquentes
En production, on voit surtout quatre patterns de chaos multi-agent.
Chevauchement des rôles (Role overlap)
Deux agents ou plus prennent la même sous-tâche et donnent des résultats intermédiaires différents.
Cause typique : pas de role map et pas d'owner explicite pour la sous-tâche.
Boucle de délégation (Delegation loop)
L'agent A délègue à B, B délègue à C, C renvoie à A. De l'extérieur, le run est "actif", mais il n'y a pas de progrès.
Cause typique : pas de limite de profondeur de délégation ni de budget de transferts.
Travail dupliqué entre agents (Cross-agent duplicate work)
Des agents différents appellent le même tool avec des arguments identiques ou presque.
Cela devient vite du tool spam.
Cause typique : pas de dedupe au niveau global du run, seulement par agent.
Fan-out excessif (Unbounded fan-out)
Un agent génère beaucoup de sous-tâches, et le système consomme des ressources plus vite qu'il ne termine un travail utile.
Cause typique : pas de caps sur le nombre d'agents actifs et de tâches parallèles.
Comment détecter ces problèmes
Le chaos multi-agent se voit bien via la combinaison des métriques orchestration et runtime.
| Métrique | Signal de chaos multi-agent | Action |
|---|---|---|
agent_handoffs_per_run | beaucoup de transferts de tâche sans fin | ajouter max_handoffs et stop reason |
delegation_depth_p95 | les chaînes de délégation deviennent trop profondes | limiter la profondeur et forcer le retour à l'orchestrator |
duplicate_subtask_rate | plusieurs agents font la même sous-tâche | lock de l'owner + dedupe signatures |
cross_agent_tool_overlap_rate | hausse de tool_call identiques entre agents | shared cache, per-run dedupe, bounded fan-out |
multi_agent_chaos_stop_rate | stop reasons multi_agent_chaos:* fréquentes | revoir rôles d'agents et arbitration policy |
Comment distinguer le chaos multi-agent d'une spécialisation utile
Un run multi-agent long n'est pas toujours du chaos. La question clé : chaque agent apporte-t-il une contribution unique au résultat final.
Normal si :
- chaque sous-tâche a un owner unique et un périmètre clair ;
- un handoff change l'état de la tâche, au lieu de seulement la transférer ;
- le nombre d'agents et d'appels monte avec la qualité de la réponse.
Dangereux si :
- une sous-tâche a plusieurs owners ;
- les agents se renvoient la tâche sans nouveau signal ;
- coût et latency montent, mais le run ne converge pas vers
final_answer.
Comment stopper ces pannes
En pratique :
- définir une role map : qui fait quoi et qui est owner de chaque sous-tâche ;
- poser des limites sur agents actifs, nombre de transferts et profondeur de délégation ;
- ajouter un arbitration step avant chaque nouvelle délégation ;
- en cas de conflit ou de budget dépassé, basculer en fallback (single-agent ou réponse partielle).
Guard minimal pour coordination multi-agent :
from dataclasses import dataclass
import json
def task_signature(task: dict) -> str:
return json.dumps(task, sort_keys=True, ensure_ascii=False)
@dataclass(frozen=True)
class MultiAgentLimits:
max_agents_per_run: int = 4
max_handoffs: int = 8
max_delegation_depth: int = 3
max_parallel_subtasks: int = 6
max_duplicate_signature: int = 2
class MultiAgentChaosGuard:
def __init__(self, limits: MultiAgentLimits = MultiAgentLimits()):
self.limits = limits
self.seen_agents: set[str] = set()
self.handoffs = 0
self.in_flight_signatures: set[str] = set()
self.signature_claims: dict[str, int] = {}
self.owner_by_signature: dict[str, str] = {}
def register_agent(self, agent_id: str) -> str | None:
self.seen_agents.add(agent_id)
if len(self.seen_agents) > self.limits.max_agents_per_run:
return "multi_agent_chaos:agent_fanout"
return None
def on_handoff(self, _from_agent: str, to_agent: str, depth: int) -> str | None:
self.handoffs += 1
if self.handoffs > self.limits.max_handoffs:
return "multi_agent_chaos:handoff_budget"
if depth > self.limits.max_delegation_depth:
return "multi_agent_chaos:delegation_depth"
return self.register_agent(to_agent)
def claim_subtask(self, agent_id: str, task: dict) -> str | None:
sig = task_signature(task)
owner = self.owner_by_signature.get(sig)
if owner is not None and owner != agent_id:
return "multi_agent_chaos:ownership_conflict"
self.owner_by_signature.setdefault(sig, agent_id)
self.signature_claims[sig] = self.signature_claims.get(sig, 0) + 1
if self.signature_claims[sig] > self.limits.max_duplicate_signature:
return "multi_agent_chaos:duplicate_subtask"
if sig not in self.in_flight_signatures:
if len(self.in_flight_signatures) >= self.limits.max_parallel_subtasks:
return "multi_agent_chaos:parallel_fanout"
self.in_flight_signatures.add(sig)
return None
def finish_subtask(self, task: dict) -> None:
self.in_flight_signatures.discard(task_signature(task))
C'est un guard de base.
Dans cette version, seen_agents compte aussi les tentatives d'étendre le fan-out,
pas seulement les agents déjà admis.
max_agents_per_run limite le nombre d'agents uniques dans un run.
En production, on l'étend en général avec un shared state store,
une priority queue pour sous-tâches et un fallback explicite vers single-agent mode.
on_handoff(...) est appelé avant de transférer à un autre agent,
et claim_subtask(...) avant de lancer l'exécution, pour stopper le chaos à l'entrée.
Où c'est implémenté dans l'architecture
En production, le contrôle du chaos multi-agent est en général réparti entre trois couches système.
Orchestration Topologies définit comment les agents interagissent, qui possède l'état et où passe l'arbitration. Sans cette couche, le chaos inter-agent est presque inévitable.
Agent Runtime pilote execution limits,
stop reasons (multi_agent_chaos:*) et transitions fallback.
C'est ici qu'on fixe handoff/depth budgets et conditions d'arrêt forcé.
Tool Execution Layer limite les appels d'outils dupliqués entre agents : dedupe, retries, timeout et shared caching au niveau run.
Checklist
Avant de shipper un scénario multi-agent en production :
- [ ] role map et owner de chaque sous-tâche explicitement définis ;
- [ ]
max_agents_per_run,max_handoffs,max_delegation_depthdéfinis ; - [ ] lock de l'owner de tâche et per-run dedupe signatures en place ;
- [ ] bounded fan-out activé pour sous-tâches parallèles ;
- [ ] stop reasons couvrent
multi_agent_chaos:*; - [ ] fallback présent : single-agent mode ou réponse partielle ;
- [ ] alertes sur
agent_handoffs_per_run,duplicate_subtask_rate,queue_backlog; - [ ] runbook décrit comment isoler un conflit de rôles pendant incident.
FAQ
Q : Plus d'agents signifie toujours meilleure qualité ?
R : Non. Sans coordination, plus d'agents produit souvent plus de doublons et de conflits, pas un meilleur résultat.
Q : Peut-on supprimer le chaos uniquement en modifiant le prompt ?
R : Non. Le prompt aide, mais la racine est dans le contrôle orchestration : rôles, ownership des tâches, budgets et arbitration.
Q : Que faire si le chaos a déjà commencé en production ?
R : Limiter temporairement le fan-out, réduire le nombre d'agents actifs, activer un fallback single-agent, et vérifier les stop reasons dans les traces.
Q : Qui doit prendre la décision finale en système multi-agent ?
R : En général un orchestrator ou un arbitration step. Sans owner unique de la décision finale, le système bascule vite en conflits ou doublons.
Le chaos multi-agent ressemble rarement à une seule grosse panne. Le plus souvent, c'est une accumulation de petits conflits entre agents. C'est pourquoi les systèmes de production ont besoin non seulement d'agents "intelligents", mais aussi d'une discipline stricte d'orchestration.
Pages liées
Si ce problème apparaît en production, ces pages sont aussi utiles :
- Pourquoi les agents IA échouent — carte générale des pannes en production.
- Deadlocks — comment l'attente cyclique entre agents bloque le workflow.
- Cascading failures — comment une panne locale se propage dans le système.
- Tool spam — comment les appels d'outils dupliqués consomment le budget.
- Agent Runtime — où définir budgets, stop reasons et fallback.
- Orchestration Topologies — comment concevoir une interaction contrôlée entre agents.
- Tool Execution Layer — où centraliser retries, dedupe et timeout.