Alejandro Rioja.
AI Agents Operations

Patterns d'Orchestration Multi-Agents : Files, État et Transferts

Alejandro Rioja
Alejandro Rioja
7 min de lecture
TL;DR

Les systèmes multi-agents fiables ne reposent pas sur des prompts astucieux — ils reposent sur l'ennuyeuse discipline des systèmes distribués : des files durables entre agents, un état conservé hors du modèle et des transferts idempotents qui survivent aux réessais. Le modèle est l'ouvrier ; la file est la colonne vertébrale.

Newsletter gratuite

Chaque mercredi. 28 400+ opérateurs. Zéro superflu.

Table des matières

Mis à jour juin 2026.

TL;DR : Les systèmes multi-agents fiables ne se gagnent pas avec des prompts astucieux — ils se gagnent avec l’ennuyeuse discipline des systèmes distribués. Placez une file durable entre les agents, conservez l’état hors du modèle et rendez chaque transfert idempotent pour qu’un réessai ne puisse pas agir deux fois. Le modèle est l’ouvrier ; la file est la colonne vertébrale. Réussissez ces trois points et l’orchestration cesse d’être effrayante.

Lecture de l’opérateur : La plupart de mes plus de 100 agents sont à étape unique. Ceux qui ne le sont pas — les pipelines qui classent, puis enrichissent, puis agissent — ne sont devenus fiables que lorsque j’ai cessé de penser « chaîne de prompts » et commencé à penser « file de tâches avec des ouvriers LLM ». C’est de l’architecture, pas de l’ingénierie de prompts.

« Multi-agents » donne l’impression que les agents se parlent entre eux. En pratique, la version fiable est l’inverse : les agents ne communiquent pas directement du tout. Ils déposent des messages sur une file et récupèrent du travail dans une file, et l’orchestration vit dans la plomberie entre eux. Voici les patterns qui tiennent en production.

Pattern 1 : Placez une file durable entre chaque agent

Le premier réflexe est d’appeler l’agent B directement depuis l’agent A. Ne le faites pas. Les appels directs couplent les deux : si B est lent, A se bloque ; si B échoue, le travail de A est perdu ; si vous devez mettre B à l’échelle, vous ne le pouvez pas sans toucher à A.

À la place, A termine son travail et met un message en file pour B. B est un ouvrier séparé qui vide la file à son propre rythme.

typescript
// L'agent A termine et transfère via la file — pas d'appel direct à B
await env.ENRICH_QUEUE.send({
  traceId,
  type: "enrich",
  payload: classifierResult,
});
// Le travail de A est fait. B le récupérera de manière indépendante.

Sur Cloudflare j’utilise Workers Queues exactement pour cela — les mêmes primitives derrière la stack d’agents que j’utilise. La file vous offre quatre choses gratuitement : le buffering (B peut être hors service sans perdre de travail), les réessais (les messages en échec sont redélivrés), la contre-pression (un pic se met en file au lieu de planter) et le découplage (mettez à l’échelle ou redéployez B sans toucher à A). Chacune de ces choses est quelque chose que vous devriez sinon construire à la main et rater.

Pattern 2 : Conservez l’état hors du modèle, toujours

Le bug multi-agents le plus courant est de supposer que le modèle se souvient de quoi que ce soit entre les étapes. Ce n’est pas le cas. Chaque appel de modèle est sans état ; la seule mémoire est ce que vous mettez dans le prompt. Donc la source de vérité pour « où en est cette tâche dans le pipeline » doit vivre dans une base de données, pas dans une conversation.

Je conserve un seul enregistrement de tâche que chaque agent lit et met à jour :

typescript
interface JobState {
  traceId: string;
  stage: "classified" | "enriched" | "acted" | "done" | "failed";
  data: Record<string, unknown>;
  attempts: number;
  updatedAt: number;
}

Chaque agent effectue la même boucle : lire l’état de la tâche, faire son travail, écrire le nouvel état, mettre en file l’étape suivante. Le modèle ne détient jamais l’état — il reçoit la tranche pertinente en entrée et renvoie un résultat. C’est ce qui rend le système redémarrable : si un ouvrier meurt en pleine tâche, l’enregistrement d’état indique toujours exactement où en étaient les choses, et le message de file redélivré reprend à partir de là. Cela rend aussi le débogage gérable, car la table d’état est un enregistrement interrogeable du parcours de chaque tâche — le même état d’esprit d’instrumentation que dans comment je mesure si un agent fonctionne.

Pattern 3 : Rendez chaque transfert idempotent

Les files garantissent une livraison au moins une fois, pas exactement une fois. Cela signifie qu’un message peut être livré deux fois — coupures réseau, réessais, redéploiements. Si l’action de votre agent n’est pas idempotente, une double livraison agit deux fois : deux e-mails de confirmation, deux réservations, deux débits. C’est la classe de bug d’orchestration la plus pernicieuse, et c’est celle que les équipes découvrent en production.

La solution est de rendre les actions idempotentes avec une clé :

typescript
async function handleEnrich(msg: QueueMessage, env: Env) {
  const job = await getJob(env, msg.traceId);
  if (job.stage !== "classified") {
    // Déjà traité au-delà de cette étape — c'est une livraison en double. Ignorer.
    return;
  }
  const result = await enrich(job.data);
  await advanceJob(env, msg.traceId, "enriched", result);
  await env.ACT_QUEUE.send({ traceId: msg.traceId, type: "act" });
}

