Aller au contenu principal

Agent multi-étapes avec boucle de raisonnement

Mis à jour le 29 juillet 2026

Agent multi-étapes avec boucle de raisonnement

Les agents les plus puissants ne se contentent pas d’un seul appel de tool. Ils enchaînent plusieurs étapes de raisonnement, ajustent leur stratégie en fonction des résultats, et itèrent jusqu’à atteindre l’objectif. Dans cette leçon, vous apprendrez à construire ces agents multi-étapes. Les exemples utilisent la famille GPT-5.6 : là où la génération précédente vous faisait changer de modèle pour obtenir de la réflexion, c’est désormais le réglage d’effort qui joue ce rôle, sur le modèle que vous avez choisi.

Le pattern plan-execute

Un agent multi-étapes commence par élaborer un plan, puis exécute chaque étape. La séparation est délibérée : le planificateur ne dispose d’aucun tool et produit une structure typée, tandis que l’exécuteur reçoit ce plan comme feuille de route et n’a plus qu’à dérouler. Une demande floue du type « prépare le point trimestriel pour les grands comptes » devient ainsi une suite d’actions concrètes — interroger le CRM, produire le rapport, envoyer l’email — avant que la moindre action ne soit tentée.

from agents import Agent, Runner, function_tool
from pydantic import BaseModel
import json

class PlanAction(BaseModel):
    etapes: list[str]
    objectif: str

agent_planificateur = Agent(
    name="Planificateur",
    instructions="""Vous recevez une tâche complexe. Décomposez-la en étapes simples et ordonnées.
    Chaque étape doit être une action concrète et réalisable.""",
    model="gpt-5.6-sol",  # Le raisonnement avancé pour la planification
    output_type=PlanAction,
)

@function_tool
def rechercher_dans_crm(requete: str) -> str:
    """Recherche dans le CRM des informations clients."""
    return json.dumps({"clients": [
        {"nom": "Acme Corp", "ca": 500000, "contrat": "Enterprise"},
        {"nom": "TechStart", "ca": 50000, "contrat": "Starter"},
    ]})

@function_tool
def generer_rapport(titre: str, contenu: str) -> str:
    """Génère un rapport formaté."""
    return f"Rapport '{titre}' généré avec succès ({len(contenu)} caractères)"

@function_tool
def envoyer_email(destinataire: str, sujet: str, corps: str) -> str:
    """Envoie un email."""
    return f"Email envoyé à {destinataire} : {sujet}"

agent_executeur = Agent(
    name="Exécuteur",
    instructions="""Vous exécutez des tâches étape par étape.
    Utilisez les outils disponibles pour accomplir chaque étape.
    Si une étape échoue, tentez une approche alternative.""",
    tools=[rechercher_dans_crm, generer_rapport, envoyer_email],
    model="gpt-5.6-terra",
)

async def traiter_tache_complexe(tache: str):
    # Étape 1 : Planifier
    plan = await Runner.run(agent_planificateur, tache)
    print(f"Plan : {plan.final_output.etapes}")

    # Étape 2 : Exécuter avec le plan comme contexte
    instructions_execution = f"""Exécutez les étapes suivantes dans l'ordre :
    {chr(10).join(f'{i+1}. {e}' for i, e in enumerate(plan.final_output.etapes))}
    Objectif : {plan.final_output.objectif}"""

    result = await Runner.run(agent_executeur, instructions_execution)
    return result.final_output

Agent auto-correcteur

Planifier ne suffit pas : sur le terrain, les tools échouent. La seconde forme de boucle consiste donc à laisser l’agent détecter ses erreurs et se corriger. Tout repose sur un détail souvent négligé — le tool ne lève pas d’exception, il renvoie un message d’erreur lisible. L’agent le lit, comprend qu’il a oublié le FROM, réécrit sa requête et réessaie, dans la limite des trois tentatives fixées par ses instructions.

from agents import Agent, Runner, function_tool

@function_tool
def executer_requete_sql(sql: str) -> str:
    """Exécute une requête SQL sur la base de données."""
    # Simulation : certaines requêtes échouent
    if "DROP" in sql.upper():
        return "ERREUR : Les requêtes destructives sont interdites."
    if "SELECT" in sql.upper() and "FROM" not in sql.upper():
        return "ERREUR : Syntaxe SQL invalide - FROM manquant."
    return json.dumps({
        "colonnes": ["nom", "ca_mensuel", "region"],
        "lignes": [
            ["Acme Corp", 45000, "Île-de-France"],
            ["TechStart", 12000, "Rhône-Alpes"],
        ],
        "nb_resultats": 2
    })

