Skip to content

Pipeline d'IA

Ce qui se passe entre « une alerte arrive » et « un verdict est écrit ». La couche de triage de SocTalk est une machine à états LangGraph — un superviseur qui achemine le travail vers des nœuds worker spécialisés, puis un nœud de verdict qui décide si le cas nécessite une revue humaine.

Cette page est le modèle mental. Le code se trouve dans src/soctalk/graph/, src/soctalk/supervisor/ et src/soctalk/workers/.

Nœuds

NœudRôleModèle utilisé
supervisorDécide de la prochaine action. Routage pur — n'effectue lui-même aucun travail métier.modèle rapide
wazuh_workerRécupère l'alerte en contexte, extrait les observables (IP, hachages, utilisateurs, processus), corrèle avec les alertes récentes du même tenant.modèle rapide
cortex_workerEnvoie les observables aux analyseurs Cortex (VirusTotal, AbuseIPDB, etc.) pour la réputation/l'enrichissement.modèle rapide
misp_workerRecherche les observables dans les flux de renseignement sur les menaces MISP pour le contexte de campagne/acteur connu.modèle rapide
verdictRaisonne sur tout ce que les workers ont collecté. Produit `escalateclose
human_reviewMet le run en pause ; émet une demande d'examen vers la file du tableau de bord et/ou Slack. Attend une HumanDecision (`approvereject
closeGénère le rapport de clôture et écrit la disposition (`close_fpescalate

Routage du superviseur

Le seul travail du superviseur est de choisir le nœud suivant. Son espace de décision est une énumération fixe à 5 éléments :

DécisionSignification
INVESTIGATEJe n'en sais pas encore assez sur cette alerte. Exécuter le worker Wazuh.
ENRICHJ'ai des observables dont je n'ai pas vérifié la réputation. Exécuter Cortex.
CONTEXTUALIZELes observables semblent intéressants ; rechercher des campagnes/acteurs connus. Exécuter MISP.
VERDICTJ'en ai assez. Transmettre au nœud de verdict.
CLOSEIl s'agit d'un cas tranché (par exemple, un faux positif évident ou une alerte déjà résolue). Ignorer le nœud de verdict.

Le superviseur n'invoque jamais lui-même d'outils externes. Il lit le SecOpsState accumulé (alertes, observables, sorties de workers antérieures, verdicts) et produit l'une des cinq décisions. La plupart des cas enchaînent superviseur → worker → superviseur → worker → superviseur → VERDICT, soit trois à six sauts au total.

Nœud de verdict

Le modèle de raisonnement reçoit tout l'état accumulé — alerte d'origine, conclusions de chaque worker, tous les observables avec leur enrichissement, tentatives de verdict antérieures (si NEEDS_MORE_INFO a bouclé). Il produit :

ChampType
decision`escalate
confidenceénumération : `low
rationalemarkdown court
evidence_strength`weak
verdict`benign
impact`low

escalate passe toujours par human_review. close ignore la revue humaine et va directement à close. needs_more_info retourne au superviseur avec une invite suggérant ce qui manque encore.

Portail de revue humaine

human_review met le run en pause. Le cas apparaît dans la file d'examen du tableau de bord et (si Slack est configuré) dans le HIL bidirectionnel Slack. L'humain choisit :

DécisionEffet sur le cas
approveExamen en attente marqué comme terminé + retour audité. Pas de reprise automatique ; suivi par l'analyste.
rejectLe cas se clôt en auto_closed_fp. Terminal — le graphe n'est pas ré-invoqué.
more_infoExamen marqué info_requested avec la liste de questions. Pas de reprise automatique ; suivi par l'analyste.

L'identité de l'humain, l'horodatage et la justification sont ajoutés au journal case_events du cas, en ajout seul.

Cycle de vie d'un run

Un « run » est une exécution du graphe sur un cas. Énumération de statut :

StatutSignification
activeLe graphe est en cours d'exécution.
waiting_on_gateEn pause à human_review.
pausedMis en pause manuellement par un administrateur MSSP.
halted_budgetA atteint le budget de tokens par run. Les runs V1 normaux prennent tokens_budget = 200,000 depuis la ligne case_runs (valeur par défaut du modèle). La variable d'environnement SOCTALK_CASE_RUN_TOKEN_BUDGET (par défaut 15,000) n'est utilisée qu'en repli lorsque la ligne n'a aucune valeur définie.
completedLe graphe a atteint close et a écrit une disposition.
failedLe graphe a rencontré une erreur ou un outil externe est injoignable.

Les budgets de tokens sont suivis par run, par tenant et à l'échelle de l'installation. Voir Observabilité pour les métriques, Fournisseurs LLM pour les leviers de coût.

Le processus runs-worker

Chaque tenant possède son propre pod runs-worker (dans l'espace de noms tenant-<slug>) qui consomme la file :

  1. Appelle POST /api/internal/worker/runs/claim pour un run assigné à son tenant.
  2. Construit le LangGraph à partir du chart de nœuds.
  3. ainvoke() sur le graphe, en publiant POST /api/internal/worker/runs/{run_id}/heartbeat toutes les 20 s.
  4. À la fin, publie l'état final et la disposition vers POST /api/internal/worker/runs/{run_id}/complete.

Le runs-worker est le seul pod de calcul par tenant — le garder dans l'espace de noms du tenant signifie qu'un tenant dépassant son budget ne peut pas priver le reste de l'installation de calcul. La logique superviseur + worker + verdict elle-même est sans état ; le gros du travail réside dans les appels LLM (hors cluster, facturés au fournisseur configuré du tenant).

Pointeurs de code source

ConceptFichier
Constructeur de graphe + routagesrc/soctalk/graph/builder.py
Logique du superviseursrc/soctalk/supervisor/node.py
Nœud de verdictsrc/soctalk/supervisor/verdict.py
Nœuds workersrc/soctalk/workers/
Clôture / dispositionsrc/soctalk/graph/close.py
Boucle du runs workersrc/soctalk/runs_worker/main.py
Schéma d'étatsrc/soctalk/models/state.py

Publié sous la licence Apache 2.0.