Aller au contenu principal

Tool Search : outils dynamiques

Tool Search : outils dynamiques

Quand votre agent dispose de dizaines ou centaines de tools, les envoyer tous 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 :

# 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 :

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 :

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="o4-mini",  # 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.3",
    )

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

Pattern : tools dynamiques selon le contexte

Vous pouvez aussi adapter les tools disponibles selon l’utilisateur connecté :

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.3",
    )

Optimiser les descriptions de tools

La qualité des descriptions de vos tools impacte directement la pertinence de la sélection :

# 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.

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 o4-mini pour le routage rapide et gpt-5.3 pour l’exécution