Aller au contenu principal

Tracing et observabilité

Mis à jour le 29 juillet 2026

Tracing et observabilité

Un agent en production est une boîte noire si vous ne tracez pas ses actions. Quand un client se plaint d’une réponse absurde, vous n’avez ni la requête exacte, ni les tools appelés, ni les valeurs qu’ils ont renvoyées. Le tracing du SDK enregistre chaque étape de l’exécution : les appels au modèle, les tools utilisés, les handoffs, et les guardrails. C’est votre outil principal pour débugger, optimiser et auditer vos agents.

Tracing intégré au SDK

Bonne nouvelle : vous n’avez rien à activer. Le SDK trace automatiquement chaque exécution, et par défaut les traces sont envoyées au dashboard OpenAI sur platform.openai.com. L’agent ci-dessous, écrit sans la moindre instruction de tracing, produit déjà une trace exploitable.

from agents import Agent, Runner, function_tool

@function_tool
def rechercher_produit(nom: str) -> str:
    """Recherche un produit dans le catalogue."""
    return f"Produit trouvé : {nom}, prix 29.99€"

agent = Agent(
    name="Agent boutique",
    instructions="Vous aidez les clients à trouver des produits.",
    tools=[rechercher_produit],
    model="gpt-5.6-terra",
)

# Chaque exécution crée automatiquement une trace
result = Runner.run_sync(agent, "Cherchez le laptop pro")

Rendez-vous sur le dashboard pour voir la trace complète : durée, tokens consommés, tools appelés, et réponse finale.

Nommer les traces

Passé quelques centaines d’exécutions, le dashboard devient une liste indifférenciée. Donnez donc des noms significatifs à vos traces pour les retrouver facilement — le nom d’un parcours métier vaut mieux qu’un identifiant technique.

from agents import trace

with trace("commande-client-premium"):
    result = await Runner.run(
        agent,
        "Je veux commander 5 laptops pour mon équipe",
    )

Le nom de la trace apparaît dans le dashboard et facilite le filtrage.

Traces imbriquées

Pour les workflows complexes, imbriquez les traces. Un traitement de commande qui enchaîne compréhension, traitement et confirmation devient alors lisible par étape : vous voyez immédiatement laquelle des trois consomme les deux tiers de la latence.

from agents import trace, Runner

async def traiter_commande(message: str):
    with trace("workflow-commande"):
        # Étape 1 : Comprendre la demande
        with trace("etape-1-compréhension"):
            result_comprehension = await Runner.run(agent_triage, message)

        # Étape 2 : Traiter la commande
        with trace("etape-2-traitement"):
            result_traitement = await Runner.run(
                agent_commande,
                result_comprehension.to_input_list(),
            )

        # Étape 3 : Confirmer
        with trace("etape-3-confirmation"):
            result_final = await Runner.run(
                agent_confirmation,
                result_traitement.to_input_list(),
            )

    return result_final.final_output

Dans le dashboard, vous verrez la trace parent avec trois sous-traces, chacune avec ses propres métriques.

Custom trace processors

Le dashboard OpenAI est pratique, mais votre équipe d’exploitation surveille probablement déjà tout le reste ailleurs. Pour envoyer les traces vers votre propre système d’observabilité, écrivez un processeur : il reçoit les événements de début et de fin, aussi bien pour la trace complète que pour chaque span intermédiaire.

from agents.tracing import TracingProcessor, Span

class MonProcesseurDeTraces(TracingProcessor):
    def on_trace_start(self, trace):
        print(f"[TRACE START] {trace.name} - {trace.trace_id}")

    def on_trace_end(self, trace):
        duree = trace.end_time - trace.start_time
        print(f"[TRACE END] {trace.name} - durée: {duree:.2f}s")

    def on_span_start(self, span: Span):
        print(f"  [SPAN START] {span.name}")

    def on_span_end(self, span: Span):
        print(f"  [SPAN END] {span.name}")

    def shutdown(self):
        pass

    def force_flush(self):
        pass

# Enregistrer le processeur
from agents.tracing import add_trace_processor
add_trace_processor(MonProcesseurDeTraces())

Exporter vers des systèmes externes

Le passage à un outil réel demande simplement de reformater les données au format attendu. Voici comment intégrer avec des outils d’observabilité courants, ici Datadog : on ne conserve que l’identifiant, le nom, le service et la durée en millisecondes, et on laisse les autres callbacks vides puisqu’ils ne servent pas ce besoin.

import json
import logging
from agents.tracing import TracingProcessor

logger = logging.getLogger("agent-traces")

class DatadogTraceProcessor(TracingProcessor):
    """Envoie les traces vers Datadog APM."""

    def on_trace_end(self, trace):
        # Format compatible Datadog
        span_data = {
            "trace_id": trace.trace_id,
            "name": trace.name,
            "service": "agent-openai",
            "duration_ms": (trace.end_time - trace.start_time) * 1000,
        }
        logger.info(json.dumps(span_data))
        # En production : envoi via ddtrace

    def on_span_start(self, span):
        pass

    def on_span_end(self, span):
        pass

    def shutdown(self):
        pass

    def force_flush(self):
        pass

Désactiver le tracing

Il existe un cas où le tracing gêne plus qu’il n’aide : une suite de tests qui exécute des centaines d’agents fictifs et pollue votre dashboard. Dans les tests ou en développement local, vous pouvez donc le désactiver, globalement ou pour une seule exécution.

from agents.tracing import set_tracing_disabled

# Désactiver complètement
set_tracing_disabled(True)

# Ou par exécution
with trace("test", disabled=True):
    result = await Runner.run(agent, "Message de test")

Métriques clés à surveiller

Reste à savoir quoi regarder. En production, six indicateurs suffisent à qualifier la santé d’un agent. La latence totale — le temps entre la requête et la réponse finale — est celle que vos utilisateurs ressentent ; elle s’explique le plus souvent par le nombre de tours, c’est-à-dire le nombre de fois où la boucle agent s’est exécutée. Les tokens consommés, en entrée comme en sortie et par exécution, portent quant à eux votre facture.

Les trois autres relèvent de la qualité. Le taux d’échec des tools, soit le pourcentage de tools qui retournent une erreur, révèle une API tierce instable ou des arguments mal générés. Le taux de déclenchement des guardrails mesure la fréquence des blocages : une hausse brutale signale soit une attaque, soit un guardrail devenu trop strict. Enfin, la distribution des handoffs vous dit quel agent répond le plus souvent — et donc si votre triage envoie bien les demandes là où elles doivent aller.

Points clés à retenir

  • Le SDK trace automatiquement chaque exécution vers le dashboard OpenAI
  • Utilisez with trace("nom") pour nommer et imbriquer vos traces
  • Les custom TracingProcessor permettent d’exporter vers Datadog, Grafana, etc.
  • Surveillez la latence, les tokens, le taux d’erreur des tools et les guardrails
  • Désactivez le tracing dans les tests avec set_tracing_disabled(True)