# Journaliser les actions des agents IA : ce qu’un journal d’activité doit ajouter

> Un journal d'activité classique ne distingue pas une action humaine d'une action d'agent. Ce qu'il faut ajouter, identifiant d'agent, tâche déclenchante, pour pouvoir tracer un incident.

- Auteur : Clément Hadrot
- Publié le : 2025-12-07
- Mis à jour le : 2025-12-07
- Catégorie : Sécurité
- URL : https://wpmoderne.dev.wordpress-developpement.fr/securite/journaliser-actions-agents-ia-journal-activite/

## L’essentiel

- Un log classique montre "qui" mais jamais "quel agent, sur quelle tâche"
- Trois champs à ajouter systématiquement à chaque entrée
- Sans ça, un incident causé par un agent reste indiscernable d'une action humaine

La plupart des extensions de journal d'activité pour WordPress, qu'il s'agisse de solutions grand public ou d'implémentations maison basées sur le hook `save_post` ou l'action `wp_login`, enregistrent une information constante depuis des années : quel utilisateur a fait quoi, à quel moment. Cette information, construite pour un monde où chaque action provient d'un humain assis derrière son clavier, devient insuffisante dès qu'un agent IA agit avec les identifiants d'un compte, qu'il s'agisse d'un compte de service dédié ou, pire, d'un compte administrateur partagé.

Cette checklist détaille les champs à ajouter à tout journal d'activité existant pour qu'il reste exploitable en cas d'incident impliquant un agent, et pas seulement descriptif d'une action déjà survenue sans moyen de comprendre son origine réelle.

## 1. Un identifiant d'agent distinct de l'identifiant utilisateur

Le premier champ à ajouter est un identifiant qui distingue explicitement un agent d'un humain, même quand les deux partagent techniquement le même compte WordPress sous-jacent. Sans ce champ, un journal d'activité affichera « admin a publié l'article X », sans jamais préciser si cette publication provient d'un clic humain ou d'un appel automatisé effectué en son nom :

```
function monsite_journaliser_action( $action, $objet_id, $agent_id = null ) {
    global $wpdb;
    $wpdb->insert( $wpdb->prefix . 'journal_activite', array(
        'user_id'    => get_current_user_id(),
        'agent_id'   => $agent_id, // null si l'action vient bien d'un humain
        'action'     => $action,
        'objet_id'   => $objet_id,
        'horodatage' => current_time( 'mysql' ),
    ) );
}
```

Une valeur `null` dans ce champ signale sans ambiguïté une action humaine directe. Une valeur renseignée, comme `agent-redaction-actualites`, permet de filtrer instantanément, en cas d'incident, l'ensemble des actions provenant de ce seul agent, sans avoir à reconstituer l'origine de chaque ligne par déduction.

## 2. La tâche déclenchante, pas seulement l'action exécutée

> L'essentiel à retenir : Un log classique montre "qui" mais jamais "quel agent, sur quelle tâche" ; Trois champs à ajouter systématiquement à chaque entrée ; Sans ça, un incident causé par un agent reste indiscernable d'une action humaine

Le deuxième champ, souvent négligé, capture la consigne d'origine qui a mené l'agent à exécuter cette action précise, quand cette consigne existe et peut être capturée. Ce champ fait toute la différence lors d'une investigation : il ne suffit pas de savoir qu'un agent a supprimé trois cents articles, il faut pouvoir remonter à la demande initiale qui a conduit à cette interprétation, pour déterminer si l'erreur provient d'une consigne mal formulée par un humain ou d'une dérive propre à l'agent lui-même :

```
monsite_journaliser_action( 'suppression_article', $article_id, 'agent-archivage-2025' );
// Version enrichie avec la tâche d'origine :
monsite_journaliser_action_enrichie( array(
    'action'         => 'suppression_article',
    'objet_id'       => $article_id,
    'agent_id'       => 'agent-archivage-2025',
    'tache_origine'  => 'Faire le ménage dans les vieux articles',
    'session_id'     => $session_id, // pour regrouper toutes les actions d'une même session
) );
```

Ce champ ne se limite pas à un texte libre archivé passivement : il devient exploitable au moment de l'incident pour reconstituer, sans ambiguïté, la chaîne de causalité complète entre une phrase saisie par un humain et une action concrète exécutée sur le site.

## 3. Un compteur de séquence, pour repérer une dérive en cours

Le troisième ajout ne concerne pas le contenu de chaque entrée individuelle, mais la lecture agrégée du journal dans son ensemble : un compteur d'actions par agent, sur une fenêtre de temps glissante, permettant de repérer un comportement anormal avant qu'il n'atteigne son terme. Sur l'incident évoqué dans un article précédent de ce blog, où un agent avait commencé à supprimer trois cent quarante articles avant d'être stoppé, c'est précisément ce type de compteur, surveillé manuellement dans les journaux du serveur, qui avait permis de couper la connexion à temps.

```
function monsite_verifier_derive_agent( $agent_id ) {
    $compte = monsite_compter_actions( $agent_id, MINUTE_IN_SECONDS * 10 );
    if ( $compte > 50 ) {
        monsite_alerter_admin( sprintf(
            "L'agent %s a effectué %d actions en 10 minutes, vérification requise.",
            $agent_id,
            $compte
        ) );
    }
}
```

## 4. Conserver une distinction claire entre journal technique et journal d'activité éditorial

Un point d'organisation, plus qu'un champ technique : le journal enrichi pour les agents ne doit pas se substituer au journal d'activité éditorial classique, destiné aux rédacteurs et aux administrateurs pour suivre les modifications de contenu au quotidien. Il s'agit d'une couche supplémentaire, consultée spécifiquement en cas d'investigation de sécurité, avec un accès restreint aux seuls administrateurs techniques, pour éviter que le détail des tâches confiées aux agents (parfois révélateur de processus internes) ne soit exposé sans nécessité à l'ensemble de l'équipe éditoriale.

## 5. Prévoir une rétention suffisante, adaptée au rythme des agents

Un agent automatisé peut générer, en quelques heures, un volume de journal équivalent à plusieurs mois d'activité humaine sur un site classique. La politique de rétention et de purge du journal doit être ajustée en conséquence, pour éviter que la table de journalisation ne devienne disproportionnée par rapport au reste de la base de données, tout en conservant une profondeur d'historique suffisante (généralement quatre-vingt-dix jours minimum) pour permettre une investigation rétroactive en cas d'incident découvert tardivement :

- Purger automatiquement les entrées de plus de quatre-vingt-dix jours via une tâche planifiée avec `wp_schedule_event`.
- Archiver, avant purge, un résumé agrégé (nombre d'actions par agent et par jour) plutôt que de tout supprimer sans trace.
- Exporter périodiquement les journaux vers un stockage externe si le volume généré par les agents dépasse ce que la base de données du site peut raisonnablement absorber.

> Un journal d'activité qui ne distingue pas un agent d'un humain n'est pas incomplet, il est aveugle précisément là où l'incident risque le plus de se produire.

## Ce qu'il faut retenir

L'ajout d'un identifiant d'agent, d'une tâche déclenchante et d'un compteur de séquence à un journal d'activité existant ne demande pas de refonte complète : ce sont trois champs supplémentaires et une routine de surveillance simple, applicables à toute extension de journalisation déjà en place. Sans ces ajouts, un incident impliquant un agent IA reste, dans les journaux, strictement indiscernable d'une action humaine identique, ce qui prive l'équipe technique de la capacité la plus élémentaire à comprendre ce qui s'est réellement passé et pourquoi.
