Briefing produit

VIGIE-01

Un agent IA de veille défense & export-contrôle, cadré et construit comme un livrable réel — pipeline fonctionnel de bout en bout, pas une maquette.

LangGraph · StateGraph Claude Haiku FastAPI · React V1 — testé de bout en bout

Synthèse

Réduire le temps de synthèse quotidienne sans céder sur la traçabilité

  • Le constat. Le point dur n'est pas de collecter — les outils existent — mais de classer un flux hétérogène de façon homogène, de recouper, et de pouvoir justifier a posteriori pourquoi une information a été retenue.
  • La réponse. Un pipeline en cinq nœuds où chaque affirmation est adossée à une citation vérifiée verbatim, et où l'escalade agentique bornée est déclenchée par une condition mesurée — l'existence d'un antécédent à recouper — et non par la catégorie de l'article.
  • L'état. V1 fonctionnelle de bout en bout, première tranche du vérificateur V2 et premier étage du raisonnement longitudinal V3 (threads d'événements) livrés, garde-fous codés et testés dans les deux sens — pas seulement déclarés. En production depuis le 2026-09-05 : le digest est servi publiquement, la persistance de production a tourné, et la réservation de budget en transaction — le garde-fou qui ne pouvait être vérifié qu'en conditions concurrentes réelles — tient sous 30 réservations simultanées pour 4 places. L'ordonnanceur quotidien reste à armer.
  • La recommandation. Rendre le pipeline observable avant de le rendre autonome. Le diagnostic de déploiement n'a pas buté sur l'infrastructure mais sur le fait que le pipeline ne journalisait rien : sous un ordonnanceur, toute l'instrumentation de coût construite les jours précédents aurait disparu au moment exact où elle devient la seule fenêtre sur le système.

Ce qui suit détaille le cadrage, l'architecture et les preuves — dans cet ordre.

Le problème

Le suivi manuel du risque export ne se justifie pas a posteriori

  • Revue de presse quotidienne dispersée, alertes email non structurées
  • Aucune trace de pourquoi une information a été retenue ou écartée
  • Cible : fonctions conformité export, intelligence économique, affaires publiques

Non-objectif explicite : le système ne décide pas. Il accélère et structure la veille humaine — la décision reste humaine.

Cadrage

Trois enjeux critiques, pas un seul

  1. Classification cohérente d'un flux hétérogène de sources
  2. Recoupement multi-sources — distinguer signal confirmé et rumeur isolée
  3. Traçabilité systématique — chaque affirmation adossée à une source identifiée

1 et 3 couverts en V1 · 2 livré en première tranche V2 — périmètre étendu aux cinq catégories le 2026-08-20, l'escalade étant conditionnée à un antécédent candidat mesuré plutôt qu'à la catégorie (cf. feuille de route)

Périmètre MECE

Cadré en MECE, puis corrigé au contact des données réelles

Inclus (V1)

Export control, contrats d'armement, mouvements militaires, diplomatie défense, programmes industriels — filtrage thématique, zone mondiale.

Exclu explicitement

Renseignement classifié, cybersécurité (périmètre voisin distinct), décision automatisée, analyse financière de marché.

Révision assumée : un filtrage géographique strict, testé sur données réelles, rejetait à tort la quasi-totalité de 2 sources sur 5 → retiré, remplacé par une extraction de lieu en métadonnée non filtrante. Documenté comme révision, pas masqué.

Architecture

Un pipeline agentique traçable, pas un script

Sources

18 flux RSS, sélection par pays, validés en direct

Collecte

collector.py

Dédoublonnage

avant l'appel LLM, pas après

Analyse

classification + résumé + citation vérifiée

Vérification

recoupement + score de confiance, boucle d'outil bornée

Regroupement

threads d'événements sur l'historique, même boucle bornée

État partagé (VigieState) entre les nœuds, chaque nœud tracé nativement — sans instrumentation manuelle. Les trois premiers nœuds sont un workflow déterministe ; les deux derniers laissent le modèle décider de ses propres appels d'outil, chacun sous double plafond codé — un nœud agentique de plus n'est pas un plafond de plus à oublier.

