Journaliser un agent IA : 12 événements pour rejouer une exécution

Un protocole de journalisation d’agent IA avec 12 événements, références plutôt que contenus bruts et test local de replay avant mise en production.

Schéma Python : valider les données, exécuter un traitement borné et conserver une trace du résultat.

Journaliser un agent IA ne consiste pas à conserver chaque prompt et chaque réponse. Cette copie intégrale crée souvent un nouveau stock de données sensibles sans expliquer la décision importante : quel outil a été demandé, quelle règle a autorisé l’action, qui l’a approuvée et quel effet a réellement eu lieu.

Une trace utile doit permettre de reconstruire le chemin de l’exécution sans dépendre de la mémoire du modèle. Elle relie des événements ordonnés, des versions, des références de données, des décisions de politique et des résultats d’outils.

J’ai testé le contrat présenté ici sur un scénario local entièrement synthétique. La trace saine contient douze événements et ne produit aucune erreur de validation. Une copie volontairement dégradée contient onze événements : le contrôle détecte l’approbation absente avant une écriture et la présence d’un contenu brut interdit dans le journal. Aucun service externe, compte, document réel ou donnée client n’a été utilisé.

Réponse en bref

Pour journaliser un agent IA, commencez par douze événements :

  1. run.started ;
  2. input.accepted ;
  3. plan.created ;
  4. tool.requested ;
  5. policy.checked ;
  6. approval.requested ;
  7. approval.granted ;
  8. tool.started ;
  9. tool.completed ;
  10. output.validated ;
  11. decision.recorded ;
  12. run.completed.

Chaque événement possède au minimum un identifiant, un trace_id, un run_id, un numéro de séquence, un horodatage, un type, un acteur et un statut.

Les contenus complets restent absents par défaut. Le journal conserve plutôt un identifiant de document, une version, une empreinte ou une référence vers un stockage soumis à ses propres droits. Les secrets, jetons, mots de passe et raisonnements internes ne doivent jamais être enregistrés.

Ce qu’une bonne trace doit permettre de répondre

Un journal technique n’est utile que s’il répond à des questions d’exploitation.

Après une exécution, l’équipe doit pouvoir déterminer :

  • quelle version de l’agent et de sa politique a été utilisée ;
  • quelle entrée a déclenché le run ;
  • quels outils étaient disponibles ;
  • quel outil a été demandé ;
  • quels paramètres ont été validés ;
  • quelle règle a autorisé ou bloqué l’action ;
  • quelle personne a approuvé ;
  • quel système a été appelé ;
  • quel effet a été observé ;
  • quelle validation a accepté la sortie ;
  • pourquoi le run s’est arrêté ;
  • quelles données doivent être examinées en cas d’incident.

Si le journal contient des centaines de lignes mais ne permet pas de répondre à ces questions, il est verbeux, pas traçable.

Pourquoi le prompt complet est une mauvaise unité

Le prompt est une donnée d’entrée parmi d’autres. Un agent peut aussi utiliser :

  • une instruction système ;
  • un historique de conversation ;
  • un document récupéré ;
  • un résultat d’API ;
  • une mémoire de travail ;
  • un outil ;
  • une validation humaine ;
  • une règle déterministe.

Conserver uniquement le prompt utilisateur ne suffit donc pas à expliquer l’exécution. Conserver tout le contexte brut augmente au contraire le risque.

La documentation OpenTelemetry avertit que les messages d’entrée et de sortie des systèmes génératifs peuvent contenir des données sensibles ou personnelles. Elle prévoit des mécanismes de filtrage ou de troncature selon les instrumentations. Les conventions GenAI ont en outre été déplacées vers un dépôt dédié et plusieurs éléments restent en développement. Il faut donc versionner le vocabulaire utilisé au lieu de le présenter comme une norme figée.

Le contrat proposé dans cet article est volontairement applicatif. Il peut ensuite être relié à OpenTelemetry, à des logs JSON ou à un stockage interne.

Les quatre niveaux de la trace

Séparez quatre objets. Les mélanger rend les incidents difficiles à lire.

1. Le run

Le run est l’exécution complète déclenchée par une demande ou un événement.

