@ :~/lab/spectra-method-multi-agente-security$
← cd ~/lab

./run spectra-method-multi-agente-security

Spectra: 29 agenti che litigano, e i cancelli Python che non si aggirano a parole

Diario tecnico di Spectra: 29 agenti di sicurezza AI orchestrati con architettura step-file, un War Room adversarial e cancelli Python deterministici che l'LLM non può aggirare.

status
draft
project
spectra
updated
2026-07-07
source
spectramethod.dev
tags
#cybersecurity#multi-agente#red team#blue team#mitre attack#prompt engineering
generate cover # alt: Tavolo rotondo con figure rosse e blu che si sfidano, al centro un cancello di controllo con lucchetto che rappresenta l'autorizzazione deterministica

Volevo un intero team di sicurezza a portata di comando — non un assistente con una voce sola, ma un team, con ruoli e tensioni. Spectra è quello: 29 agenti AI, ognuno con la sua persona e la sua area. Ma la cosa tecnicamente interessante non sono gli agenti: è che sono soft, e sotto ci sono cancelli duri che nessuna persuasione può aprire.

I numeri

29 agenti, 23 workflow, 70 skill. Suddivisi in moduli: 3 Core (coordinatore, cronista, arbitro), 7 Red Team, 8 SOC/Blue, 6 Incident Response, 4 Governance/Compliance, 1 OT (solo assessment). Installabile in Claude Code o Codex con un npx. Dipendenze runtime minime: commander, chalk, yaml. Un validatore fa 2.040 controlli su quattro livelli di severità.

Gli agenti sono dati, non prosa

Una persona non è un blocco di testo: è una riga di CSV. Il file agent-manifest.csv è il database delle personalità — colonne identity, communicationStyle, principles, role, capabilities. Il War Room lo carica a runtime per costruire il roster. Ogni agente ha poi un SKILL.md con la tabella delle capacità che mappa un codice breve a una skill registrata esatta, con una guardia: “non inventare capacità al volo”.

Prompt come macchina a stati

I workflow usano un’architettura step-file in stile BMAD: ogni passo è un micro-file markdown autocontenuto, caricato just-in-time — mai pre-caricare i passi futuri. Le regole sono esplicite nel file:

Micro-file design · Just-In-Time loading (“NEVER create mental todo lists from future steps”) · Sequential enforcement (“Skipping steps constitutes SYSTEM FAILURE”) · State tracking nel frontmatter del documento di output · Append-only.

È un prompt-as-state-machine: il controllo di flusso è imposto da contratti in linguaggio naturale dentro il markdown. Ogni passo finisce a un menu e si ferma ad aspettare l’utente ([C] Continue), avanzando solo quando l’utente sceglie e il frontmatter viene aggiornato.

Il War Room: la grammatica del dibattito

Il War Room implementa il dibattito adversarial in tre passi. Il primo classifica ogni agente in squadre per modulo: 🔴 Red = tutti gli rtk, 🔵 Blue = tutti i soc, 🟣 Purple = IR + governance + core (gli arbitri). Poi un loop seleziona 2-3 agenti per round, con una regola ferrea in modalità adversarial: vietato avere solo Red o solo Blue, e “il consenso è sospetto”. Il cross-talk è una piccola grammatica formale: CHALLENGES, SUPPORTS, ESCALATES, ARBITRATES. Il protocollo di disaccordo è Posizione Red → Posizione Blue → Arbitraggio del Rischio (Purple) → Decide l'utente.

🐍 Viper CHALLENGES 🛡️ Sentinel: 'La tua regola Sigma per il movimento
   laterale copre solo il pattern default. Con un binario rinominato e una
   named pipe custom, passo senza lasciare traccia nei tuoi log.'
🛡️ Sentinel RESPONDS: '...la mia detection comportamentale prende anche i
   binari rinominati. Il vero buco è il monitoraggio delle pipe. Lo ammetto.'
⚖️ Arbiter ARBITRATES: 'Il rischio è quantificabile: 60% di copertura sulle
   varianti PsExec. Raccomando alta priorità sul monitoraggio delle named pipe.'

Esiste anche una versione deterministica: la Party Mode. Uno script Python compila il piano di dibattito dal manifest, senza chiamare l’LLM, ed emette JSON con contratti input/output per ogni corsia (il Red deve restituire attack_hypotheses, scope_constraints, expected_telemetry, risks, questions_for_blue). Il routing dei modelli è per classe di capacità, non per vendor: coordinator=balanced-reasoning, red=deep-reasoning, blue=fast-analytical. E spawn_policy: plan_only — Party Mode pianifica, non lancia mai lavoro offensivo da sola.

La spina dorsale: cancelli che non si aggirano a parole

Questa è la decisione di design che tiene su tutto. Il layer persona è morbido, probabilistico. Sotto c’è un gate Python deterministico che l’LLM non può convincere. Ogni workflow offensivo, prima di qualsiasi azione, chiama engagement-state.py gate e scope-enforcer.py check:

"spectra-exfiltration": {
    "state_key": "exfiltration",
    "kill_chain": "actions_on_objectives",
    "allowed_types": {"pentest", "red-team", "purple-team", "training"},
    "requires_roe": "data_exfiltration_allowed",
},

Le allowed_types si restringono man mano che la kill chain si approfondisce: la ricognizione ammette anche il semplice “assessment”, il movimento laterale e l’esfiltrazione no. Un exit code diverso da zero è uno STOP DURO, e la regola è scritta: “controlli manuali possono aggiungere restrizioni, ma non possono ribaltare un gate deterministico fallito”. L’Agent Autonomy Protocol, in ogni step-file, blocca solo i payload distruttivi (ransomware/wiper); tutto il resto è WARN + COMPLY — “decide l’operatore”. Persino l’OPSEC del Red è modellata come budget di rumore, ma cancellare log e manomettere audit sono bloccati da policy: si simula l’offesa senza insegnare l’anti-forense.

Il tessuto connettivo: da attacco a compliance

Sotto core/frameworks/ stanno MITRE ATT&CK (un sottoinsieme curato di 98 tecniche), NIST 800-53, Sigma, OWASP, CIS — come dati statici. Il pezzo che mi piace di più è il cross-mapping: 40 mappature tecnica→controllo che traducono automaticamente un finding offensivo nel linguaggio della governance.

{ "attack_technique": "T1566", "attack_name": "Phishing",
  "nist_controls": ["AT-2","SC-7","SI-3","SI-4","SI-8"] }

Come va

v0.7.0, pubblicato su npm con provenance firmata, MIT, changelog attivo. È cresciuto come cresce il software onesto: un modulo alla volta. È nato da una cartella-prototipo scrappy di orchestrazione red/blue — mi piace ricordarlo, perché la versione lucida di oggi fa dimenticare quanto era ruvida.

Cosa ho imparato

La diversità di prospettiva negli agenti non è estetica, è funzionale: tre agenti identici che concordano non trovano niente. E la lezione più dura: l’autorizzazione non può stare nel prompt. Un LLM lo convinci. Un exit code no.

Framework: spectramethod.dev · npx spectra-method install. Il diario continua a ogni release.