Claude Platform Docs
Managed AgentsOrchestration avancée

Orchestration multi-agents

Coordonnez plusieurs agents au sein d'une même session.

La « multiagent orchestration » (orchestration multi-agents) permet à un agent de se coordonner avec d'autres pour accomplir des tâches complexes. Les agents peuvent agir en parallèle, chacun avec son propre contexte isolé, ce qui contribue à améliorer la qualité des résultats et peut également réduire le délai d'exécution.

Vous n'êtes pas sûr qu'une configuration multi-agents convienne à votre problème ? Consultez quand utiliser les systèmes multi-agents (et quand ne pas le faire).

Fonctionnement

Tous les agents partagent le même « sandbox » (bac à sable), le même système de fichiers et les mêmes identifiants de coffre. Chaque agent s'exécute toutefois dans son propre « session thread » (fil de session), un flux d'événements au contexte isolé doté de son propre historique de conversation. Le coordinateur signale son activité dans le « primary thread » (fil principal), qui correspond au flux d'événements au niveau de la session. Des fils supplémentaires sont créés à l'exécution lorsque le coordinateur délègue du travail.

Les fils sont persistants : le coordinateur peut envoyer un message de suivi à un agent qu'il a appelé précédemment, et cet agent conserve tout le contenu de ses tours précédents.

Chaque agent utilise sa propre configuration : modèle, « system prompt » (invite système), outils, serveurs « Model Context Protocol », ou MCP, et « skills » (compétences). Les remplacements de configuration d'agent au niveau de la session constituent l'exception : ils s'appliquent au coordinateur et à ses copies self. Les outils, les serveurs MCP et le contexte ne sont pas partagés.

Ce qu'il faut déléguer

La coordination multiagent convient particulièrement aux tâches complexes qui nécessitent un travail sur des surfaces variées, ou dans lesquelles plusieurs tâches bien délimitées contribuent à un objectif global.

Schémas qui fonctionnent bien :

  • Parallélisation : Répartissez simultanément des sous-tâches indépendantes (recherche dans plusieurs sources, analyse de fichiers distincts) et demandez au coordinateur de synthétiser les résultats.
  • Spécialisation : Acheminez le travail vers des agents dotés d'invites système et d'outils propres à un domaine, comme un agent de sécurité ou un agent de documentation, plutôt que de doter un seul agent de toutes les capacités.
  • Escalade : Consultez un agent ou un modèle plus performant pour un sous-ensemble de sous-tâches complexes.

Configurer le coordinateur

Lors de la définition de votre agent, définissez multiagent pour déclarer le « roster » (liste d'agents) auxquels le coordinateur peut déléguer :

ant apply engineering-lead.md reviewer.md test-writer.md
engineering-lead.md
---
name: Engineering Lead
model: claude-opus-5-5
tools:
  - type: agent_toolset_20260401
multiagent:
  type: coordinator
  agents: # paths: ant apply substitutes {type: agent, id, version}
    - ./reviewer.md
    - ./test-writer.md
---

You coordinate engineering work. Delegate code review to the reviewer agent and test writing to the test agent.
reviewer.md
---
name: reviewer
model: claude-haiku-4-5
---

You are a code reviewer.
test-writer.md
---
name: test-writer
model: claude-haiku-4-5
---

You write unit tests.

multiagent.agents peut accepter l'un des éléments suivants :

  • {"type": "agent", "id": agent.id} référence par son ID un agent créé précédemment. Si aucune version n'est spécifiée, la référence est épinglée à la dernière version de cet agent au moment de la création du coordinateur.
  • {"type": "agent", "id": agent.id, "version": agent.version} épingle une version spécifique de l'agent.
  • {"type": "self"} permet au coordinateur de créer des copies de lui-même. Si la session a été créée avec des remplacements de configuration d'agent, ces remplacements s'appliquent également à ces copies. Les entrées de la liste référencées par ID ne sont pas affectées.
  • {"type": "advisor", "model": "<model id>"} donne au fil principal de la session un conseiller qu'il peut consulter en cours de tour. Une liste peut contenir au maximum une entrée de conseiller. Consultez Donner un conseiller à la session.

Dans un fichier d'agent ant apply (l'onglet CLI), une entrée de la liste peut également être le chemin vers le fichier d'un autre agent, comme ./reviewer.md. Apply crée d'abord cet agent, puis remplace le chemin par une référence épinglée {"type": "agent", "id": ..., "version": ...}.

La configuration du coordinateur, y compris sa liste multiagent.agents, fait l'objet d'un instantané lors de la création ou de la mise à jour du coordinateur. Les agents référencés restent épinglés aux versions résolues à ce moment-là. Ils ne récupèrent pas automatiquement les mises à jour ultérieures de leurs définitions. Pour déléguer à une version plus récente d'un agent référencé, mettez à jour le coordinateur afin que sa liste référence cette version.