Champs utiles :

  • run_id ;
  • agent_name ;
  • agent_version ;
  • policy_version ;
  • started_at ;
  • ended_at ;
  • final_status ;
  • stop_reason.

2. La trace

La trace relie les opérations d’un même parcours, y compris lorsque plusieurs services interviennent.

Champs utiles :

  • trace_id ;
  • parent_trace_id si une orchestration lance un sous-processus ;
  • environment ;
  • tenant_ref uniquement si nécessaire et pseudonymisé ;
  • correlation_ref.

Un identifiant de trace n’est pas une donnée métier. Il permet de rassembler des événements sans recopier le dossier traité.

3. L’opération

Une opération possède une durée et une frontière : appel de modèle, recherche, requête HTTP, exécution d’outil, validation.

OpenTelemetry utilise le concept de span pour ce type d’activité. Les conventions distinguent notamment traces, métriques, logs et événements. Le vocabulaire gen_ai.operation.name peut qualifier des opérations comme une conversation, une recherche, l’appel d’un agent ou l’exécution d’un outil, mais sa stabilité doit être vérifiée dans la version adoptée.

4. L’événement

Un événement marque un instant : demande d’approbation, changement d’état, blocage, erreur, décision.

La documentation OpenTelemetry recommande un événement lorsqu’une occurrence possède son propre horodatage ou représente un point de contrôle dans une opération plus longue. Le nom doit rester stable et ne pas intégrer de valeur dynamique.

Ainsi, utilisez approval.granted avec un champ approval_id, pas approval.granted.48219.

Le schéma minimal d’un événement

Voici une forme de départ :

{
  "schema_version": "1.0",
  "event_id": "evt-08",
  "trace_id": "trace-demo-001",
  "run_id": "run-demo-001",
  "sequence": 8,
  "occurred_at": "2026-07-30T12:00:07.000Z",
  "event_type": "tool.started",
  "actor": "agent",
  "status": "recorded",
  "tool_name": "demo.write",
  "side_effect": "write",
  "input_ref": null,
  "output_ref": null,
  "decision": null
}

Ce schéma ne stocke pas les paramètres bruts. Dans un système réel, une référence peut pointer vers une enveloppe chiffrée, soumise à des droits plus stricts et à une rétention différente.

Ajoutez seulement les champs utilisés pour filtrer, regrouper, corréler ou décider. Une collecte « au cas où » devient vite impossible à gouverner.

Les douze événements et leur rôle

1. run.started

Il fixe l’agent, sa version, l’environnement et la politique active. Sans ces versions, un même nom d’agent peut désigner deux comportements différents.

2. input.accepted

Il confirme que l’entrée a franchi les contrôles de format et de périmètre. Enregistrez une référence, une catégorie et le résultat des contrôles, pas le texte complet.

3. plan.created

Il décrit la structure prévue à un niveau court : nombre d’étapes, outils envisagés, budget et limite d’itérations. Il ne faut pas enregistrer un raisonnement interne détaillé.

4. tool.requested

Il indique quel outil a été choisi et pour quelle opération métier. Les paramètres sensibles restent dans une enveloppe séparée. Une version normalisée ou une empreinte peut permettre la comparaison.

5. policy.checked

Il conserve la décision indépendante du modèle :

  • allow ;
  • allow_with_approval ;
  • deny ;
  • defer.

Ajoutez la règle appliquée, sa version et un code de raison stable.

6. approval.requested

Il présente ce que la personne doit réellement décider : action, destination, portée, données concernées et possibilité d’annuler.

7. approval.granted

Il relie l’approbation à la demande, à l’identité autorisée et à la version des paramètres présentés. Une approbation sur une ancienne version ne doit pas autoriser une action modifiée.

8. tool.started

Il prouve que l’exécution a commencé après les contrôles. Pour une action avec effet, le validateur doit retrouver les décisions requises dans les événements précédents.

9. tool.completed

Il consigne le statut réel, la durée, l’identifiant retourné et une référence de sortie. Une réponse HTTP 200 ne signifie pas toujours que l’effet métier attendu a eu lieu. Ajoutez un contrôle de résultat lorsque le système le permet.

10. output.validated

