Aller au contenu principal

Module 9 — Observabilité et journalisation des décisions

Un agent en production sans observabilité n'est pas un agent, c'est un panier percé. La différence entre une équipe qui améliore son agent et une équipe qui l'abandonne se joue ici : la première a une trace lisible, la seconde regarde son solde de facturation grimper sans savoir pourquoi. Ce module dit ce qu'il faut enregistrer, comment le lire et comment comparer deux mises en œuvre — celle du fil rouge et sa version LangGraph.

Ce qu'il faut enregistrer, systématiquement

Pour chaque exécution d'agent, un journal structuré capture huit informations minimales.

L'identifiant de l'exécution — un UUID stable — permet de relier une trace à un incident client. La question initiale in extenso, avec les métadonnées de l'appelant. Le plan produit s'il y en a eu un. Pour chaque étape : la pensée, l'outil appelé avec ses arguments, l'observation avec sa taille, la durée et le coût en jetons. La sortie finale ou le motif d'arrêt (budget épuisé, exception, finish). Le coût total en jetons et en euros. Le statut de vérification — a-t-il passé les tests du module 6.

Ce n'est pas un journal texte ; c'est un enregistrement JSON qu'on peut interroger. Sur le fil rouge :

enregistrement = {
"id": "exec_2c8f...",
"question": "quels concurrents ont ajoute un tableau Kanban en 2025 ?",
"modele": "gpt-4o",
"etapes": [
{"n": 1, "pensee": "...", "outil": "chercher_web",
"args": {"requete": "..."}, "obs_taille": 812,
"duree_ms": 950, "jetons": 640},
# ...
],
"sortie": "...",
"statut": "finish",
"cout_eur": 0.29,
"verifie": True,
}

Un enregistrement de ce type par exécution, empilé dans un fichier JSONL ou une table agent_runs, permet toutes les analyses qui suivent.

Coût par étape et où il fuit

Sur les trente exécutions du fil rouge évaluées, le coût moyen se répartit ainsi :

PostePart du coûtNote
Contexte du système et outils rediffusé à chaque étape38 %fixe, dominant
Observations issues des pages lues27 %compressible par module 4
Pensées et actions14 %difficilement compressible
Recherches web (chercher_web)10 %dépend de la profondeur
Vérification et critique (module 6)11 %activable ou non

La ligne qui saute est la première : près de 40 % de la dépense sert à rediffuser le prompt système et la palette d'outils à chaque étape. C'est un coût structurel qu'on ne peut pas éliminer sans mise en cache de contexte — que l'API des modèles récents propose désormais, souvent avec 80 % de réduction sur les jetons rediffusés. Activer cette mise en cache est le levier d'économie numéro un.

Rejeu déterministe

Une exécution qu'on ne peut pas rejouer ne peut pas être déboguée. Le rejeu déterministe suppose deux choses. D'une part, on archive les observations — la page lue à l'étape 4, avec son contenu exact au moment de la lecture, pas l'URL. D'autre part, on fixe la semence du modèle si elle est exposée, ou à défaut on accepte la variance résiduelle en la mesurant.

Le rejeu sert à deux choses. Corriger sans dépenser : on change une description d'outil ou une consigne système, on rejoue la trace en simulant les mêmes observations, on regarde si l'agent prend cette fois la bonne décision. Comparer deux configurations : on rejoue le même jeu de trente questions sur deux prompts et on chiffre lequel gagne.

Sur le fil rouge, un script de rejoue en trente lignes suffit. Il lit un JSONL, remplace les appels réels d'outils par des lectures dans le journal, et compare la sortie finale au verdict humain.

Comparer avec la version LangGraph

Le module 9 propose une comparaison éclairante : la même tâche, implémentée avec LangGraph. LangGraph modélise l'agent comme un graphe de nœuds — un nœud « raisonner », un nœud « outil », un nœud « vérifier » — et un état partagé qui circule.

Trois différences se voient à l'usage.

Le graphe rend explicites les transitions. Là où notre boucle Python enchaîne implicitement pensée-action-observation, LangGraph a une arête raisonner → outil → raisonner visible dans le code. On peut plus facilement ajouter un nœud « vérifier avant sortie » sans casser le reste. La lisibilité gagne.

L'état partagé impose la discipline. Ce qui traverse les nœuds est un dictionnaire typé (TypedDict), ce qui interdit d'accumuler des variables un peu partout. C'est utile pour les agents complexes ; c'est une lourdeur pour l'agent de trois nœuds.

L'observabilité vient avec la bibliothèque. LangGraph intégré à LangSmith enregistre chaque nœud avec son entrée, sa sortie, son coût. En version Python pure, il faut écrire soi-même le journal ci-dessus. C'est probablement la meilleure raison d'adopter LangGraph, plus que la modélisation du graphe.

Sur les trente questions du fil rouge, les deux versions donnent des résultats à moins d'un point l'un de l'autre. Le choix n'est donc pas de qualité, c'est un choix de maintenabilité et d'écosystème. Écrire soi-même est très bien pour comprendre et pour un projet unique ; LangGraph gagne dès qu'on maintient trois agents ou plus.

Tableaux de bord et alertes

Trois indicateurs suffisent pour un tableau de bord agent.

Le taux de bonnes réponses — pourcentage d'exécutions dont la sortie passe la vérification humaine sur un échantillon échantillonné hebdomadaire. Une chute de plus de cinq points déclenche une enquête.

Le coût moyen par exécution — en euros, avec une distribution p50, p90, p99. Le p99 est le premier à réagir en cas de boucle infinie non détectée.

Le taux d'arrêt par budget — proportion d'exécutions qui se terminent par « budget épuisé » plutôt que par finish. Un taux supérieur à 5 % signale une boucle sur soi (module 8) ou une condition d'arrêt trop stricte.

Une alerte automatique sur ces trois lignes suffit à détecter les régressions avant que la facture ne monte. Le cours 20 sur les opérations d'apprentissage automatique décrit une architecture de collecte compatible ; le journal JSONL de ce module s'y insère naturellement.

En résumé

  • Un enregistrement JSON par exécution, avec pensée, outil, arguments, observation, coût et statut, est le socle de tout le reste.
  • Le coût structurel du prompt rediffusé domine ; activer la mise en cache de contexte est le levier d'économie principal.
  • Le rejeu déterministe exige d'archiver les observations et rend possible la correction sans dépenser.
  • LangGraph apporte lisibilité et observabilité intégrée ; sur ce cours, notre version Python pure donne la même qualité, à maintenabilité près.

Module suivant : le projet complet — assembler le tout, évaluer sur trente questions, mesurer, comparer, décider si l'agent est prêt pour la production.