Audit logs pour les agents IA : comment reconstruire la chaîne de décisions en production

Audit trail pratique en production : policy decisions, stop reasons, actor/scope, redaction, immutable storage et investigation rapide des incidents.
Sur cette page
  1. L’idée en 30 secondes
  2. Le problème
  3. La solution
  4. Audit logs ≠ debug logs
  5. Composants du contrôle d’audit
  6. À quoi ça ressemble dans l’architecture
  7. Exemple
  8. En code, ça ressemble à ça
  9. À quoi ça ressemble pendant l’exécution
  10. Scénario 1 : policy stop
  11. Scénario 2 : approval_required
  12. Scénario 3 : allow + exécution
  13. Erreurs typiques
  14. Auto-vérification
  15. FAQ
  16. Où Audit Logs se place dans le système
  17. Pages liées

L’idée en 30 secondes

Audit logs est le journal runtime centralisé des décisions de l’agent : ce qui s’est passé, pourquoi, et qui l’a initié.

Quand c’est nécessaire :
quand un agent travaille avec tools, approval, limites, et que tout incident doit être analysé sur des faits, pas des hypothèses.

Le problème

Sans audit logs, l’équipe voit les symptômes, mais pas la chaîne de décisions. En démo, c’est presque invisible. En production, chaque incident devient un "guesswork" manuel.

Conséquences typiques :

  • on ne sait pas clairement pourquoi il y a eu deny ou stop
  • impossible de reconstruire quel step exact a produit des side effects (changements d’état)
  • difficile d’expliquer au client qui a changé une policy ou activé une limite, et quand

Analogie : c’est comme enquêter sur un accident sans enregistrement vidéo. Il y a le résultat, mais pas de séquence d’événements vérifiable.

Et chaque minute sans audit trail de qualité allonge l’incident et augmente le temps de recovery.

La solution

La solution est d’ajouter une couche audit centralisée dans runtime qui écrit à la fois les décisions policy et le fait d’exécution de l’action. Chaque step de l’agent log un événement standardisé : decision, reason, action, scope, actor, timestamp.

Pour runtime, un modèle de décision unique est essentiel :

  • allow
  • stop
  • approval_required

Il est aussi important de logguer non seulement les blocages, mais aussi l’exécution réussie. Sinon, en incident, on voit "pourquoi c’est bloqué", mais pas "ce qui a réellement été exécuté".

Audit logs ≠ debug logs

Ce sont des objectifs différents :

  • Audit logs : journal structuré et reproductible des décisions et actions.
  • Debug logs : détails techniques pour diagnostic local.

L’un sans l’autre ne suffit pas :

  • sans audit logs, il n’y a pas d’historique de décisions fiable juridiquement et opérationnellement
  • sans debug logs, le débogage local des détails d’implémentation est difficile

Exemple :

  • audit: decision=stop, reason=rate_limited_tenant, tenant_id=t_42, action=crm.search
  • debug: stack trace, retries internes, latence des dépendances individuelles

Composants du contrôle d’audit

Ces composants travaillent ensemble à chaque step de l’agent.

ComposantCe qu’il contrôleMécaniques clésPourquoi
Event identityUnicité de l’événementrun_id + step_id
event timestamp
Permet de reconstruire la séquence complète sans trous
Decision contextRaison de la décision policydecision / reason
policy layer name
Explique pourquoi l’action a été exécutée ou stoppée
Action contextCe que l’agent a fait exactementaction + action_key
scope (user/tenant/global)
Relie la policy à l’action réellement exécutée
Data safetyRisque de fuite de données sensiblesargs hash
redaction policy
Préserve la valeur d’audit sans secrets bruts ni PII
Immutable storageIntégrité de l’auditappend-only sink
retention + access control
Protège le journal contre l’édition silencieuse après incident

Exemple d’alerte :

Slack: 🛑 Support-Agent decision=stop, reason=approval_required, tenant=t_42, run_id=run_981.

À quoi ça ressemble dans l’architecture

La couche audit est dans la runtime loop et enregistre les décisions avant et après l’exécution de l’action suivante. Chaque outcome (allow, stop, approval_required) est écrit dans un audit trail centralisé. Ici, policy layer est une couche logique dans runtime, pas un service séparé.

Chaque step passe par ce flow avant exécution : runtime n’exécute pas l’action directement tant que policy n’a pas renvoyé de décision et que l’événement n’est pas enregistré dans l’audit.

Résumé du flow :

  • Runtime prépare l’action suivante de l’agent
  • Policy renvoie allow, stop ou approval_required
  • Runtime log un pre-event avec decision et reason
  • si l’action s’exécute, runtime log un post-event avec result
  • les deux types d’événements sont disponibles pour recherche, alerting et investigation

Exemple

L’agent support reçoit une demande refund.create. Policy renvoie approval_required.

Résultat :

  • l’exécution ne démarre pas sans approbation
  • l’audit montre decision=approval_required, actor, scope, action_key
  • après approbation, l’audit montre un événement séparé decision=allow et le résultat d’exécution

Audit logs réduit le temps d’investigation d’incident au niveau des steps runtime, pas après collecte manuelle d’artefacts.

En code, ça ressemble à ça

Le schéma simplifié ci-dessus montre le flow principal. Point critique : les événements audit doivent être structurés et cohérents par schéma, sinon la recherche d’incident casse.

Exemple de configuration audit :