Il décrit les validations appliquées à la sortie : schéma, domaines autorisés, références, doublons, règles métier ou relecture.

11. decision.recorded

Il explique la décision finale sous une forme courte : publier, conserver en brouillon, rejouer, escalader, annuler ou arrêter.

12. run.completed

Il clôt la trace avec un statut et un motif d’arrêt. Un run sans clôture doit être détecté par la supervision.

Le test local exécuté

Le prototype a construit une trace synthétique de douze événements. Chaque événement possédait :

  • un identifiant unique ;
  • le même trace_id et le même run_id ;
  • une séquence de 1 à 12 ;
  • un horodatage croissant ;
  • un type stable ;
  • un acteur ;
  • un statut ;
  • des références hachées uniquement lorsque nécessaires.

Le validateur a vérifié :

  1. présence de run.started ;
  2. présence de run.completed ;
  3. unicité des identifiants ;
  4. continuité de la séquence ;
  5. ordre des horodatages ;
  6. absence de champs content, prompt et response ;
  7. présence d’un contrôle de politique avant l’outil ;
  8. présence d’une approbation avant toute écriture.

Résultat :

TraceÉvénementsErreurs
saine120
dégradée112

Dans la trace dégradée, j’ai retiré approval.granted puis ajouté un champ de contenu brut à tool.completed. Le validateur a renvoyé :

approval_missing
raw_content_forbidden:evt-09

Ce test ne mesure pas la fiabilité d’un agent réel. Il prouve seulement que le contrat permet de détecter deux défauts précis avant de choisir une infrastructure d’observabilité.

Rejouer sans réexécuter l’effet

Un replay d’analyse ne doit pas envoyer à nouveau un message, modifier un dossier ou déclencher un paiement.

Séparez trois modes :

ModeButEffet externe
lecturereconstruire la chronologieaucun
simulationrecalculer règles et validationsaucun
réexécution contrôléereproduire une opération dans un environnement prévuseulement après autorisation dédiée

Le replay en lecture reconstitue l’ordre. Le replay en simulation vérifie si la politique actuelle aurait pris la même décision. La réexécution doit utiliser des données synthétiques, une destination de test ou une procédure spécifique.

Conservez la version historique de la politique. Sinon, l’équipe ne sait plus si elle examine la décision prise à l’époque ou celle qu’un nouveau système prendrait aujourd’hui.

Journaliser les refus

Les équipes observent souvent uniquement les actions réussies. Les refus contiennent pourtant une information importante :

  • donnée manquante ;
  • permission absente ;
  • destination interdite ;
  • budget dépassé ;
  • outil indisponible ;
  • entrée hors périmètre ;
  • approbation expirée ;
  • sortie invalide.

Un taux de refus sans codes de raison est difficile à interpréter. Un code de raison stable permet de savoir si le système protège correctement ou bloque inutilement un usage légitime.

Ne placez pas la donnée interdite elle-même dans le message d’erreur. Enregistrez la catégorie et la règle.

Matrice de données et de rétention

La CNIL recommande une journalisation proportionnée, exploitable et protégée. Sa recommandation générale évoque une durée de six mois à un an pour la traçabilité des accès et actions des utilisateurs habilités, tout en demandant une analyse au cas par cas et une justification des durées plus longues. Ce repère ne doit pas être copié automatiquement à tout journal d’agent.

Construisez votre propre matrice :

DonnéeNécessitéAccèsRétentionSuppression
identifiants de tracecorrélationexploitationpériode définieautomatisée
décision de politiqueauditsécurité et produitselon risqueprocédure
approbationpreuve d’autorisationrôles limitésselon finalitéprocédure
métriques de duréeperformanceexploitationagrégation possiblepurge du détail
contenu brutabsent par défautstockage séparé si justifiéminimaleprioritaire
secret ou jetoninterditaucunaucuneblocage immédiat

Les journaux doivent aussi être protégés contre la modification, les accès illégitimes et la saturation. L’ANSSI recommande de pouvoir reconstituer les traitements d’un système d’IA générative, notamment les requêtes, traitements d’entrée, appels aux extensions ou données additionnelles, filtres de sortie et réponses, avec un niveau de granularité adapté et une protection des contenus sensibles.

