
Pistes d'audit inviolables pour agents d'IA : Runtime Records chaînés par hachage, sans dépendance, vérifiables par tous.
Pistes d'audit inviolables pour les agents IA — des Runtime Records chaînés par hachage, restitués sous forme de Runtime Report que vos clients peuvent vérifier eux-mêmes.
Chaque action effectuée par votre agent (appels d'outils, appels de modèles, accès aux données, approbations) devient un Runtime Record dans un journal en ajout seul, chaîné par hachage ; le Runtime Report est cette chaîne restituée sous forme de page HTML auto-vérifiable. Toute partie détenant un point de contrôle de la chaîne peut vérifier que les enregistrements qui la composent n'ont jamais été altérés, sans faire confiance à celui qui les a produits — ce point de contrôle est la pièce maîtresse : la chaîne seule est inviolable face à tous, sauf face à la partie qui exploite l'enregistreur (LIMITS.md §1). Quand l'équipe sécurité d'un client demande « qu'a fait votre agent avec nos données ? », vous leur donnez un lien au lieu d'un paragraphe. Les revues de sécurité posent déjà des questions sur l'IA à côté de la checklist SOC 2 — et de plus en plus, ces questions proviennent de l'ISO 42001, des articles de tenue de registres du règlement européen sur l'IA, et des questionnaires propres aux clients. Aujourd'hui, une assurance écrite suffit encore. Le pari derrière ce projet, c'est que cela ne durera pas longtemps.
Présenté dans Help Net Security (août 2026).
Le format d'enregistrement est ouvert et libre à implémenter. Ce paquet est l'implémentation de référence : enregistreur, vérificateur, client témoin et serveur de rapports.
Vous utilisez halo-record, ou vous y pensez ? Dites-moi qui vous êtes et pour quoi faire → Qui utilise halo-record ?
On vous demande d'installer un enregistreur à l'intérieur de votre agent. Vous ne devriez pas accepter cela sur parole :
pip install halo-record installe exactement un paquet.summaries=False) ne conserve aucun résumé. L'expurgation est effectuée au mieux (regex sur les formats courants de secrets et de données personnelles, plus un attrape-tout par entropie) : considérez-la comme une défense en profondeur, pas comme une garantie. Les champs de résultat que vous fournissez au-delà de summary sont scellés tels quels (LIMITS §13).Ce que chaque couche prouve — la distinction porteuse dans ce projet (LIMITS.md §1) : une chaîne que vous détenez vous-même prouve que les enregistrements n'ont pas été modifiés, par rapport à une tête que quelqu'un détient déjà ; seuls des points de contrôle détenus en dehors de l'opérateur prouvent qu'aucun n'a été supprimé ; et aucun hachage ne prouve que chaque action a été capturée.
| Affirmation | Chaîne auto-détenue | + Points de contrôle externes | + Capture de confiance |
|---|---|---|---|
| Détecter les modifications d'un artefact établi | ✔ | ✔ | ✔ |
| Détecter la réécriture d'un historique validé | — | ✔ | ✔ |
| Détecter les points de contrôle manquants/tardifs | — | ✔ (cadence convenue) | ✔ |
| Prouver que chaque action a été enregistrée | — | — | dépend de la frontière de capture |
Voyez-en un avant d'installer : un exemple de Runtime Report — données fictives, chaîne réelle, et il se re-vérifie lui-même dans votre navigateur pendant que vous regardez.
Aucun agent requis. Avec uv, rien à installer :``` uvx --from halo-record halo demo --serve
ou de la manière classique :```
pip install halo-record
halo demo --serve
Soit on échafaude un fournisseur fictif d'agents de support avec deux clients, on est témoin des chaînes (avec un fichier témoin local tenant lieu de témoin extérieur à l'opérateur — voir LIMITS.md §1), on sert leurs Runtime Reports soumis à contrôle d'accès, et on ouvre la console opérateur dans votre navigateur. Ensuite, essayez le test d'altération : supprimez une ligne de l'un des fichiers .jsonl et rechargez. Le rapport le détecte.
Une ligne à la frontière :```python from halo_record import trace
agent = trace(run_my_agent, profile="my-agent", log="audit.jsonl") # wraps your entrypoint; records the run boundary to ./audit.jsonl — add record_call() or a framework adapter at each tool boundary to capture individual calls
Un shim de commodité `from halo import ...` est également fourni — mais le nom `halo` sur PyPI appartient à un paquet de terminal-spinner sans rapport, et si ce paquet est installé, c'est lui qui remporte l'import. `halo_record` est sans ambiguïté, donc les exemples l'utilisent.
Sans `log=`, les enregistrements vont dans `~/.halo/my-agent.jsonl` (une chaîne par agent). Le wrapper scelle la frontière d'exécution ; les preuves résident dans les enregistrements par appel. Capturez-les avec un adaptateur de framework (matrice ci-dessous) — ou explicitement, ce qui montre aussi comment les liens de délégation fonctionnent :```python
from halo_record import Recorder, record_call
rec = Recorder("audit.jsonl")
with record_call(rec, "crm.lookup", {"account": "acct-9"}) as call: # one sealed record per tool call
call.result = crm.lookup("acct-9")
with record_call(rec, "payments.refund", {"amount": 120},
parent_id=rec.last_record_id()) as call: # child links to the action that spawned it
call.result = payments.refund(120)
Ensuite, générez le rapport :``` halo report audit.jsonl -o report.html # one chain -> self-verifying HTML halo serve ./records --port 8721 # all tenants, gated per customer
Le quickstart se termine lorsque vous consultez le Runtime Report de votre propre agent dans un navigateur. Si vous avez obtenu un fichier JSONL et aucun rapport, quelque chose ne va pas : ouvrez une issue.
### Le bloc de vérification