YAML
audit:
  sink: append_only
  retention_days: 180
  redact_fields: ["email", "phone", "card_number"]
  hash_args: true
  sign_events: true
PYTHON
action = planner.next(state)
action_key = make_action_key(action.name, action.args)
decision = policy.evaluate(action, state.user_context)

base_event = {
    "run_id": run_id,
    "step_id": state.step,
    "tenant_id": state.tenant_id,
    "action": action.name,
    "action_key": action_key,
    "timestamp": clock.iso(),
}

audit.log(
    **base_event,
    phase="pre_exec",
    decision=decision.outcome,
    reason=decision.reason,
    args_hash=hash_args(action.args),
)

if decision.outcome == "approval_required":
    # approval resume flow est loggué comme step runtime séparé :
    # approval_required -> approval_granted -> allow -> result
    return stop("approval_required")

if decision.outcome == "stop":
    return stop(decision.reason)

result = executor.execute(action)

audit.log(
    **base_event,
    phase="post_exec",
    decision=decision.outcome,
    reason=decision.reason,
    result=result.status,
)

return result

À quoi ça ressemble pendant l’exécution

Scénario 1 : policy stop

  1. Runtime prépare l’action crm.search.
  2. Policy renvoie stop (reason=rate_limited_tenant).
  3. Runtime écrit le pre-event dans l’audit.
  4. L’action n’est pas exécutée.
  5. L’équipe voit immédiatement le stop reason dans les logs.

Scénario 2 : approval_required

  1. Runtime prépare refund.create.
  2. Policy renvoie approval_required.
  3. Runtime écrit le pre-event et stoppe l’exécution.
  4. Après décision humaine, un step séparé démarre.
  5. L’audit montre tout le chemin : approval_required -> allow -> result.

Scénario 3 : allow + exécution

  1. Runtime prépare l’action suivante.
  2. Policy renvoie allow.
  3. Runtime exécute l’action.
  4. Écrit un post-event avec result.
  5. Le journal contient décision et résultat d’exécution.

Erreurs typiques

  • logguer seulement stop, mais pas allow
  • stocker args bruts sans redaction/hash
  • ne pas avoir de action_key stable pour déduplication
  • mélanger audit et debug dans un seul texte non structuré
  • ne pas enregistrer actor pour changements de policy et actions opérateur
  • permettre la modification/suppression rétroactive d’événements audit

Résultat : le journal existe, mais en incident il ne donne pas de vue vérifiable.

Auto-vérification

Vérification rapide d’audit logging avant lancement en production :

Progression: 0/8

⚠ Les contrôles de governance de base manquent

Avant la production, il faut au minimum le contrôle d'accès, des limites, des audit logs et un arrêt d'urgence.

FAQ

Q : Quelle différence entre audit logs et traces ?
A : Trace montre le chemin technique d’exécution, audit log montre décisions policy et actions en termes de qui/quoi/pourquoi. En incident, on a généralement besoin des deux.

Q : Peut-on logguer les args complets pour le confort ?
A : Mieux vaut éviter. En production, il est plus sûr de stocker hash ou version redacted pour éviter les fuites de secrets et PII.

Q : Quel est le minimum de champs obligatoires ?
A : Minimum : run_id, step_id, decision, reason, action, action_key, scope, timestamp.

Q : Quand écrire l’événement : avant ou après exécution ?
A : Les deux sont importants : pre-event fixe la décision, post-event fixe le fait et le résultat de l’exécution.

Q : Où stocker les audit logs ?
A : Dans un stockage centralisé append-only avec accès contrôlé, retention et recherche rapide par run_id/tenant_id/reason.

Où Audit Logs se place dans le système

Audit logs est la couche de transparence de base dans Agent Governance. Avec RBAC, limites, budget controls, approval et kill switch, il donne un comportement agent contrôlable et explicable en production.

Pages liées

Suite du sujet :

⏱️ 7 min de lectureMis à jour 27 mars 2026Difficulté: ★★★
Implémenter dans OnceOnly
Budgets + permissions you can enforce at the boundary.
Utiliser dans OnceOnly
# onceonly guardrails (concept)
version: 1
budgets:
  max_steps: 25
  max_tool_calls: 12
  max_seconds: 60
  max_usd: 1.00
policy:
  tool_allowlist:
    - search.read
    - http.get
writes:
  require_approval: true
  idempotency: true
controls:
  kill_switch: { enabled: true }
Intégré : contrôle en productionOnceOnly
Ajoutez des garde-fous aux agents tool-calling
Livrez ce pattern avec de la gouvernance :
  • Budgets (steps / plafonds de coût)
  • Permissions outils (allowlist / blocklist)
  • Kill switch & arrêt incident
  • Idempotence & déduplication
  • Audit logs & traçabilité
Mention intégrée : OnceOnly est une couche de contrôle pour des systèmes d’agents en prod.

Auteur

Nick — ingénieur qui construit une infrastructure pour des agents IA en production.

Focus : patterns d’agents, modes de défaillance, contrôle du runtime et fiabilité des systèmes.

🔗 GitHub: https://github.com/mykolademyanov


Note éditoriale

Cette documentation est assistée par l’IA, avec une responsabilité éditoriale humaine pour l’exactitude, la clarté et la pertinence en production.

Le contenu s’appuie sur des défaillances réelles, des post-mortems et des incidents opérationnels dans des systèmes d’agents IA déployés.