Aller au contenu principal

Tool Search : outils dynamiques

Mis à jour le 29 juillet 2026

Tool Search : outils dynamiques

Un agent de démonstration vit très bien avec trois ou quatre tools. Un agent d’entreprise, lui, finit toujours par en accumuler des dizaines, parfois des centaines : facturation, RH, CRM, documents, planning. À ce stade, envoyer l’intégralité du catalogue au modèle à chaque requête devient inefficace et coûteux en tokens. Le Tool Search résout ce problème en sélectionnant dynamiquement les tools pertinents pour chaque requête.

Le problème des nombreux tools

Imaginons un agent avec 50 tools. À chaque appel API, les schémas de ces 50 tools sont envoyés dans le prompt. Cela consomme des milliers de tokens et peut confondre le modèle : plus la liste est longue, plus les descriptions se ressemblent, et plus le modèle hésite entre deux outils voisins. Le coût grimpe donc pendant que la précision baisse — la pire combinaison possible.

# Problème : trop de tools
agent = Agent(
    name="Super agent",
    instructions="Vous pouvez tout faire.",
    tools=[tool_1, tool_2, tool_3, ... , tool_50],  # 50 tools = beaucoup de tokens
)

Le Tool Search utilise un index sémantique pour sélectionner les tools pertinents selon la requête. Vous déclarez vos tools normalement, et c’est le paramètre tool_use_behavior="auto" qui laisse le modèle piocher dans le catalogue au lieu de tout charger frontalement. Dans l’exemple ci-dessous, une demande de relance de paiement ne mobilisera pas les tools RH, et inversement.

from agents import Agent, Runner, function_tool

# Définir de nombreux tools
@function_tool
def creer_facture(client: str, montant: float) -> str:
    """Crée une facture pour un client."""
    return f"Facture créée pour {client}: {montant}€"

@function_tool
def envoyer_relance(facture_id: str) -> str:
    """Envoie une relance de paiement pour une facture impayée."""
    return f"Relance envoyée pour la facture {facture_id}"

@function_tool
def generer_rapport_rh(mois: str) -> str:
    """Génère un rapport des ressources humaines pour un mois donné."""
    return f"Rapport RH généré pour {mois}"

@function_tool
def planifier_entretien(candidat: str, date: str) -> str:
    """Planifie un entretien d'embauche avec un candidat."""
    return f"Entretien planifié avec {candidat} le {date}"

# Beaucoup d'autres tools...

agent = Agent(
    name="Agent entreprise",
    instructions="Vous gérez les opérations de l'entreprise.",
    tools=[
        creer_facture,
        envoyer_relance,
        generer_rapport_rh,
        planifier_entretien,
        # ... 50 autres tools
    ],
    tool_use_behavior="auto",  # Le modèle sélectionne dynamiquement
)

Pattern : sélection manuelle de tools

Si vous voulez un contrôle total sur la sélection des tools, implémentez votre propre logique. Le principe est simple : un petit agent routeur lit la demande et se contente de nommer le domaine concerné, puis vous construisez à la volée l’agent spécialisé avec les seuls tools de ce domaine. Une phrase comme « relancez la facture F-2026-114 » sort du routeur avec la réponse comptabilite, et l’agent d’exécution ne verra jamais les tools RH.

from agents import Agent, Runner, function_tool

# Grouper les tools par domaine
tools_comptabilite = [creer_facture, envoyer_relance]
tools_rh = [generer_rapport_rh, planifier_entretien]

# Un agent routeur qui sélectionne le domaine
routeur = Agent(
    name="Routeur",
    instructions="""Déterminez le domaine de la demande.
    Répondez uniquement 'comptabilite' ou 'rh'.""",
    model="gpt-5.6-terra",  # Rapide et pas cher pour le routage
    output_type=str,
)