Alertes utiles

Une alerte doit conduire à une action. Commencez par :

  • run sans clôture après un délai ;
  • écriture sans approbation antérieure ;
  • outil non déclaré dans la version active ;
  • répétition au-delà du budget ;
  • hausse d’un code de refus ;
  • erreur d’authentification ;
  • destination nouvelle ;
  • version de politique inconnue ;
  • contenu brut détecté ;
  • taux d’erreur supérieur à la référence du pilote.

Évitez une alerte sur chaque réponse différente. Un système probabiliste produit des variations. Les alertes doivent viser les contrats, les effets et les risques.

Les volumes et durées du journal peuvent aussi alimenter un calcul du coût de l’agent IA par tâche acceptée. Gardez toutefois les métriques financières séparées des contenus sensibles et rapprochez-les des rapports de facturation.

Passer du prototype à OpenTelemetry

Le schéma local peut être adapté à OpenTelemetry :

  • le run ou l’appel d’agent devient une trace ou un span parent ;
  • les appels de modèle et d’outil deviennent des spans ;
  • les demandes d’approbation et décisions deviennent des événements ;
  • les durées, erreurs et volumes deviennent des métriques ;
  • les lignes de diagnostic restent des logs structurés.

Ne copiez pas automatiquement tous les attributs GenAI. La documentation officielle consultée le 30 juillet 2026 indique que les conventions génératives ont été déplacées vers un dépôt dédié. Plusieurs champs du registre historique sont marqués comme déplacés ou en développement.

Avant l’instrumentation, figez :

  • la version des conventions ;
  • les champs activés ;
  • les règles de filtrage ;
  • les limites de taille ;
  • l’échantillonnage ;
  • les droits d’accès ;
  • la rétention ;
  • la procédure de migration.

La compatibilité s’organise. Elle ne se déduit pas du préfixe gen_ai.

Checklist avant un pilote

  • un propriétaire du journal est nommé ;
  • les questions d’incident sont écrites ;
  • les types d’événements sont versionnés ;
  • les identifiants corrèlent sans copier le dossier ;
  • les actions avec effet exigent une preuve d’autorisation ;
  • les contenus bruts sont absents par défaut ;
  • les secrets sont bloqués avant écriture ;
  • les durées de conservation sont justifiées ;
  • les accès au journal sont limités ;
  • une alerte existe pour les traces incomplètes ;
  • le replay en lecture est séparé de la réexécution ;
  • un test dégradé vérifie que les contrôles échouent.

La méthode contre la prompt injection complète cette checklist pour les agents exposés à des sources non fiables. Le choix entre MCP et API aide à placer la frontière entre l’agent et le système métier. Pour transformer les traces en décisions de pilotage, définissez aussi des SLO de fiabilité pour l’agent IA.

Limites

Le contrat de douze événements est un modèle applicatif, pas une norme. Il a été testé sur une trace synthétique courte. Il ne prouve ni la résistance à une attaque, ni la conformité réglementaire, ni l’adéquation à un système distribué.

La journalisation peut elle-même traiter des données personnelles, révéler l’activité de personnes habilitées ou exposer des informations sensibles. La finalité, les champs, les accès, l’analyse et la conservation doivent être validés dans le contexte réel.

Les conventions OpenTelemetry évoluent. Les noms et niveaux de stabilité doivent être vérifiés au moment de l’implémentation. Une trace complète n’empêche aucune action : les permissions, validations indépendantes, limites, tests et procédures d’arrêt restent nécessaires.

À propos de l’auteur

Je suis Ayoub Kahouadji, développeur Python, formateur et consultant IA. Je travaille sur des workflows où chaque effet doit être relié à une entrée, une règle, une validation et une preuve exploitable.

Prochaine étape

Prenez un seul workflow en lecture seule. Écrivez ses événements, exécutez un cas sain, retirez volontairement un contrôle puis vérifiez que le validateur bloque la trace. Lorsque le contrat est stable, la page automatisation IA et Python présente l’accompagnement pour passer du prototype à un système maintenable.

Sources vérifiées

Rechercher

La recherche porte uniquement sur les contenus publiés. Entrée ouvre le premier résultat ; les flèches permettent de choisir.