Chapitres

DOC-05 / Référence technique · Chapitre 01

Vue d'ensemble du harness agentique

Le harness transforme une demande (courriel, console, cron) en action déployée en enchaînant classification, spawn LLM via pseudo-TTY, validation qualité à deux niveaux et boucle d'apprentissage, le tout sans état métier hors base de données.

1. Ce qu'est le harness

Le « harness » est l'ensemble du dispositif qui transforme une demande (un courriel transmis, un message dans une console de pilotage, un déclencheur planifié) en action exécutée et déployée (du code commité, une réponse préparée pour validation humaine, un site mis à jour), sans état métier stocké hors base de données.

Trois principes le structurent :

  • Base de données unique. La base PostgreSQL est la seule source de vérité métier. Les fichiers de documentation ne portent que des guides opérationnels, des schémas d'architecture et des doctrines. Tout référentiel (serveurs, clients, missions, agents, journaux d'apprentissage, exécutions) vit en table.
  • Asymétrie déploiement/publication. La mise à jour des environnements de préproduction est déclenchée automatiquement par le système. La mise en production finale est un geste manuel et exclusif d'un opérateur humain. Le système ne publie jamais en production de lui-même.
  • Gouvernance par garde-fous. Vérifications antivirus obligatoires avant ouverture de toute pièce jointe, façade d'envoi de courriels unique soumise à validation, protection anti-fuite des secrets, procédure en sept étapes pour créer une mission structurée. Toute violation déclenche une dette architecturale prioritaire.

Le harness sert un cockpit de pilotage privé — distinct des produits e-commerce publics et des configurations spécifiques aux clients. Cette page ne couvre que le harness lui-même.


2. Topologie réelle

Trois couches d'exécution communiquent toutes avec le même schéma PostgreSQL, mais via des transports différents :

  • Le cockpit (application Nuxt 4 Nitro, mode standalone) — l'interface de pilotage. Accès à la base via un pool postgres-js équipé d'un adaptateur de traduction SQL MySQL→PostgreSQL à la volée : substitution des paramètres positionnels, qualification du schéma sur les tables métier, conversion de INSERT IGNORE, DATE_SUB/DATE_ADD, TIMESTAMPDIFF, IFNULL et des alias en camelCase. Certaines constructions MySQL ne sont pas converties automatiquement (ON DUPLICATE KEY UPDATE, LAST_INSERT_ID(), GROUP_CONCAT, FIND_IN_SET, DATE_FORMAT, CURDATE()) et doivent être portées manuellement. L'application se décompose en 27 modules indépendants.
  • La couche d'automatisation Python (236 façades) — orchestration, automates, mémoire, audits, courriels, déploiement. Accès à la base via un conteneur de base de données dédié, en passant les requêtes par sous-processus.
  • Les scripts et le planificateur — wrappers de déploiement, spawn du moteur LLM via pseudo-TTY, extraction de pièces jointes, sauvegardes, tests de régression. Le planificateur intégré à l'application Nuxt est hors service depuis mai 2026 ; l'ordonnancement repose exclusivement sur le crontab Linux de la machine hôte (69 entrées actives).
                    DEMANDE
 courriel transmis ──┐       ┌─── console de pilotage
 boîte agentique     │       │    (scopée mothership | tenant)
                     ▼       ▼
     ┌─────────────────────────────────────────────────────┐
     │  COUCHE PYTHON — 236 façades                        │
     │  Orchestrateur : poll + classification + spawn       │
     │  Exécution : worker de tâches, cycle ReAct           │
     │  Mémoire / audits / courriels / déploiement          │
     │  Invocation LLM headless via pseudo-TTY              │
     │                    (jamais subprocess direct)         │
     └──────────────┬──────────────────────┬───────────────┘
    sous-processus  │                       │ SSH + conteneur
                    ▼                       ▼
     ┌────────────────────────┐   ┌──────────────────────────┐
     │  POSTGRESQL            │   │  COCKPIT (Nuxt 4)        │
     │  schéma unique         │◄──┤  interface de pilotage   │
     │  271 tables + 18 vues  │   │  pool postgres-js        │
     │  tables métier         │   │  adaptateur MySQL→PG     │
     │  vues-shim legacy      │   │  27 modules              │
     └────────────────────────┘   └──────────────────────────┘
                    ▲
     planificateur  │  crontab Linux (69 entrées)
     (Nitro hors    │  scripts shell / Node
      service)      │
     ┌──────────────┴──────────────────────────────────────┐
     │  SCRIPTS ET CRON — déploiement, hooks, sauvegardes  │
     │  Asymétrie : déploiement préproduction = automatique │
     │              publication production = geste humain   │
     └─────────────────────────────────────────────────────┘