async def traiter_requete(message: str):
    # Étape 1 : déterminer le domaine
    route = await Runner.run(routeur, message)
    domaine = route.final_output.strip().lower()

    # Étape 2 : créer l'agent spécialisé avec les bons tools
    if domaine == "comptabilite":
        tools = tools_comptabilite
        instructions = "Vous gérez la comptabilité de l'entreprise."
    elif domaine == "rh":
        tools = tools_rh
        instructions = "Vous gérez les ressources humaines."
    else:
        tools = tools_comptabilite + tools_rh
        instructions = "Vous gérez les opérations de l'entreprise."

    agent_specialise = Agent(
        name=f"Agent {domaine}",
        instructions=instructions,
        tools=tools,
        model="gpt-5.6-terra",
    )

    result = await Runner.run(agent_specialise, message)
    return result.final_output

Le couple gpt-5.6-terra pour le routage et gpt-5.6-terra pour l’exécution appartient à la génération précédente de modèles ; le raisonnement du principe reste identique avec la famille GPT-5.6, où c’est le réglage d’effort qui distingue le routeur rapide de l’exécutant.

Pattern : tools dynamiques selon le contexte

La sélection ne dépend pas seulement de la question posée : elle dépend aussi de qui la pose. Vous pouvez adapter les tools disponibles selon l’utilisateur connecté, ce qui fait d’une pierre deux coups — moins de tokens envoyés, et surtout un cloisonnement des droits imposé avant même que le modèle raisonne. Un employé du service commercial obtient les tools de devis, mais supprimer_compte n’existe tout simplement pas dans son agent.

from dataclasses import dataclass

@dataclass
class ContexteUtilisateur:
    role: str  # "admin", "manager", "employee"
    departement: str

def obtenir_tools_pour_role(ctx: ContexteUtilisateur) -> list:
    """Retourne les tools autorisés selon le rôle."""
    tools_de_base = [rechercher_document, consulter_planning]

    if ctx.role in ("admin", "manager"):
        tools_de_base.extend([creer_facture, generer_rapport_rh])

    if ctx.role == "admin":
        tools_de_base.extend([modifier_permissions, supprimer_compte])

    if ctx.departement == "commercial":
        tools_de_base.extend([rechercher_client, creer_devis])

    return tools_de_base

async def creer_agent_pour_utilisateur(ctx: ContexteUtilisateur):
    tools = obtenir_tools_pour_role(ctx)
    return Agent(
        name="Agent personnalisé",
        instructions=f"Vous assistez un {ctx.role} du département {ctx.departement}.",
        tools=tools,
        model="gpt-5.6-terra",
    )

Optimiser les descriptions de tools

Quelle que soit la mécanique de sélection retenue, elle s’appuie sur un seul matériau : le texte de vos descriptions. La qualité de ces descriptions impacte donc directement la pertinence de la sélection. Comparez les deux déclarations suivantes : la première ne dit rien de la situation d’usage, la seconde nomme les entrées, le résultat et le moment où l’on s’en sert.

# Mauvais : description vague
@function_tool
def process_data(data: str) -> str:
    """Traite les données."""
    return "OK"

# Bon : description précise et contextualisée
@function_tool
def calculer_marge_brute(chiffre_affaires: float, cout_production: float) -> str:
    """Calcule la marge brute en pourcentage à partir du chiffre d'affaires
    et du coût de production. Utile pour l'analyse financière trimestrielle."""
    marge = ((chiffre_affaires - cout_production) / chiffre_affaires) * 100
    return f"Marge brute : {marge:.1f}% (CA: {chiffre_affaires}€, coûts: {cout_production}€)"

Une bonne description de tool est comme une bonne docstring : elle explique quand utiliser le tool, pas seulement ce qu’il fait. Prenez dix minutes pour relire les descriptions de votre agent en vous demandant, pour chacune, si un collègue saurait choisir le bon outil en ne lisant que cette phrase. C’est exactement l’exercice que fait le modèle.

Points clés à retenir

  • Le Tool Search sélectionne dynamiquement les tools pertinents pour chaque requête
  • Avec beaucoup de tools, un routeur agent peut déterminer le domaine en amont
  • Adaptez les tools disponibles selon le rôle et le contexte de l’utilisateur
  • La qualité des descriptions de tools impacte la précision de la sélection
  • Utilisez un modèle léger pour le routage rapide et un modèle capable pour l’exécution