agent_analyste = Agent(
    name="Analyste de données",
    instructions="""Vous analysez des données en exécutant des requêtes SQL.
    Si une requête échoue :
    1. Analysez le message d'erreur
    2. Corrigez la requête
    3. Réessayez
    Maximum 3 tentatives par requête.
    Ne jamais utiliser DROP, DELETE ou TRUNCATE.""",
    tools=[executer_requete_sql],
    model="gpt-5.6-terra",
    max_turns=10,  # Assez de tours pour les corrections
)

result = Runner.run_sync(
    agent_analyste,
    "Quel est le chiffre d'affaires total par région ?"
)

Remarquez que l’interdiction des requêtes destructives figure à deux endroits : dans les instructions et dans le code du tool. La consigne oriente le modèle, mais seule la vérification côté tool garantit qu’un DROP TABLE ne passera jamais.

Pattern : chaîne d’agents spécialisés

Pour les workflows complexes, enchaînez plusieurs agents spécialisés plutôt que de charger un agent unique de tout faire. Chaque maillon a un rôle net : le collecteur va chercher la matière, l’analyste — doté d’un modèle de raisonnement — dégage les tendances, le rédacteur met en forme. L’intérêt est autant pédagogique qu’opérationnel : quand le rapport final déçoit, vous savez immédiatement lequel des trois agents corriger.

from agents import Agent, Runner

agent_collecte = Agent(
    name="Collecteur de données",
    instructions="Collectez toutes les données nécessaires à l'analyse.",
    tools=[rechercher_dans_crm, executer_requete_sql],
    model="gpt-5.6-terra",
)

agent_analyse = Agent(
    name="Analyste",
    instructions="Analysez les données collectées et identifiez les tendances.",
    model="gpt-5.6-sol",  # Raisonnement avancé pour l'analyse
)

agent_redaction = Agent(
    name="Rédacteur",
    instructions="""Rédigez un rapport clair et structuré en français
    à partir de l'analyse fournie. Format : introduction, points clés, recommandations.""",
    model="gpt-5.6-terra",
)

async def pipeline_analyse(question: str):
    # Étape 1 : Collecter les données
    donnees = await Runner.run(agent_collecte, question)

    # Étape 2 : Analyser
    analyse = await Runner.run(
        agent_analyse,
        f"Analysez ces données : {donnees.final_output}"
    )

    # Étape 3 : Rédiger le rapport
    rapport = await Runner.run(
        agent_redaction,
        f"Rédigez un rapport basé sur cette analyse : {analyse.final_output}"
    )

    return rapport.final_output

Contrôler la profondeur de raisonnement

Toutes ces boucles ont un point commun : elles peuvent ne jamais s’arrêter. Le paramètre max_turns est votre garde-fou principal, et il se règle en fonction de l’ambition de la tâche. Trois tours suffisent à un agent censé répondre du premier coup ; vingt-cinq sont nécessaires à une exploration qui interroge plusieurs sources avant de conclure.

# Agent prudent : peu de tours
agent_simple = Agent(
    name="Agent simple",
    instructions="Répondez en un seul tour si possible.",
    model="gpt-5.6-terra",
)
result = await Runner.run(agent_simple, "Question simple", max_turns=3)

# Agent complexe : beaucoup de tours
agent_recherche = Agent(
    name="Chercheur approfondi",
    instructions="Explorez toutes les pistes avant de conclure.",
    tools=[rechercher_dans_crm, executer_requete_sql],
    model="gpt-5.6-terra",
)
result = await Runner.run(agent_recherche, "Analyse complète du Q1", max_turns=25)

Réglez cette valeur en observant vos traces plutôt qu’au jugé : si vos exécutions réelles tiennent en six tours, une limite à vingt-cinq ne protège plus de rien.

Points clés à retenir

  • Le pattern plan-execute sépare la planification (modèle de raisonnement) de l’exécution
  • Un agent auto-correcteur analyse ses erreurs et ajuste sa stratégie
  • Les chaînes d’agents spécialisés permettent des workflows complexes et maintenables
  • max_turns contrôle la profondeur de raisonnement et protège contre les boucles
  • Réservez les capacités de raisonnement avancé à la planification et à l’analyse