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
)
Activer Tool Search
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