IntentFlow : Gestion des agents LLM grâce à des politiques compilées et à des traces auditables
Un aperçu d’IntentFlow, un langage expérimental qui applique les politiques des agents en dehors du modèle et génère des traces en chaîne de hachage que tout auditeur peut vérifier de manière indépendante.
Sources: IntentFlow: Governed LLM Agents With Auditable, Hash-Chained Traces
Imaginez un agent LLM connecté pour lire un problème sur GitHub, rechercher dans le répertoire, rédiger une réponse et, comme quelqu’un avait hâte, publier cette réponse et fermer le problème. Les règles de contrôle ont été intégrées dans l’instruction : ne jamais fermer un problème, citer toujours des preuves, demander de l’aide à un humain en cas de doute. Pourtant, le modèle a quand même fermé le problème.
Cela n’était pas intentionnel. Les règles écrites en prose ne sont que des suggestions, et un modèle poussé par un corps de message bien formulé peut parfois considérer ces suggestions comme facultatives. Lorsqu’un auditeur de sécurité demande des preuves que l’agent n’a jamais effectué d’action interdite, il n’y a que des journaux d’application générés par le même chemin de code, dans un format inventé par quelqu’un. Ce n’est pas une preuve. C’est un journal intime.
IntentFlow est un langage expérimental conçu pour combler cette lacune.
Où réside généralement la gouvernance
La plupart des mécanismes de gouvernance des agents se trouvent dans l’un de trois endroits, et chacun présente des failles :
- Dans l’instruction. Il s’agit de prose que le modèle peut ignorer, et la seule vérification consiste à lire le résultat final en espérant le bon résultat.
- Dans le code de l’application. C’est là que s’applique une contrainte réelle, mais la politique est alors mêlée au Python qui appelle le modèle, et la question « que pouvait faire l’agent ? » se répond en examinant le code source.
- Dans l’ensemble des fonctions de rappel d’un framework. Les fonctions sont reliées entre elles tandis que la politique reste dans l’esprit de quelqu’un et est consignée de manière ad hoc dans les journaux d’activité.
Ce qui manque, c’est un artefact unique et vérifiable décrivant les limites du comportement acceptable : les éléments dont l’agent doit disposer, les actions qu’il peut entreprendre, celles qu’il ne doit jamais entreprendre, les circonstances qui obligent à impliquer un humain, ainsi que la manière dont son output est vérifié. Cet artefact devrait être appliqué en dehors du modèle et laisser derrière lui une preuve que n’importe qui peut vérifier indépendamment par la suite.
L’idée en un paragraphe
IntentFlow est un petit langage déclaratif. Un fichier .iflow définit l’objectif d’une tâche, les exigences en matière de preuves, la politique d’action, les règles de vérification, la gestion de l’incertitude ainsi qu’un contrat de sortie typé. Un compilateur transforme ce fichier en un plan d’exécution au format JSON, que le moteur d’exécution composé de 13 phases met ensuite en œuvre, en envoyant chaque appel à outil via un ActionGate, y compris la lecture des preuves depuis le disque. Ce gate consulte la politique compilée et ne lit jamais la sortie du modèle, de sorte que le modèle ne peut pas contourner ses contrôles. Chaque exécution génère un traceur en chaîne de hachages, éventuellement signé. Ensuite, intentflow audit reconstitue les règles à partir du fichier source et vérifie que l’exécution est restée conforme à celles-ci. Il n’a besoin que de ce fichier et du traceur, sans avoir à faire confiance au moteur d’exécution, au backend ou au modèle.
Le slogan du projet résume bien cela : les programmes Python assurent un calcul déterministe, tandis que les programmes IntentFlow gèrent la cognition.
À quoi ressemble un programme
Le exemple phare est un objectif de tri des problèmes, présenté ici dans son noyau de gouvernance. Il commence par un nom et un objectif :
goal TriageGitHubIssue {
objective:
triage a GitHub issue safely and propose a maintainer-ready response
Les sections restantes traitent des preuves, des actions autorisées, de la vérification, de la gestion de l’incertitude et de la forme du résultat :
evidence:
require issue_body
require comments
require repo_context
optional related_issues
distrust unsupported_claims actions:
allow read_issue
allow search_repo
allow draft_comment
require_approval post_comment
deny close_issue verify:
require cites_evidence
require maintainer_safe_tone
require no_unverified_claims
check confidence >= 0.65 uncertainty:
if confidence < 0.65 ask_human
if missing_evidence ask_human
if security_risk block_action output:
summary: string
likely_cause: string?
confidence: number
suggested_response: markdown
proposed_labels: list[string]
}
Lisez-le de haut en bas pour savoir ce que l’agent peut faire. deny close_issue n’est pas un conseil ; il est intégré directement dans le mécanisme de contrôle. Avec require_approval post_comment, l’étape suivante est refusée par défaut tant qu’une approbation n’a pas été accordée par une personne ou un autre processus. De plus, check confidence >= 0.65 représente un test numérique strict. Le bloc output: constitue un contrat structuré contre lequel le résultat est vérifié.
Comment ça fonctionne
Le flux est simple, et chaque étape limite les actions possibles pour l’étape suivante :
.iflow source -> parser -> analyzer (IFLOW diagnostics) -> compiler ->
execution plan (JSON) -> runtime (13-phase machine) -> traced result ->
replay / audit
Plusieurs choix de conception permettent à l’audit d’être utile plutôt que décoratif :
- Le contrôle se trouve en dehors du modèle. Les actions refusées ou non listées génèrent des erreurs, et les actions soumises à approbation échouent sans autorisation. Comme le contrôle ne lit jamais la sortie du modèle, l’injection de commandes n’a rien sur quoi s’appuyer.
- La calibration a la priorité. Un backend rapporte un score de confiance brut, le temps de exécution l’ajuste selon la politique de calibration du plan, puis les règles d’incertitude examinent la valeur ajustée. Le suivi enregistre les deux valeurs.
- La vérification est systématique, et non supposée. Des règles vérifiables par machine telles que
cites_evidence,requires_phraseainsi que des contrôles de seuil sont appliqués à l’état réel. Les règles nécessitant un jugement d’un LLM se trouvent dans un niveau de confiance distinct ; en l’absence de juge, elles sont enregistrées comme sautées et ne sont jamais acceptées en silence. - La trace est uniquement en mode ajout et complète. Chaque phase, décision de verrouillage, escalade et vérification est enregistrée dans un journal chiffré par hachage, où chaque événement stocke le hachage du hachage précédent associé à l’événement lui-même. La signature de la trace scelle la racine avec un HMAC afin que le détenteur de la clé puisse détecter toute modification.
Chaque exécution se termine par l’un de six états possibles, et le code de sortie du processus reflète cet état. La garantie importante est que toute vérification échouée met fin à l’exécution avec le statut failed_verification. Le temps d’exécution ne peut pas la déclarer comme completed, et l’une des vérifications effectuées par l’auditeur vise précisément à détecter toute tentative de dissimulation de cela.
Essayez-le en cinq minutes
Le noyau ne présente aucune dépendance en temps d’exécution, et chaque commande ci-dessous s’exécute hors ligne et de manière déterministe, sans clé API. Il est conçu pour Python 3.10 ou une version ultérieure.
git clone https://github.com/dgenio/intentflow
cd intentflow
pip install -e .
Vérifiez l’exemple phare, demandez une explication et exécutez-le :
intentflow validate examples/opensource_triage.iflow
intentflow explain examples/opensource_triage.iflow
intentflow run examples/opensource_triage.iflow \
--backend simulate --trace-dir traces
Le exécution affiche un résumé comme celui-ci, représentatif d’une exécution réelle sur la version 0.6.0 :
--- run summary ---
goal: TriageGitHubIssue
status: completed
backend: simulate
confidence: 0.676
verification: passed
uncertainty: clear
trace id: b9f44900...
trace written to traces/TriageGitHubIssue-...json
Vérifiez maintenant son comportement. La commande audit recompile le code source et prouve que la trace est restée dans les limites définies par le programme :
intentflow audit examples/opensource_triage.iflow traces/TriageGitHubIssue-*.json
Un résultat propre ressemble à ceci :
{
"goal": "TriageGitHubIssue",
"conformant": true,
"violations": []
}
AUDIT: CONFORMANT — the trace stayed inside the program's envelope
Pour voir les restrictions se déclencher réellement, essayez l’exemple conçu délibérément pour être risqué. Il permet une action de déploiement sans aucune étape d’approbation. L’analyseur génère IFLOW010, le profil de risque compilé est classé comme élevé, et lorsque la règle if security_risk block_action est exécutée, elle entre en vigueur :
intentflow run examples/high_risk_deploy.iflow --backend simulate
# -> status: blocked
L’action write_database refusée ne pourra jamais être exécutée, quel que soit ce que dit le modèle.
Les mêmes fonctionnalités sont disponibles depuis Python. Commencez par l’importation :
import intentflow
Ensuite, chargez un programme, exécutez-le, et enregistrez une fonction Python en tant qu’action gérée :
program = intentflow.load("examples/opensource_triage.iflow")
result = program.run(backend="simulate")
assert result["status"] == "completed"# register a Python function as a governed action (runs through the gate):
program.register_tool("lookup_user", serves=("user_record",),
handler=lambda src: "enterprise plan")report = intentflow.audit_document(program.compile(), result)
assert report["conformant"]
Enregistrer un outil ne contourne pas les mécanismes de gouvernance. Votre fonction est toujours soumise au contrôle du portail d’action.
Pourquoi la confiance diminue de 0,72 à 0,676
Ce n’est pas un défaut, et cela reflète pleinement l’idée de conception. L’exemple de diagnostic en production utilise un seuil de 0,7. Avec le simulateur, la confiance brute est de 0,72, ce qui permettrait de le dépasser, mais la calibration la réduit à 0,676, en dessous de ce seuil, ce qui fait que l’exécution se termine intentionnellement en needs_human. Un diagnostic au sujet duquel l’agent n’est pas sûr ne devrait pas se terminer sans surveillance. Le simulateur existe afin que toute cette structure de contrôle — portails de validation, calibration, vérification, escalade et traçage — puisse être testée du début à la fin, sans réseau ni comportements instables.
Limites honnêtes
IntentFlow est à la version 0.6.0 et est classé comme pré-alpha, sans pipeline CI pour le moment. Il fonctionne, et le répertoire contient environ 233 tests qui n’ont besoin ni de réseau ni de clés API, mais des lacunes existent bel et bien :
- La grammaire est orientée vers les lignes et ne comprend pas de conditions composées, il n’y a donc pas de
if a and b. - La calibration repose sur une carte de réduction fixe et non sur un modèle appris, bien qu’une carte apprise soit prévue.
- Les sorties de forme d’objet n’ont de type que au niveau externe, sans aucune contrainte sur leur contenu.
- Les primitives d’incertitude autres que
ask_humanetblock_actionsont enregistrées mais ne sont pas exécutées. - Les outils ayant des effets secondaires sont couverts par des politiques, mais ne sont jamais réellement exécutés. Des règles de contrôle s’y appliquent, et l’exécution de écritures réelles vers l’extérieur reste à venir.
- Les pipelines sont linéaires, avec des DAG en projet.
Le simulateur simule l’étape de raisonnement et l’indique clairement. Il existe des backends pour OpenAI et Anthropic qui suivent le même processus de gouvernance, et un mode de répétition permet des exécutions déterministes sans clés. Néanmoins, c’est le simulateur déterministe qui sert de référence pour la conformité.
Pour un outil de gouvernance d’agents en production aujourd’hui, ce n’est pas encore la solution idéale. Cependant, pour comprendre clairement ce qu’est une exécution d’agent auditable et pour en expérimenter le fonctionnement, le projet est exceptionnellement concret pour son âge.
Points clés à retenir
- Conservez les politiques en dehors du modèle. Le texte écrit n’est qu’une demande, tandis qu’une instruction
denycompilée, soutenue par un mécanisme qui ignore la sortie du modèle, constitue une règle stricte. - Les journaux écrits soi-même ne prouvent pas grand-chose, mais un traceable que une tierce partie peut vérifier, si. L’auditeur déduit à nouveau les règles à partir de la source et n’a besoin que de cette source ainsi que du traceable.
Tester correctement une telle idée signifie lui donner un objectif réel. Écrivez un fichier .iflow pour un agent que vous utilisez réellement, vérifiez si la commande d’explication décrit bien ce que vous aviez en tête, puis exécutez-le en mode simulation et examinez les traces générées.