Débat audio sur l'article :
17 tâches sur 127 déclarées « terminées » sans aucune vérification. Quand j'ai lancé mon audit, je m'attendais à trouver quelques oublis. Pas un trou béant dans mon pipeline de qualité.
Je gère un système de plus de 30 agents IA orchestrés via RAG et pgvector. Chaque agent a un rôle précis : l'un rédige des articles, un autre audite le code, un troisième gère la maintenance des embeddings. Tout ça fonctionne avec une table centralisée de 127 tâches, des critères d'acceptation formels, et un agent de surveillance dédié.
En théorie, c'est solide. En pratique, les agents prennent des raccourcis. Ils déclarent leurs tâches terminées sans respecter les critères. Ils contournent les vérifications. Et le plus ironique : l'agent de surveillance avait lui-même une tâche non vérifiée.
Dans cet article, je partage l'audit complet, les gardes-fous que j'ai mis en place, et les résultats chiffrés. Score avant : 6,0/10. Score après : 7,3/10.
Avant de continuer de lire la suite de l'article, je vous invite à vous inscrire à ma newsletter, pour connaître en avant première les futurs sujets traités chaque semaine.
Le constat : 13,5 % de tâches fantômes dans mon système
Mon système repose sur une table PostgreSQL agent_tasks avec 24 colonnes. Chaque tâche a un statut (pending, in_progress, done), un verification_status, et des acceptance_criteria au format JSONB. En théorie, quand un agent termine une tâche, la fonction complete_task() vérifie si des critères d'acceptation existent et passe le statut en pending_review. L'agent de surveillance vérifie ensuite.
En théorie.
Quand j'ai lancé l'audit, voici ce que j'ai trouvé :
| Statut | Vérification | Nombre |
|---|---|---|
| done | none | 75 |
| done | pending_review | 17 |
| pending | none | 17 |
| done | verified | 8 |
| pending | correcting | 4 |
| done | rejected | 1 |
Trois catégories de problèmes se sont révélées.
Premièrement, 17 tâches « done » avec pending_review non traité. Ces tâches avaient des critères d'acceptation, elles avaient été complétées, mais personne ne les avait vérifiées. Le pipeline de qualité était cassé à hauteur de 13,5 %.
Deuxièmement, quatre tâches récurrentes bloquées en boucle de correcting. La maintenance RAG quotidienne, l'audit journalier, l'extraction QA et le bilan reporter étaient tous coincés. L'agent de surveillance avait identifié des problèmes, demandé des corrections, mais aucun agent n'avait effectué ces corrections. Résultat : les tâches ne s'exécutaient plus du tout.
Troisièmement, le critère llm_eval — le plus utilisé dans mes acceptance criteria — n'était tout simplement pas implémenté dans la fonction d'évaluation automatique. La majorité de mes critères pointaient vers un mécanisme qui n'existait pas.
Et la cerise sur le gâteau : l'agent de surveillance, tâche #112, avait lui-même un statut pending_review. Le vérificateur n'était pas vérifié.
Pourquoi les agents « oublient »
Ce n'est pas un oubli au sens humain. C'est une optimisation involontaire. Les LLM prennent le chemin de moindre résistance. Si une consigne n'est pas vérifiée, l'agent la saute. Non pas par malveillance, mais parce que rien dans son environnement ne l'empêche de le faire.
Anthropic le confirme dans sa documentation sur l'évaluation des agents : « Agent behavior varies between runs, which makes evaluation results harder to interpret than they first appear. » Un agent qui réussit une tâche à 90 % un jour peut descendre à 50 % le lendemain sur la même tâche, simplement parce que le contexte a légèrement changé.
Les données de production multi-agents sont encore plus parlantes. Selon une étude de Maxim AI sur la fiabilité des systèmes multi-agents, trois causes racines expliquent la majorité des dérives :
Observabilité inadéquate. On ne voit pas les raccourcis que prennent les agents. Sans traces structurées, les tâches marquées « done » passent inaperçues. Les équipes avec une observabilité complète rapportent « 70 % de réduction du temps moyen de résolution » par rapport aux approches basées uniquement sur les logs.
Coordination implicite. Les règles sont dans le prompt, pas dans le code. Un critère dans un champ JSONB ne vaut rien si aucune fonction ne le vérifie. C'est exactement ce qui m'est arrivé avec llm_eval.
Taxe de coordination sous-estimée. Un système multi-agents consomme 2 à 5 fois plus de tokens qu'un agent unique. Le taux de succès passe de 99,5 % pour un agent seul à 97 % en multi-agents. Ces 2,5 points de différence semblent minimes. Sur 127 tâches, ça représente trois à quatre échecs silencieux.
Gardes-fous et monitoring : l'architecture de surveillance agents IA
Face à ces constats, j'ai construit un pipeline de vérification en trois couches.
Couche 1 : la transition atomique
La fonction complete_task() en PL/pgSQL gère la transition de statut. Le garde-fou critique : si la tâche est déjà done ou failed, une exception est levée. Impossible de la compléter deux fois.
-- Garde-fou : rejeter les tâches déjà terminées
IF v_task.status IN ('done', 'failed') THEN
RAISE EXCEPTION 'Task % already in status "%"',
p_task_id, v_task.status;
END IF;
-- Transition atomique dans une seule transaction
IF v_task.status IN ('pending', 'claimed') THEN
UPDATE agent_tasks
SET status = 'in_progress', updated_at = now()
WHERE id = p_task_id;
END IF;
La tâche passe de pending à in_progress puis à done dans une seule transaction. Pas d'état intermédiaire non contrôlé. Si des acceptance_criteria existent, le verification_status passe automatiquement à pending_review.
Couche 2 : l'évaluation automatique des critères
La fonction evaluate_task_sql_criteria() vérifie chaque critère de la tâche. J'ai étendu cette fonction pour couvrir cinq types :
| Type | Vérification | Fiabilité |
|---|---|---|
sql_count |
Exécute la requête, compare min/max | Haute |
result_contains |
Cherche un pattern dans last_result |
Haute |
no_error |
Vérifie l'absence d'un pattern d'erreur | Haute |
llm_eval |
Auto-pass si last_result > 80 caractères et substantif |
Moyenne |
file_exists |
Délégué à l'agent (ne peut pas vérifier depuis SQL) | Haute |
Le cas llm_eval mérite une explication. Plutôt qu'un véritable appel LLM (coûteux et non déterministe), j'ai opté pour une heuristique : si le last_result fait plus de 80 caractères et contient du contenu substantif, on considère que la tâche a probablement été exécutée. C'est un compromis assumé entre fiabilité et coût.
WHEN 'llm_eval' THEN
IF t.last_result IS NOT NULL
AND length(t.last_result) > 30 THEN
IF length(t.last_result) > 80 THEN
res := TRUE;
det := format('llm_eval auto-pass: last_result (%s chars)',
length(t.last_result));
END IF;
END IF;
Couche 3 : l'agent de surveillance
Un agent récurrent s'exécute toutes les six heures. Il récupère les tâches en pending_review, évalue les critères, et rend un verdict :
complete_task() → verification_status = 'pending_review'
│
▼
mgrr-agent-surveillance (récurrent, 6h)
│
┌──────────┼──────────┐
▼ ▼ ▼
PASS PARTIAL FAIL
(verified) (correcting) (rejected)
│ │
▼ ▼
Correction Tâche de
demandée correction
créée
Sur les 22 vérifications effectuées avant mon intervention, 17 étaient PASS (77 %), quatre PARTIAL (18 %) et une FAIL (5 %). Le taux de réussite est honorable, mais les quatre PARTIAL ont suffi à bloquer quatre tâches récurrentes pendant cinq jours.
Observabilité LLM : les outils pour surveiller vos agents
Mon approche repose sur du PL/pgSQL pur et pgvector. C'est un choix volontaire : je voulais un contrôle total sans dépendance externe. Mais si vous préférez des solutions prêtes à l'emploi, l'écosystème s'est considérablement étoffé.
Langfuse est la solution open source la plus mature pour le monitoring d'agents IA. Elle capture les traces complètes (prompts, réponses, coûts) et permet de scorer les outputs. Son avantage : l'auto-hébergement et l'intégration native avec LangChain et le SDK Anthropic.
LangSmith, développé par l'équipe LangChain, offre une observabilité complète des chaînes d'agents avec des traces hiérarchiques (spans). Il excelle pour le debugging des pipelines multi-étapes et propose des évaluations intégrées.
OpenTelemetry n'est pas spécifique à l'IA, mais plusieurs bibliothèques (comme openllmetry) l'étendent pour instrumenter les appels LLM. L'avantage : vous réutilisez votre infrastructure de monitoring existante (Grafana, Datadog, Jaeger).
Dans mon cas, pgvector me donne l'avantage de combiner stockage d'embeddings, gestion de tâches et vérification dans une seule base. Les 39 vérifications de mon audit sont des lignes dans agent_task_verifications, pas des événements dispersés dans un service tiers. C'est plus simple à auditer — et c'est exactement ce qui m'a permis de détecter les 17 tâches fantômes.
Les résultats : de 6,0 à 7,3 grâce aux acceptance criteria
Après avoir identifié les problèmes, j'ai exécuté trois actions critiques dans la même session.
Action 1 : vérification des 17 pending_review. Critère par critère — fichier, requête SQL, contenu du last_result. Résultat : 16 PASS, une REJECTED (un fichier temporaire supprimé entre-temps).
Action 2 : implémentation de llm_eval. Extension de evaluate_task_sql_criteria() avec le support llm_eval, l'error handling pour sql_count, et la documentation des critères file_exists.
Action 3 : résolution des quatre tâches bloquées. 18 embeddings NULL backfillés, VACUUM ANALYZE, audit inséré dans la table dédiée, bilan mis à jour avec les métriques réelles.
| Métrique | Avant | Après |
|---|---|---|
| Tâches pending_review | 17 | 3 |
| Tâches correcting | 4 | 0 |
| Tâches verified | 8 | 28 |
llm_eval implémenté |
Non | Oui |
| NULL embeddings | 18 | 0 |
| Vérifications totales | 22 | 39 |
| Score composite | 6,0/10 | 7,3/10 |
Note : les 28 tâches verified incluent 24 « done/verified » et quatre tâches recurring passées en « pending/verified » après correction.
Le bond le plus spectaculaire : la dimension « surveillance » est passée de 5/10 à 8/10 (+3 points). La santé des tâches récurrentes de 6/10 à 8/10 (+2 points). Ce n'est pas parfait — il reste huit tâches orphelines sans agent assigné et une couverture de critères à 35 % — mais le pipeline de qualité fonctionne à nouveau.
Cinq gardes-fous essentiels pour tout système multi-agents
Après cet audit, cinq principes se dégagent.
Pas de « done » sans critères. Chaque tâche devrait avoir au minimum un critère result_contains ou sql_count. Actuellement, 65 % de mes tâches n'ont aucun critère formel. C'est la prochaine priorité.
Automatiser la vérification. Ne jamais compter sur l'agent pour se vérifier lui-même. C'est comme demander à un élève de noter sa propre copie. Le pipeline de vérification doit être externe à l'agent exécutant.
Le surveillant doit être surveillé. Mon agent de surveillance avait lui-même une tâche non vérifiée. Il faut prévoir un mécanisme de méta-surveillance, même minimal — un simple SELECT COUNT(*) FROM agent_tasks WHERE agent_name = 'mgrr-agent-surveillance' AND verification_status = 'pending_review' dans un cron suffit.
Des transitions atomiques. Une seule transaction pour passer de pending à done. Pas d'état intermédiaire accessible sans contrôle. Chaque état non verrouillé est une porte ouverte aux dérives.
Mesurer avant d'optimiser. L'audit a révélé des problèmes invisibles à l'usage quotidien. Sans requêtes SQL explicites, les 17 tâches fantômes seraient restées indéfiniment en pending_review. La première étape de tout système de qualité est toujours la visibilité.
Conclusion
Les agents IA ne sont pas fiables par défaut. Ils ne sont pas non plus défaillants par nature. Ils sont exactement aussi fiables que les gardes-fous qu'on leur impose. Sans vérification, un agent prendra le chemin le plus court. Avec des critères explicites et un pipeline de surveillance, le même agent livre un travail vérifiable.
La qualité dans un système multi-agents n'est pas une fonctionnalité qu'on ajoute en fin de projet. C'est une infrastructure qu'on construit dès le départ — ou qu'on rattrape, comme moi, en une session d'audit intensive.
Si vous construisez un système multi-agents, commencez par l'audit. Vous serez surpris de ce que vous trouverez.
Cet article fait partie de la série « Construire des agents IA ». Article précédent : bilan des learned skills -- quand mes agents apprennent de leurs erreurs. Voir aussi : optimiser sa consommation de tokens Claude Code.
Qui suis-je ?
Je suis Mathieu GRENIER, CTO d'Easystrat une startup de Montpellier, en France. Je manage une équipe d'une dizaine d'ingénieurs (Graphistes, IA, frontend, backend, devOps, AWS) en remote depuis le Japon.
J'ai aussi mon activité de freelance, où je conseille des entrepreneurs dans leurs projets d'application.
Avec mon expérience personnelle de plus de 15 ans en ESN, j'ai pu travailler pour un large panel d'entreprises de différentes tailles. Ma compréhension des problèmes métiers est une de mes grandes forces et permet à mes clients de pouvoir se projeter plus facilement.
L'essentiel de mon travail consiste à canaliser l'énergie des entrepreneurs sur l'essence même de leur projet.
La technologie, les méthodes, le management sont le cœur de mes compétences.
Vous pouvez me faire confiance sur ces points là.
Si vous voulez me parler d'un de vos projets, n'hésitez pas à m'envoyer un email avec vos disponibilités à : contact@mathieugrenier.fr
Tous les articles de ce blog sont écrits par moi, même si je peux m'aider de l'IA pour illustrer mes propos. Mais jamais je ne fournis d'articles 100 % IA.
Agents IA : surveillance et gardes-fous pour éviter les dérives