Points d'attention architecturaux clés :

  • Le schéma PostgreSQL est distinct de la base par défaut (public) ; une qualification explicite du schéma est requise sur toutes les requêtes.
  • Douze tables du registre des agents sont en réalité des vues qui encapsulent les tables physiques sous-jacentes — héritage d'une migration progressive. En lecture, utiliser les vues ; en écriture, cibler les tables physiques.
  • Une même entité « mission » est répartie entre des tables historiques (données de pilotage) et des tables cockpit (suivi d'exécution).
  • Le cockpit est standalone : il n'étend pas la base de code e-commerce. La sécurité réelle repose sur l'infrastructure réseau (tunnel et porte de filtrage nginx) ; un middleware injecte automatiquement une session opérateur en interne.

3. Cycle de vie complet d'une demande

Le chemin canonique « courriel → action déployée ». Deux portes d'entrée alimentent le même moteur d'orchestration : le poll de la boîte agentique et la console de pilotage.

(0) INGESTION
    Un opérateur transmet un courriel vers la boîte agentique
       │  planificateur */1 min — poll IMAP (SEARCH UNSEEN)
       ▼
    Enregistrement en base (brut) ──► file agentique (status='received')
       │
(0b) SCAN ANTIVIRUS (si pièce jointe — doctrine scan-first P0)
       │  Analyse ClamAV + heuristiques (PDF malveillant, macros Office, exécutables)
       │  verdict ∈ {clean, suspect, blocked} ; verdict ≠ clean ⇒ classification BLOQUÉE
       ▼
(1) CLASSIFICATION  (LLM via façade IA unifiée, énumération stricte, anti-injection)
    classified_intent ∈ {run, chantier, question, noise, negociation, conseil}
       │  matérialise au plus 1 ligne dans la table correspondante
       ▼
(2) SPAWN + ORCHESTRATION  (planificateur */5 min, décalé 120 s après classify)
    Orchestrateur Python
       │  verrou consultatif PostgreSQL (anti-double-spawn)
       │  spawn du moteur LLM via pseudo-TTY (node-pty, stream-json) :
       │    isolation de contexte inter-spawns (zéro fuite entre exécutions)
       │    modèle configuré, mode permissions contrôlé
       │    outillage optionnellement restreint (ex. validateur QA en lecture seule)
       │    timeout configurable (défaut : 15 min, extensible à 40 min par l'appelant)
       │    ⚠️ ordre des arguments CLI : les arguments varargs doivent précéder les flags
       │    ⚠️ le flux de log doit se clore APRÈS l'émission de l'événement de sortie
       │    ⚠️ le pipe stdout doit être drainé avant la sortie du processus
       │  le moteur LLM dépose un fichier résultat JSON puis se termine
       ▼
    Post-traitement de l'orchestrateur
       ├─ branche sans code (run/question/negociation) → récapitulatif courriel → 'actioned'
       └─ branche avec code (chantier) → déploiement en préproduction automatique
              └─ Validation qualité à 2 niveaux par route :
                     Niveau 1 — requête HTTP (statut + détection de patterns d'erreur,
                                bypass SSH optionnel pour contournement du filtre nginx)
                     Niveau 2 — navigateur Playwright chromium headless
                                (erreurs console, erreurs de page, capture d'écran)
                     Filtres de bruit : erreurs 401 et ERR_HTTP2 ignorées
                                        sur les environnements preprod protégés
                    ├─ OK   → récapitulatif courriel vers l'opérateur → status='actioned'
                    └─ FAIL → re-spawn (max 3 itérations) sinon escalade humaine
       ▼
(3) MISSION STRUCTURÉE (si intent=chantier, voir documentation dédiée)
    procédure 7 étapes : audit des agents → lettre de mission → recrutement ≥2 agents
       │  création atomique : mission + travaux + tâches en une transaction
       ▼
    EXÉCUTION des agents : worker de tâches (*/1 min) ou cycle ReAct
       │  cascade de statut tâche→travail→mission (max 1 cran) ; équipe QA si recrutée
       ▼
    mission → 'test' (validation preprod, revue opérateur) ── manuel ──► publication → 'done'
       ▼
(4) APPRENTISSAGE (asynchrone)
    journal d'apprentissage (échec/victoire) → réindexation vectorielle →
    suggestion validée par l'humain → règle dans la mémoire persistante →
    réflexe disponible à la session suivante

Côté courriels sortants, rien ne part jamais directement vers un destinataire externe : tout transite par la façade d'envoi de courriels (rédaction → copie de validation pour l'opérateur → envoi après accord explicite). Le système écrit à l'opérateur interne, jamais au demandeur.

L'ordonnancement repose sur le crontab Linux : poll IMAP et scan en continu (*/1 min), spawn décalé (*/5 min + 120 s), worker de tâches en continu (*/1 min), plus 69 entrées cron actives pour les automates récurrents, les workers et les observateurs.


4. Glossaire des noms cardinaux

Nom Définition Support physique
Orchestrateur (Atlas) Le chef d'orchestre du harness. Une persona enregistrée en base sans runtime propre : « être l'orchestrateur » = lancer un moteur LLM avec le prompt système dédié. Pilote la classification, le spawn, l'orchestration post-spawn. Façades Python d'orchestration + module de spawn pseudo-TTY
Agent Une persona (identité + cadre cognitif + périmètre métier) injectée dans le contexte d'un moteur LLM pour exécuter une tâche. 30 agents actifs, répartis en 4 familles : direction, cadrage, execution, validation. Un agent délibère (cycle ReAct), il n'exécute pas une routine figée. Registre des agents en base ; persona chargée par une façade dédiée ; 30 définitions dans le répertoire des agents
Automate Un script déterministe qui exécute une routine ; peut invoquer un LLM mais son flux de contrôle est codé en dur. Opposé conceptuel de l'agent. Registre des automates en base ; journal d'exécution dédié
Chantier Une mission structurée multi-étapes. Unité de travail de plus haut niveau. Créée atomiquement avec ≥1 travail et ≥1 tâche via une procédure dédiée. Hiérarchie : 1 chantier = N travaux = N tâches. Table des missions en base
Travail Un lot granulaire d'un chantier (phase ou sous-objectif), avec son agent responsable, son périmètre et ses critères de sortie. Porte les cascades de statut et le mécanisme de déblocage (travail-bis). Table des travaux en base
Tâche L'unité atomique assignée à un agent, avec estimation de tokens et modèle recommandé. Table des tâches en base
Run Une exécution scopée pilotée par l'orchestrateur sur un périmètre (cockpit interne ou site client), le périmètre chargeant le contexte (serveur, client, boîte mail). Déclencheur : courriel transmis ou console de pilotage. L'enregistrement d'exécution de tâche n'est PAS un run : c'est l'unité d'exécution déléguée à un agent. Table des runs en base ; console de pilotage dédiée
Cicatrice Une leçon gravée d'une erreur (kind='failure') ou d'un succès reproductible (kind='victory'). Indexée en vecteurs pour le rappel sémantique, scorée en importance, porte d'entrée de la boucle d'apprentissage. Table des cicatrices en base + index vectoriel pgvector
Orbite Anneau d'organisation des agents (1/2/3). Notion double : la colonne numérique de la base (sous-utilisée) ne mappe pas 1:1 sur le rendu visuel du réacteur, qui recalcule l'anneau depuis la famille (direction=1, cadrage/execution=2, validation=3). C'est la famille qui fait foi. Colonne orbite + colonne group_name dans le registre des agents
Façade Un point d'entrée unique obligatoire pour une capacité, qui rend une opération non-contournable (courriels, invocation IA, scan antivirus, accès base de données). Souvent doublée d'un hook qui bloque le contournement. Façades Python + hooks de vérification pré-outil

Autres termes utiles : knock-gate (filtre nginx cookie+slug en amont du cockpit), pseudo-TTY (terminal virtuel obligatoire pour spawner le moteur LLM de façon programmatique), scan-first (doctrine : aucune pièce jointe ouverte avant verdict antivirus clean), travail-bis (travail portant une référence de déblocage pour déverrouiller un travail en attente).


5. Les frontières dures (non-négociables)

Rappel condensé des règles que tout le harness fait respecter :

  • Base unique — zéro contenu métier dans des fichiers statiques (JSON, TypeScript, Markdown) ; tout en base de données.
  • Anti-fuite de secrets P0 — aucun secret en clair dans un fichier versionné ; les secrets vivent dans des fichiers d'environnement hors dépôt, référencés par nom de variable uniquement.
  • Scan antivirus avant ouverture — toute pièce jointe reste fermée jusqu'au verdict clean du moteur antivirus.
  • Zéro communication client directe par le système — façade d'envoi de courriels + validation humaine avant envoi + prise de rendez-vous uniquement via le lien Calendly canonique.
  • Procédure 7 étapes — aucun chantier sans création atomique via la procédure dédiée, avec ≥2 agents distincts pour un périmètre client.
  • Commit en flux — aucun travail terminé sans commit immédiat ; l'IA commit, l'opérateur humain ne tape jamais les commandes git de bas niveau ; un hook bloquant garantit l'invariant à chaque fin de session.

6. Les autres pages de la documentation

Page Sous-système couvert
02 — La couche données Base de données unique, préfixes de tables, adaptateur MySQL→PostgreSQL, classes Entity Python, vues-shim legacy, i18n en base
03 — Le cœur agentique Orchestrateur, modèle d'agents, classification d'intent, spawn pseudo-TTY, orchestration déploiement→QA→courriel, orbites, calibration
04 — Chantiers, travaux et tâches Hiérarchie mission/travail/tâche, création atomique, procédure 7 étapes, verrou multi-session, cascades de statut, travail-bis
05 — Automates, crons et runs 236 façades, wrapper cron, registre des automates, distinction run / enregistrement de tâche, double planificateur (Nitro hors service + crontab)
06 — Le cockpit Application Nuxt, modules, pages de pilotage, endpoints internes, authentification knock-gate + auto-session, consoles
07 — Boîte de réception, boîte agentique et courriels Deux pipelines IMAP (cockpit vs boîte agentique), façade d'envoi de courriels, scan antivirus, zéro communication directe
08 — Mémoire et apprentissage Mémoire 3 niveaux (fichiers persistants / notes / index vectoriel), rappel RAG, boucle cicatrices→suggestions→leçons, façade IA unifiée
09 — Déploiement et infrastructure Asymétrie déploiement/publication, dispatcher YAML, build + transfert compressé, auto-déploiement du cockpit, inventaire serveurs, secrets, commit avant déploiement
10 — Catalogue des façades et points d'entrée Recensement des façades Python + scripts par famille, mode d'invocation (cron/CLI/skill/hook/lib), hooks recensés
11 — Skills, agents et hooks Compétences slash-commandes, définitions des sous-agents, hooks de configuration + permissions/env