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 :
run.started;input.accepted;plan.created;tool.requested;policy.checked;approval.requested;approval.granted;tool.started;tool.completed;output.validated;decision.recorded;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_idsi une orchestration lance un sous-processus ;environment;tenant_refuniquement 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_idet le mêmerun_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é :
- présence de
run.started; - présence de
run.completed; - unicité des identifiants ;
- continuité de la séquence ;
- ordre des horodatages ;
- absence de champs
content,promptetresponse; - présence d’un contrôle de politique avant l’outil ;
- présence d’une approbation avant toute écriture.
Résultat :
| Trace | Événements | Erreurs |
|---|---|---|
| saine | 12 | 0 |
| dégradée | 11 | 2 |
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 :
| Mode | But | Effet externe |
|---|---|---|
| lecture | reconstruire la chronologie | aucun |
| simulation | recalculer règles et validations | aucun |
| réexécution contrôlée | reproduire une opération dans un environnement prévu | seulement 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ée | Nécessité | Accès | Rétention | Suppression |
|---|---|---|---|---|
| identifiants de trace | corrélation | exploitation | période définie | automatisée |
| décision de politique | audit | sécurité et produit | selon risque | procédure |
| approbation | preuve d’autorisation | rôles limités | selon finalité | procédure |
| métriques de durée | performance | exploitation | agrégation possible | purge du détail |
| contenu brut | absent par défaut | stockage séparé si justifié | minimale | prioritaire |
| secret ou jeton | interdit | aucun | aucune | blocage 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
- Recommandations de sécurité pour un système d’IA générative , consultée le 30 juillet 2026
- Sécuriser le traitement , consultée le 30 juillet 2026
- Recommandation relative aux mesures de journalisation , consultée le 30 juillet 2026
- OpenTelemetry semantic conventions 1.43.0 , consultée le 30 juillet 2026
- Semantic conventions for events , consultée le 30 juillet 2026
- NIST AI Resource Center , consultée le 30 juillet 2026