Le coordinateur ne peut déléguer qu'à un seul niveau d'agents. Si vous référencez un agent qui possède sa propre liste multiagent.agents, la requête de création ou de mise à jour échoue avec une erreur de validation. Vous pouvez lister au maximum 20 agents uniques dans multiagent.agents, mais le coordinateur peut appeler plusieurs copies de chaque agent.

Lorsque des agents épinglent une géographie d'inférence (model.inference_geo dans la définition de l'agent), l'épinglage du coordinateur et celui de chaque membre de la liste doivent soit tous être définis sur la même valeur, soit tous être non définis. Une liste incohérente est rejetée avec une erreur de validation 400. Ce contrôle s'applique lors de l'enregistrement de l'agent, ainsi que lorsqu'un remplacement à la création de session modifie l'un des épinglages.

Donner un conseiller à la session

Une entrée de conseiller dans multiagent.agents donne au fil principal de la session un « advisor » (conseiller). Il s'agit d'un modèle que le fil principal peut consulter en cours de tour pour obtenir des conseils stratégiques, par exemple pour planifier une approche, se débloquer ou relire le travail avant de terminer. L'entrée comporte exactement deux champs, type et model :

cURL
curl -fsS https://api.anthropic.com/v1/agents \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: managed-agents-2026-04-01" \
  -H "content-type: application/json" \
  -d '{
    "name": "Backend engineer",
    "model": "claude-sonnet-5",
    "system": "You implement backend features end to end. Consult the advisor before major backend design decisions.",
    "multiagent": {
      "type": "coordinator",
      "agents": [
        {"type": "advisor", "model": "claude-opus-5-5"}
      ]
    }
  }'

Une liste peut contenir au maximum une entrée de conseiller, aux côtés de n'importe quelle autre forme d'entrée. L'entrée occupe le nom réservé anthropic.advisor dans la liste. Une liste qui contient à la fois une entrée de conseiller et un membre nommé littéralement anthropic.advisor est donc rejetée avec une erreur de validation 400. Dans les réponses, l'entrée de conseiller est renvoyée en dernier dans la liste, quelle que soit la position à laquelle elle a été soumise.

Le modèle conseiller doit atteindre un niveau de capacité minimal, et le modèle de l'agent ne doit pas être plus performant que son conseiller. Des modèles de capacité égale peuvent être associés. Une association invalide est rejetée avec une erreur de validation 400 lors de l'enregistrement de l'agent. Les associations valides suivent le tableau de compatibilité des modèles de l'outil conseiller.

Le conseiller est également disponible en tant qu'outil serveur sur l'API Messages. La surface Managed Agents diffère en matière de configuration et de livraison : l'entrée de la liste ne comporte pas de champs max_uses, max_tokens ou caching, et les conseils arrivent via des événements de fil plutôt que via des blocs advisor_tool_result.

Fonctionnement des consultations

Chaque consultation s'exécute dans un fil nommé anthropic.advisor, créé par la plateforme, qui se termine de lui-même à la fin de la consultation. Le conseil est livré au fil principal sous la forme d'un événement agent.thread_message_received. Une consultation émet les événements de fil standard, identifiés par le nom réservé anthropic.advisor. Les événements de cycle de vie du fil le portent dans agent_name, et la livraison du conseil le porte dans from_agent_name. Ces événements arrivent généralement dans cet ordre :

  1. session.thread_created
  2. session.thread_status_running
  3. agent.thread_message_received (le conseil)
  4. session.thread_status_idle (stop_reason: end_turn)
  5. session.thread_status_terminated

Une consultation n'émet aucun événement agent.tool_use, et aucun événement agent.thread_message_sent n'apparaît dans le flux d'événements de la session. En effet, l'entrée de la consultation est composée par la plateforme et non envoyée par l'agent. Si vous listez les événements du fil du conseiller lui-même, le conseil y apparaît également sous la forme d'un événement agent.thread_message_sent. La livraison du conseil (événement 3) n'arrive pas forcément avant les événements idle et terminated du fil du conseiller. Ne considérez donc pas ces derniers comme le signe que le conseil a déjà été livré.

La lisibilité du conseil par votre client dépend de la politique du modèle conseiller. Elle suit la même répartition que les variantes de résultat de l'outil conseiller de l'API Messages :

  • Les modèles conseillers qui renvoient des résultats en texte brut dans l'API Messages livrent ici le conseil sous forme de texte lisible.
  • Les modèles conseillers qui renvoient des résultats masqués dans l'API Messages livrent ici un espace réservé [{"type": "redacted"}] comme contenu du message, sur toutes les surfaces client. L'agent lui-même lit toujours le conseil complet côté serveur.

