Sous-agents

Référence API : Subagent, SubagentPolicy

Un agent peut confier des parties d'un travail à des sous-agents. Chacun exécute sa propre tâche avec son propre historique pendant que les autres travaillent, et le parent rassemble leurs rapports. Un sous-agent est une session distincte, avec ses propres tours.

Si vous connaissez les transferts de l'API d'agent : un sous-agent transmet son rapport à son parent ; il ne prend pas le relais dans la conversation.

Quand utiliser des sous-agents

Quand utiliser des sous-agents

  • Des tâches indépendantes en parallèle : recherchez cinq produits à la fois, avec un sous-agent par produit.
  • Un spécialiste : un sous-agent avec ses propres instructions et outils, par exemple un agent de déploiement qui seul peut appeler deploy.
  • Une tâche longue qui remplirait le contexte du parent : le sous-agent lit les logs, et le parent ne reçoit que son résumé.

Lorsqu'une étape dépend du résultat de la précédente, laissez le parent exécuter les deux. Utilisez un skill lorsque seule la procédure change.

Déclarer et exécuter des sous-agents

Déclarer et exécuter des sous-agents

Passez les sous-agents que le modèle peut démarrer dans Agent(subagents=[...]). Le modèle du parent en choisit un par son nom lorsqu'il démarre un sous-agent :

import asyncio

from pydantic import BaseModel

from mistralai import agents

PRICES = {"atlas": "1,200 EUR", "nova": "850 EUR"}


class PriceArgs(BaseModel):
    product: str


@agents.tool(name="lookup_price", description="Price of one product.", input_schema=PriceArgs)
async def lookup_price(args: PriceArgs) -> dict[str, str]:
    return {"price": PRICES.get(args.product.casefold(), "unknown")}


agent = agents.Agent(
    model="mistral-large-4",
    instructions=(
        "You answer questions about our products. Start one researcher per product, "
        "wait for every result, then answer in one sentence."
    ),
    subagents=[
        agents.Subagent(
            name="researcher",
            description="Looks up one product and reports its price.",
            instructions="Call lookup_price once, then answer with the product name and its price.",
            tools=[lookup_price],
            builtins=agents.Builtins(subagents=False),
        )
    ],
)


async def main() -> None:
    session = await agent.start_session()
    state = await session.run("What do the Atlas and the Nova cost?")
    if isinstance(state, agents.Completed):
        print(state.text)
    print(len(await session.subagents()))
    await session.cancel()


asyncio.run(main())
The Atlas costs **1,200 EUR** and the Nova costs **850 EUR**.
2

Le parent n'a aucun outil propre ; il démarre un agent de recherche pour chaque produit et attend les deux résultats. Chaque agent de recherche dispose de lookup_price, et agents.Builtins(subagents=False) l'empêche de démarrer ses propres sous-agents, y compris des sous-agents génériques. session.subagents() renvoie les sessions des deux agents de recherche, donc le programme affiche 2 ; voir Consulter et arrêter les sous-agents.

name, description et instructions sont obligatoires. Le modèle lit le nom et la description pour choisir un sous-agent ; rédigez donc la description à son intention. La plupart des autres champs sont hérités du parent, sauf si vous les définissez ; voir Configurer les sous-agents.

Le modèle peut aussi démarrer un sous-agent générique. Celui-ci reprend le modèle, les outils et les paramètres du parent, et s'exécute selon des instructions rédigées par le modèle. Le modèle peut en démarrer un dès que l'agent possède des sous-agents ou une subagent_policy.

Fonctionnement des sous-agents

Fonctionnement des sous-agents

L'agent que vous exécutez est la racine ; il forme avec ses sous-agents un arbre. Le modèle du parent pilote ses sous-agents avec des outils que le système d'exécution lui fournit : l'un démarre un sous-agent, les autres lui envoient un message, attendent son résultat ou interrompent son tour. Vous n'avez aucun de ces outils à écrire.

  • Un sous-agent s'exécute en arrière-plan ; le parent peut donc en démarrer plusieurs à la fois.
  • Le parent peut envoyer des messages de suivi à un sous-agent, qui conserve son historique.
  • Chaque résultat arrive dans le tour en cours du parent, ou dans son prochain tour si le tour en cours est terminé. session.run() renvoie un résultat lorsque le tour du parent se termine, et non lorsque les tours de ses sous-agents se terminent. Demandez au parent d'« attendre tous les résultats » lorsqu'il ne doit pas répondre avant de les avoir reçus.
  • Un sous-agent arrêté avant la fin transmet tout de même son dernier message, et le parent peut lui envoyer un message pour qu'il continue.
Où s'exécutent les sous-agents

Où s'exécutent les sous-agents

  • Les sous-agents s'exécutent dans la sandbox de la racine et partagent ses fichiers. Vous configurez la sandbox une seule fois, sur l'agent racine. Attribuez des fichiers distincts aux sous-agents qui écrivent en parallèle.
  • Dans votre processus, toutes les sandbox fonctionnent avec les sous-agents.
  • Lorsque vous déployez avec Studio, en auto-hébergement ou avec une gestion par Mistral, utilisez MistralSandbox, qui nécessite le rôle cloud_user, ou NoSandbox. Avec une autre sandbox, un agent doté de sous-agents s'arrête au démarrage.
Limites

Limites

Au maximum, 10 tours de sous-agents s'exécutent à la fois dans l'ensemble de l'arbre. L'arbre comporte deux niveaux de sous-agents : les sous-agents et leurs propres sous-agents. Modifiez les limites sur l'agent racine avec subagent_policy=. Ajoutez ce qui suit à l'agent ci-dessus :

subagent_policy=agents.SubagentPolicy(concurrent_child_turn_limit=4),

Tous les champs et leurs valeurs par défaut : Références SubagentPolicy. Lorsque l'arbre est plein, le démarrage d'un sous-agent échoue, et le modèle du parent lit l'erreur comme toute autre erreur d'outil.

Consulter et arrêter les sous-agents

Consulter et arrêter les sous-agents

await session.subagents() renvoie un handle de session pour chaque sous-agent direct, du plus récent au plus ancien. Vous pouvez consulter un sous-agent et interrompre son tour, mais seul son parent lui confie du travail : send_message, run, start_turn et cancel sur son handle, ainsi que steer sur son tour, lèvent agents.UnsupportedSessionProcedureError. Lorsqu'un sous-agent attend un callback, par exemple une approbation, le résultat Blocked de la racine le répertorie dans state.callbacks avec les identifiants du sous-agent (Approbations entre sous-agents). Interrompez son tour avec await agent.session(callback.session_id).turn(callback.turn_id).interrupt().

Pour arrêter un sous-agent, annulez la racine : await session.cancel() sur la session racine arrête la racine et tous les sous-agents. turn.interrupt() sur le tour de la racine n'arrête que ce tour : les sous-agents continuent de s'exécuter, et leurs résultats arrivent dans le prochain tour de la racine. Dans votre processus, l'arbre s'arrête aussi lorsque la boucle d'événements se termine ; laissez donc le parent attendre ses sous-agents avant que votre programme ne se termine.

Problèmes courants

Problèmes courants

SymptômeCauseSolution
La réponse omet le résultat d'un sous-agentLe tour du parent s'est terminé avant celui du sous-agent ; le résultat est donc arrivé dans le tour suivant.Demandez au parent d'attendre tous les résultats avant de répondre.
Un agent déployé s'arrête au démarrage avec subagents_with_unborrowable_sandboxSes sous-agents ne peuvent pas partager sa sandbox.Utilisez MistralSandbox ou NoSandbox.