Ce qui survit aux runs — budget LLM, liens vus, historique analysé — passe par une couche de persistance unique, fichiers locaux en développement et Firestore en production. Le digest servi est une fenêtre glissante sur cet historique, pas la photographie du dernier run : le dédoublonnage vidant les collectes suivantes, servir le run brut effacerait l'affichage à chaque passage.

Restitution

Le digest rend visible ce qui engage la confiance

Digest VIGIE : barre de commande unique (vues, profondeur, tri), rail de filtres à gauche, bandeau d'indicateurs, et fiches d'événement portant le score de confiance, la citation vérifiée et la marque du média.

Score de confiance sur une rampe séquentielle et non en rouge/vert — un score lu comme un verdict invaliderait le non-objectif. Un item hors du périmètre du vérificateur sort sans score plutôt qu'avec un zéro. La provenance « média d'État » est affichée, pas noyée.

Couverture

La carte affiche aussi ce qu'elle ne peut pas placer

Carte de couverture géographique, construite sur le lieu vérifié de chaque événement, avec le décompte des items sans lieu extrait et des lieux non rattachables à un pays.

Construite sur le lieu vérifié de l'événement, pas sur le pays de la source. Les items sans lieu extractible et les lieux non rattachables à un pays (espaces maritimes, commandements) sont comptés explicitement : une carte qui ne montrerait que ses succès surestimerait la couverture réelle.

Synthèse

Le thread rend lisible ce qui se joue entre les articles

Vue Threads : un dossier suivi par plusieurs sources, sa chronologie à l'échelle réelle du temps, et le croisement entre pays du média et pays de l'événement.

Un thread relie les articles d'un même dossier — mêmes parties, même opération — et non d'un même thème. La chronologie est à l'échelle réelle du temps : l'écart entre les parutions est le signal, et des repères équidistants rendraient identiques trois dépêches en vingt minutes et un dossier étalé sur trois semaines. Aucun score agrégé n'est produit au niveau du thread — moyenner des scores partiellement absents comblerait par un calcul un vide laissé volontairement.

Garde-fou non négociable

Pas de résumé sans preuve

Chaque résumé généré par le LLM doit être accompagné d'une citation vérifiée verbatim contre le texte source. Sans preuve, l'item est rejeté automatiquement — pas seulement signalé.

« The Rafale export deal was signed today. » — extrait source, jamais traduit, jamais paraphrasé

Même principe appliqué au lieu extrait : vide plutôt que non vérifiable.

Valeur estimée

Ordre de grandeur illustratif

PosteHypothèseValeur
Équipe concernée4 analystes dédiés
Gain de temps90 → 30 min de revue / jour / analyste528 h/an
Valeur temps528 h × 60 €/h chargé~32 000 €/an
Coût du système (mesuré réel)~200 items/j × 1 appel + escalade plafonnée~140 €/an

Ratio favorable même en scénario dégradé (gain divisé par deux). Le bénéfice qualitatif — standardisation, traçabilité — reste déterminant au-delà du seul temps.

Risques

Traités par priorité, pas par exhaustivité

Haute priorité

Hallucination LLM

Citation verbatim obligatoire, rejet automatique si absente.

Haute priorité

Usage détourné

Positionnement explicite : aide à la veille, jamais outil de décision automatisée.

Moyenne

Biais de sources

Sélection par pays sur critère SIPRI, médias d'État marqués comme tels dans le digest.

Moyenne

Dérive de coût LLM

Plafond d'appels/jour + escalade agentique bornée — codés et testés, pas seulement documentés.

Preuve par l'usage · 1/2