Dans l'exemple précédent, Claude Opus 5 est un conseiller à résultats masqués : votre client voit l'espace réservé, tandis que l'agent lit le conseil complet. Si vous souhaitez que le conseil soit lisible dans le flux d'événements, choisissez plutôt Claude Opus 4.8 comme conseiller. La réflexion du conseiller n'est jamais exposée. Les clients ne peuvent pas envoyer eux-mêmes de blocs redacted, et tout événement qui en contient un est rejeté avec une erreur de validation 400.

Une consultation échouée ou interrompue ne fait jamais échouer le tour de l'agent : l'agent poursuit son travail après un avis générique indiquant l'échec de la consultation. Un user.interrupt au niveau de la session pendant une consultation termine le fil du conseiller sans livrer de conseil. Un user.interrupt portant le session_thread_id du fil du conseiller abandonne uniquement cette consultation.

Fils du conseiller

Le conseiller n'est pas un agent de la liste. Il est invisible pour l'outil list_agents du coordinateur et ne peut pas recevoir de messages via send_to_agent. Seul le fil principal de la session peut le consulter, et les agents de la liste ne le peuvent pas.

Les fils du conseiller ne sont pas soumis à la limite de fils simultanés. Ils apparaissent dans la liste des fils de la session avec agent défini sur la forme du conseiller, exactement telle que configurée ({"type": "advisor", "model": ...}), et parent_thread_id défini sur le fil principal.

La « prompt caching » (mise en cache des prompts) côté conseiller est automatique et ne nécessite aucune configuration. Les consultations sont facturées aux tarifs du modèle conseiller. Leurs tokens apparaissent dans l'utilisation du fil du conseiller et dans les totaux d'utilisation de la session.

Supprimer le conseiller

Pour supprimer le conseiller, mettez à jour l'agent avec une liste qui ne contient plus l'entrée de conseiller. Si le conseiller est la seule entrée de la liste, videz entièrement la liste en définissant "multiagent": null.

Créer la session

Créez une session qui référence le coordinateur. Le coordinateur délègue ensuite aux agents de sa liste selon les besoins.

session = client.beta.sessions.create(
    agent=coordinator.id,
    environment_id=environment.id,
)

Connecter les agents aux serveurs MCP

Les serveurs MCP sont propres à chaque agent : chaque définition d'agent déclare ses propres serveurs et outils. Les identifiants de coffre, eux, sont propres à la session : les vault_ids transmis lors de la création de la session s'appliquent à chaque fil. Cela a deux implications pour votre intégration :

  • Pour authentifier les serveurs MCP, incluez un identifiant de coffre pour chaque serveur MCP utilisé par l'ensemble des agents.
  • Pour limiter l'accès d'un agent, déclarez dans sa définition d'agent uniquement les serveurs dont il a besoin.

Les remplacements de configuration d'agent lors de la création de la session peuvent remplacer les serveurs MCP du coordinateur et ceux de ses copies self.

Créez le chercheur, qui déclare le serveur MCP GitHub, ainsi que le coordinateur qui délègue au chercheur :

ant apply coordinator.md researcher.md
coordinator.md
---
name: coordinator
model: claude-opus-5-5
tools:
  - type: agent_toolset_20260401
multiagent:
  type: coordinator
  agents: # path: ant apply substitutes {type: agent, id, version}
    - ./researcher.md
---
researcher.md
---
name: researcher
model: claude-haiku-4-5
mcp_servers:
  - type: url
    name: github
    url: https://api.githubcopilot.com/mcp/
tools:
  - type: mcp_toolset
    mcp_server_name: github
---

Créez ensuite la session avec le coffre qui contient l'identifiant GitHub :

session = client.beta.sessions.create(
    agent=coordinator.id,
    environment_id=environment.id,
    vault_ids=[vault.id],
)
print(session.id)

Dans cet exemple, seul le chercheur déclare le serveur MCP GitHub : le coordinateur n'y a donc pas accès. Les vault_ids de la session fournissent l'identifiant GitHub au fil du chercheur.

Fils

Le flux d'événements au niveau de la session (/v1/sessions/{session_id}/events/stream) est considéré comme le fil principal. Il contient une vue condensée de l'activité de tous les fils. Vous n'y voyez pas l'activité complète des sous-agents, mais vous voyez le début et la fin de leur travail, ainsi que les événements bloquants tels que les demandes d'autorisation d'outils.

Les fils de session vous permettent d'examiner en détail l'activité d'un agent spécifique.

Le status de la session agrège l'activité de tous les agents : si au moins un fil est running, le statut global de la session est également running.

Un budget de session est un plafond unique partagé par tous les fils d'une session. Lorsque le plafond est atteint, les fils se mettent en pause indépendamment les uns des autres. Le coût de chaque fil est calculé selon le modèle qui a servi ce fil.

Listez tous les fils associés à une session comme suit :