La vérification d’étape rend l’opération sûre à exécuter deux fois : la seconde livraison voit que la tâche a déjà avancé et ne fait rien. Pour les effets de bord externes (envoyer un e-mail, débiter une carte), passez une clé d’idempotence à l’API en aval pour qu’elle déduplique aussi. Supposez que chaque message sera livré deux fois et concevez de sorte que ce soit inoffensif — car tôt ou tard ce sera le cas.

Pattern 4 : Orchestrateur vs chorégraphie — choisissez délibérément

Il y a deux façons de câbler le flux, et le bon choix dépend de la complexité.

Chorégraphie (ce que j’utilise par défaut) : chaque agent ne connaît que l’étape suivante et la met en file. Le flux émerge de la chaîne. Simple, décentralisée, facile à étendre — ajoutez une étape en insérant une file. L’inconvénient est qu’aucun endroit unique ne décrit le flux entier, donc un pipeline complexe peut devenir difficile à appréhender.

Orchestration (un coordinateur central) : un orchestrateur possède le flux, appelle chaque agent à tour de rôle et décide de la suite en fonction des résultats. Tout le flux vit dans un endroit unique et lisible, et la logique de branchement est explicite. Le coût est un composant central qui doit lui-même être durable — si l’état propre de l’orchestrateur n’est pas externalisé (Pattern 2), il devient le point unique de défaillance.

Ma règle : la chorégraphie jusqu’à ce que le branchement devienne complexe, puis un orchestrateur durable. Un pipeline linéaire à trois étapes, c’est de la chorégraphie. Un flux avec routage conditionnel, fan-out parallèle et jointures veut un orchestrateur dont l’état vit dans la base de données pour qu’il puisse reprendre après un plantage.

Pattern 5 : Fan-out, fan-in sans perdre de pièces

Quand une tâche engendre N sous-tâches parallèles (enrichir 50 enregistrements, résumer 20 documents) et que vous devez toutes les attendre avant de continuer, il vous faut une jointure (join). L’astuce est un compteur dans l’état de la tâche :

  1. Le parent met en file N messages enfants et écrit expected: N, completed: 0 dans l’enregistrement de la tâche.
  2. Chaque enfant fait son travail et incrémente atomiquement completed.
  3. L’enfant qui porte completed à égaler expected met en file l’étape suivante.

L’incrément atomique est crucial — sans lui, deux enfants qui terminent simultanément peuvent tous deux croire qu’ils ne sont pas le dernier, et la jointure ne se déclenche jamais. Utilisez un compteur que le datastore peut incrémenter atomiquement, ou une transaction. Ce pattern vous permet de paralléliser le milieu coûteux d’un pipeline (souvent du travail bon marché pour Haiku — voir les calculs de coût Haiku vs Sonnet) tout en gardant une jointure propre à la fin.

Ce que j’éviterais

Vous n’avez pas besoin d’un framework d’agents lourd pour faire tout cela. Les files, une table d’état et les clés d’idempotence sont des primitives que toute plateforme possède déjà. J’ai vu des équipes se tourner vers des frameworks multi-agents élaborés pour obtenir des fonctionnalités qu’une file leur offre gratuitement, et hériter d’une boîte noire plus difficile à déboguer que la plomberie qu’elle remplaçait. Commencez par les ennuyeuses primitives. Tournez-vous vers un framework seulement quand vous avez ressenti une douleur précise qu’il résout.

Le résumé : les agents sont des ouvriers sans état, les files sont la colonne vertébrale durable, l’état vit dans une base de données et chaque transfert est sûr à exécuter deux fois. C’est tout le jeu.

FAQ

Les agents doivent-ils s’appeler directement ou passer par une file ?

Par une file. Les appels directs couplent les agents — l’échec ou la lenteur de l’un se propage à l’autre, et vous ne pouvez pas mettre à l’échelle ni redéployer de manière indépendante. Une file durable vous offre buffering, réessais, contre-pression et découplage gratuitement.

Où l’état multi-agents doit-il vivre ?

Hors du modèle, dans une base de données, sous forme d’enregistrement de tâche que chaque agent lit et met à jour. Les appels de modèle sont sans état, donc la source de vérité pour la progression du pipeline doit être externe — c’est ce qui rend le système redémarrable après un plantage.

Comment empêcher un agent d’agir deux fois sur la même tâche ?

Rendez les transferts idempotents. Vérifiez l’étape de la tâche avant d’agir et ne faites rien si elle a déjà avancé, et passez des clés d’idempotence aux API externes. Les files livrent au moins une fois, donc supposez que chaque message peut arriver deux fois et concevez de sorte que les doublons soient inoffensifs.

Ai-je besoin d’un framework multi-agents ?

Généralement non. Des files durables, une table d’état et des clés d’idempotence couvrent la plupart des besoins de production avec des primitives que votre plateforme fournit déjà. N’adoptez un framework que lorsque vous rencontrez un problème concret qu’il résout de manière unique, pas par défaut.

Continuer à lire

Recevez le guide IA dans votre boîte mail

Chaque mercredi. 28 400+ opérateurs. Zéro superflu.

↵ pour voir tous les résultats esc esc pour fermer