Le chiffre flatteur a été questionné avant d'être retenu

  • Garde-fou déclaré, non câblé. Le plafond d'appels LLM/jour existait dans la config sans être vérifié nulle part dans le code. Trouvé par auto-audit, corrigé, testé dans les deux sens.
  • Précision auto-questionnée. 27/30 d'accord avec l'annotation manuelle, au-dessus de la cible — retenu seulement après avoir requestionné l'annotation elle-même, ce qui a révélé des définitions de catégorie ambiguës plutôt qu'un défaut du classifieur.
  • Deuxième mesure, plus sévère. Après la reprise des sources : 73/88 (83 %), sous la cible. Le protocole d'annotation comportait lui-même un biais — documenté dans le cadrage plutôt que le chiffre présenté comme acquis.
  • Troisième mesure, décomposée. 51/68 (75 %) sur un échantillon reconstruit. Le global était le moins informatif : le tri du bruit tient la cible (85 %), la qualification de ce qui parvient au digest échoue une fois sur trois (64 %). Deux problèmes distincts qu'un chiffre unique confondait.
  • Le retest a démenti la sonde qui l'avait précédé. Retest à deux bras sur 17 items : la règle reformulée gagne ses deux cas de référence sans aucune régression. Mais les contrôles — passés cette fois, alors que la sonde s'était arrêtée à deux cas — ont trouvé deux régressions antérieures, et un troisième bras les a attribuées au changement de la veille plutôt qu'à la reformulation. Le gain que ce changement revendiquait ne se reproduit pas : rejoué quatre fois sur le prompt d'avant, le cas sort déjà correctement. Une sonde à n=2 comparait une observation à une observation.
  • Quatrième mesure, en aveugle. 38/48 (79 %) — le script d'annotation montrait jusque-là le verdict du système avant de demander le jugement humain, un biais d'ancrage retiré le jour même. À n=48 la cible de 85 % tombe dans l'intervalle de confiance : la mesure ne conclut ni dans un sens ni dans l'autre, et le dire vaut mieux que citer 79 % comme un verdict. Elle confirme en revanche, indépendamment, la frontière que la précédente avait désignée.

Une mesure de précision teste autant la clarté des définitions que la qualité du modèle. Les deux s'auditent ensemble — et l'audit s'est corrigé lui-même ici : le cadrage n'énonçait rien sur la frontière incriminée, mais le prompt portait une règle non documentée depuis cinq jours, que le modèle appliquait fidèlement. Désaccord de spécification et non lacune — la règle a été changée, pas ajoutée, et reportée dans le cadrage. Sondée dans la foulée : efficace sur le cas qui la motivait, sans effet sur un second qu'elle nomme pourtant explicitement. Une règle peut être écrite, juste, et ne rien déplacer. Le retest complet, passé depuis, a corrigé le second cas — et montré que l'effet revendiqué sur le premier n'était pas reproductible. Ce qui reste ouvert n'est plus une question de règle mais d'annotation : deux articles décrivant le même type d'événement portent des étiquettes opposées, et aucune formulation ne peut satisfaire les deux.

Preuve par l'usage · 2/2

Les défauts sont venus du test, pas de la relecture

  • Le volume réel a démenti l'estimation. La reprise des sources a fait apparaître des flux exposant des mois d'historique. Sans fenêtre de fraîcheur, le premier run aurait consommé le budget d'une journée entière sur l'arriéré avant de s'interrompre.
  • Symptôme à l'affichage, cause en amont. Deux pays seulement ressortaient sur la carte. Plutôt que d'ajouter des règles de rattrapage à la restitution : mesurer d'abord. 10 des 11 lieux manquants avaient leur pays nommé dans le titre — or la vérification verbatim ne portait que sur le corps de l'article, et effaçait des extractions correctes.
  • Corrigé sans affaiblir le garde-fou. Le titre est du texte publié par la source : l'extrait doit toujours y correspondre mot pour mot. Couverture passée de 6 à 13 lieux sur 16 items.
  • Un plantage a révélé la vraie perte. Une réponse de modèle hors énumération a interrompu un run. Au relancement : zéro item neuf — le dédoublonnage marquait les liens comme vus avant l'analyse, donc les items du run perdu étaient réputés traités sans exister nulle part, et exclus de toutes les collectes suivantes. Le marquage appartient désormais au nœud qui a réellement payé l'appel.

Remonter du symptôme à la cause plutôt que corriger là où le problème se voit — et documenter ce qui reste non vérifié plutôt que de l'omettre. Aucun de ces défauts n'était visible en relecture de code.

Feuille de route

V1 solide, prochain jalon identifié précisément