for thread in client.beta.sessions.threads.list(session.id):
    print(f"[{thread.agent.name}] {thread.status}")

La liste complète inclut le fil principal, pour lequel parent_thread_id est null.

Événements du fil principal

Ces événements exposent l'activité multiagent sur le fil principal, à l'adresse /v1/sessions/{session_id}/events/stream. Les événements liés aux messages sont nommés du point de vue du fil dans le flux duquel ils apparaissent. agent.thread_message_received signifie qu'un message est arrivé sur ce fil depuis un autre fil, et agent.thread_message_sent signifie que ce fil a envoyé un message. Par exemple, la tâche déléguée par le coordinateur arrive dans le flux du fil enfant sous la forme d'un événement agent.thread_message_received.

TypeDescription
session.thread_createdUn fil a été créé. Inclut session_thread_id et agent_name.
session.thread_status_runningUn fil a commencé une activité.
session.thread_status_idleL'agent associé au fil attend une entrée. Inclut un stop_reason indiquant pourquoi l'agent s'est arrêté.
session.thread_status_terminatedUn fil a été archivé ou a rencontré une erreur terminale.
agent.thread_message_receivedSur le fil principal, un agent a envoyé un rapport ou une question au coordinateur. Inclut from_session_thread_id, from_agent_name et content.
agent.thread_message_sentSur le fil principal, le coordinateur a envoyé une tâche ou un message de suivi à un autre agent. Inclut to_session_thread_id, to_agent_name et content.

Les consultations du conseiller émettent ces mêmes événements de fil sous le nom réservé anthropic.advisor. Ce nom figure dans agent_name pour les événements de cycle de vie du fil, et dans from_agent_name pour la livraison du conseil. Pour la séquence complète, consultez Donner un conseiller à la session.

Événements des fils de session

Les événements critiques sont relayés vers le fil principal. Vous pouvez toutefois vouloir examiner le raisonnement et les appels d'outils d'un agent spécifique. Pour ce faire, diffusez en streaming ou listez les événements du fil de session correspondant.

Chaque fil de session possède son propre flux d'événements, à l'adresse /v1/sessions/{session_id}/threads/{thread_id}/stream. Ce flux accepte le même paramètre event_deltas[] que le flux au niveau de la session, ce qui vous permet de prévisualiser le texte d'un sous-agent à mesure que le modèle le génère. Une connexion ne prévisualise que le fil qu'elle lit : les aperçus d'un fil enfant n'apparaissent jamais dans le flux au niveau de la session. Pour suivre un sous-agent en direct, ouvrez donc le flux de son propre fil. Pour savoir comment activer, accumuler et réconcilier les aperçus, consultez Prévisualiser les événements des fils de session.

with client.beta.sessions.threads.events.stream(
    thread.id,
    session_id=session.id,
) as stream:
    for event in stream:
        match event.type:
            case "agent.message":
                for block in event.content:
                    if block.type == "text":
                        print(block.text, end="")
            case "session.thread_status_idle":
                break

Autorisations d'outils et outils personnalisés

Un sous-agent peut avoir besoin d'une réponse de votre client, par exemple une autorisation pour exécuter un appel d'outil ou le résultat d'un outil personnalisé. Dans ce cas, l'événement est également publié sur le fil principal, avec un session_thread_id qui identifie le fil de session d'origine. Un appel d'outil nécessite votre autorisation sous always_ask, ou sous auto lorsque le serveur ne parvient à aucune décision.

{
  "type": "session.thread_status_idle",
  "id": "sevt_01ABC...",
  "session_thread_id": "sth_01DEF...",
  "agent_name": "code-reviewer",
  "stop_reason": {
    "type": "requires_action",
    "event_ids": ["sevt_01XYZ..."]
  }
}

Publiez user.tool_confirmation (avec tool_use_id) ou user.custom_tool_result (avec custom_tool_use_id). Le serveur achemine automatiquement la réponse vers le bon fil.

Sous auto, vos événements user.message peuvent amener le serveur à autoriser un appel qu'il refuserait autrement. Rien dans le fil d'un sous-agent n'est considéré comme l'expression de votre intention : votre client n'y publie aucun message, et les messages que le coordinateur envoie au sous-agent ne comptent pas. Lorsque le serveur refuse un appel sous auto, rien n'est publié sur le fil principal. L'événement et le résultat d'outil en erreur apparaissent uniquement dans le flux du fil du sous-agent, et le sous-agent continue de s'exécuter.

L'exemple suivant étend le gestionnaire de confirmation d'outil pour acheminer les réponses. Le même schéma s'applique à user.custom_tool_result.

for event_id in stop.event_ids:
    client.beta.sessions.events.send(
        session.id,
        events=[
            {
                "type": "user.tool_confirmation",
                "tool_use_id": event_id,
                "result": "allow",
            }
        ],
    )

Was this page helpful?