V1
Collecte + dédoublonnage + classification + résumé tracé + API + frontend — testé de bout en bout
V1
Sources par pays : top 10 exportateurs SIPRI + Iran/Corée du Nord, chaque flux validé en direct
V1
Déploiement — moitié dépôt le 2026-08-23 (journal structuré, endpoint de run fermé, dépendances épinglées, image conteneur), moitié cloud le 2026-09-05 : base managée, service et traitement par lot déployés, déploiement continu sur publication de code, infrastructure adoptée en Terraform sans dérive. Premier traitement réel 615 s, 61 articles retenus, 195 appels sur 200. Reste l'ordonnanceur à armer et la purge à sept jours à constater
V2
Vérificateur, 1re tranche : recoupement sur l'historique et score de confiance, sur les catégories les plus sensibles
V2
Carte de couverture interactive, construite sur le lieu vérifié de chaque événement
V2
Vérificateur étendu aux cinq catégories le 2026-08-20 : l'escalade est conditionnée à un antécédent candidat mesuré, plus à la catégorie
V2
Récupération du texte intégral livrée le 2026-08-31 — mais la mesure qui la motivait désignait le mauvais correctif : 4 des 6 citations non vérifiables tenaient à la typographie (apostrophes courbes contre droites), pas à la longueur des extraits. Le module reste justifié par la classification, où un extrait tronqué ne contient pas ce qu'il faut pour classer
V3
Raisonnement longitudinal, 1re tranche : threads d'événements — le signal d'une veille se situe largement entre les items, pas dans l'item isolé
V3
Brief hebdomadaire et détection de signal faible — chiffres issus d'une agrégation, jamais du modèle ; alerte gardée par un taux de fausses alertes mesuré avant exposition
V3
Mémoire interrogeable sur l'historique (requêtes en langage naturel)

Deux chantiers, dans cet ordre. Le budget d'abord. L'extension du vérificateur aux cinq catégories a tourné en réel le 2026-08-21 (15 escalades sur 36 articles, 5 avec antécédent) et a saturé le plafond de 200 appels du jour — le déficit est retombé sur le regroupement en threads, dernier de la chaîne. Premier relevé réel le 2026-08-22 : analyse 72 appels, vérification 50, regroupement 73, soit 195 des 200. Il montre que les plafonds d'escalade sont sur-souscrits — ils autorisent 140 appels à eux deux, quand l'analyse en réclame un par article soumis et en a consommé 72 — et que 21 % du budget part sur des articles écartés après analyse. L'arbitrage reste ouvert délibérément : il ne se tranche pas tant que cette part d'un cinquième n'est pas ventilée par source, et la ventilation vient d'être instrumentée. Le déploiement ensuite, et sa moitié dépôt est faite. Le diagnostic n'avait pas buté sur l'absence d'infrastructure mais sur l'absence de journal : le pipeline n'émettait rien, donc les mesures ci-dessus auraient été invisibles sous un ordonnanceur. Journal structuré, endpoint de run fermé par jeton, dépendances épinglées, image conteneur et traitement par lot quotidien sont livrés et validés en local le 2026-08-23 — le lot a tourné de bout en bout contre des flux réels avec le plafond d'appels forcé à zéro, ce qui exerce la troncature sans rien dépenser. La moitié cloud a suivi le 2026-09-05, et l'inconnue est levée : la persistance de production a tourné, et la réservation de budget en transaction — le garde-fou qui ne pouvait être ni confirmé ni infirmé ailleurs qu'en production — tient sous concurrence réelle, 30 réservations simultanées sur 3 conteneurs pour 4 places, exactement 4 acceptées. La méthode a compté autant que le résultat : le mode opératoire prescrivait deux traitements complets lancés ensemble, qui n'ont produit qu'une seule réservation et ne se sont pas même chevauchés — le dédoublonnage les avait affamés. Un compteur sous le plafond serait passé pour une preuve. Reste à armer l'ordonnanceur, et à constater la purge à sept jours au huitième jour d'historique.

En synthèse

Un cadrage complet, appliqué à un système réel — pas juste des slides

MECE, alternatives évaluées, KPIs, risques, gouvernance — avec le même niveau d'exigence de vérification empirique du début à la fin, jusqu'à la mesure de précision finale.