Anatomia di una harness Claude Code di produzione: hook, rules, skill custom, permission engine

Anatomia di una harness Claude Code di produzione: hook, rules, skill custom, permission engine

Il client di default di un agente di coding è uno strumento eccellente per provarlo, e del tutto inadeguato per affidargli lavoro vero su sistemi che contano. La differenza tra "ci gioco" e "ci lavoro ogni giorno su decine di codebase" non sta nel modello, che è lo stesso, ma in tutto ciò che gli costruisci attorno. Quello che chiamo harness è esattamente questo: un sistema di controlli che avvolgono un nucleo probabilistico per renderlo prevedibile dove la prevedibilità conta. Il mio setup, costruito sopra il framework open source gash, ha quattro strati, e li smonto qui pezzo per pezzo perché è informazione di prima mano che raramente trovi scritta: gli hook di validazione, le rules path-scoped, le skill custom e il permission engine. Non è una collezione di trucchi, è l'applicazione di un principio preciso.

Un agente affidabile non si ottiene fidandosi di più del modello, ma spostando le decisioni critiche fuori dal modello, dentro uno scaffolding deterministico. Dove serve una garanzia, non puoi affidarti a qualcosa che per costruzione è probabilistico.

Questo è il filo che lega i quattro strati, ed è la lente con cui voglio che li leggi. Un large language model è non deterministico per natura: lo stesso input può produrre risposte diverse, e va benissimo che sia così, perché è da lì che viene la sua capacità di ragionare e generare. Ma "va bene che sia variabile" è vero per la stesura di una funzione, non per la decisione se eseguire rm -rf o a quale endpoint mandare la tua API key. Per quelle decisioni servono garanzie, e le garanzie si costruiscono con codice che gira a prescindere da cosa il modello sceglie di fare.

Perché un agente probabilistico ha bisogno di scaffolding deterministico?

La risposta sta nella natura stessa dello strumento, e la documentazione ufficiale di Claude Code la dice con una chiarezza che vale la pena riprendere. Gli hook, vi si legge, forniscono "controllo deterministico sul comportamento di Claude Code, garantendo che certe azioni avvengano sempre invece di affidarsi al modello perché scelga di eseguirle" (riferimento ufficiale sugli hook). È la frase chiave di tutta l'architettura: certe azioni devono avvenire sempre, non quando il modello lo ritiene opportuno. La validazione di un comando pericoloso, il caricamento del contesto giusto, il diniego di un'operazione distruttiva non possono essere lasciati al giudizio statistico di un sistema che, per quanto bravo, può essere distratto da un prompt ostile o semplicemente sbagliare.

Il rovescio della medaglia, ed è la parte che chi costruisce harness tende a dimenticare, è che lo scaffolding non deve soffocare ciò che rende utile l'agente. Un sistema troppo rigido, dove ogni passo è prescritto, riduce un modello capace a un esecutore di script e butta via il suo valore. L'arte sta nel mettere il determinismo solo dove serve una garanzia e lasciare libero il modello dove la sua variabilità è un vantaggio. I quattro strati che seguono sono esattamente la mappa di dove ho deciso che serve una garanzia.

Se gestisci sviluppatori che usano agenti di coding e vuoi impostare un setup che sia produttivo e governato insieme, nel mio hub dedicato all'AI per lo sviluppo raccolgo gli articoli con la metodologia che applico sul campo.

I quattro strati, e cosa rende deterministico ciascuno

Il primo strato sono gli hook: comandi shell definiti dall'utente che si eseguono a punti precisi del ciclo di vita dell'agente. Il più importante nel mio setup è il validatore pre-bash, un hook che intercetta ogni comando shell prima dell'esecuzione e lo blocca se corrisponde a pattern proibiti. Gira sempre, non quando il modello decide, ed è la spina dorsale del perimetro di sicurezza. Un dettaglio prezioso documentato ufficialmente: gli hook possono essere definiti anche dentro le skill e i subagent via frontmatter, e in quel caso sono attivi solo durante il ciclo di vita di quel componente. La parte di sicurezza di questo strato, il validatore e cosa neutralizza, l'ho approfondita in come difendo una harness Claude Code in produzione; qui mi interessa il suo ruolo nell'anatomia: è lo strato che rende deterministica la sicurezza.

Il secondo strato sono le rules path-scoped: regole con un frontmatter che dichiara a quali percorsi si applicano, e che vengono caricate automaticamente nel contesto quando l'agente tocca file corrispondenti. È un meccanismo elegante perché risolve un problema reale, il caricamento del contesto giusto al momento giusto, senza affidarlo alla memoria del modello. Una regola legata ai file .php carica le convenzioni PHP solo quando servono; una legata a content/** carica il contratto editoriale solo quando si scrive un articolo. Il contesto pesante non grava sempre, ma è garantito quando il lavoro lo richiede. È lo strato che rende deterministico il contesto:

# Esempio di rule path-scoped: si attiva sola quando l'agente tocca file PHP.
# Il caricamento non dipende dal fatto che il modello "si ricordi" di farlo.
---
paths:
  - "**/*.php"
  - "**/composer.json"
---
# Convenzioni: PSR-12, strict_types, prepared statements, early return...

Il terzo strato sono le skill custom: procedure incapsulate in una cartella con un file SKILL.md che ne descrive il contratto d'uso. Una skill trasforma un workflow ripetitivo, "proponi un articolo", "valida una bozza", "esegui il deploy", in un'unità invocabile in modo coerente, invece di reimprovvisare la procedura ogni volta. Il valore è duplice: la procedura è scritta una volta e applicata sempre allo stesso modo, e il body pesante della skill si carica solo quando la skill viene invocata, non occupando contesto a vuoto. È lo strato che rende deterministici i workflow, e si estende naturalmente verso l'esterno con i server MCP, come ho descritto in MCP server personalizzati per il workflow aziendale. La differenza pratica tra un senior che vive nell'agente e uno che lo subisce passa quasi tutta da qui: i workflow che ripeti diventano skill, e smetti di ridirli ogni volta.

Il quarto strato è il permission engine: il motore che decide, a livello di configurazione, cosa è consentito in autonomia, cosa richiede conferma e cosa è negato in assoluto. La documentazione dell'Agent SDK lo descrive come l'uso di "modalità e regole di permesso per definire cosa è consentito automaticamente" (riferimento permessi). Nel mio setup la regola d'oro è separare lettura da scrittura: leggere file, eseguire query read-only, ispezionare lo stato è in genere consentito; le scritture distruttive o onerose sono in "chiedi" o in "nega". La distinzione tra "chiedi" e "nega" non è cosmetica: una richiesta in "chiedi" può essere approvata, una in "nega" no, e le operazioni irreversibili stanno nella seconda categoria. È lo strato che rende deterministica l'autorizzazione, e la sua configurazione vive in una gerarchia precisa di file, da quelli utente a quelli di progetto:

{
  "permissions": {
    "allow": ["Bash(git status)", "Bash(git diff *)"],
    "ask":   ["Bash(git push *)"],
    "deny":  ["Bash(rm -rf *)"]
  }
}

I quattro strati al lavoro su un compito reale

La teoria si capisce davvero solo guardando gli strati cooperare su un'azione concreta, quindi prendo un esempio dal mio lavoro quotidiano: pubblicare un contenuto nel CMS attraverso l'agente. È un compito che tocca tutte e quattro le dimensioni, e mostrarlo passo per passo rende tangibile perché lo scaffolding non è burocrazia ma infrastruttura.

Quando chiedo all'agente di pubblicare, la prima cosa che entra in gioco sono le rules: appena tocca i file sotto la directory dei contenuti, si carica automaticamente il contratto editoriale e le regole di validazione, senza che io debba ricordargli "tieni presente il formato". Il contesto giusto è lì, garantito, perché il percorso del file lo ha attivato. Poi interviene la skill dedicata alla pubblicazione, che incapsula la procedura corretta: validare con il linter, generare l'immagine, importare nel CMS, rigenerare l'indice, nell'ordine giusto e con i controlli giusti. L'agente non improvvisa la sequenza ogni volta rischiando di saltare un passo: segue un contratto scritto una volta e applicato sempre uguale.

Mentre la skill esegue i suoi comandi, ogni invocazione di shell passa per l'hook di validazione, che la ispeziona prima dell'esecuzione. Se per un errore la procedura tentasse un'operazione distruttiva o una connessione verso un host non previsto, l'hook la fermerebbe a prescindere da come ci si è arrivati. E al momento della scrittura vera e propria nel CMS entra il permission engine: l'import di un contenuto è consentito in autonomia, ma le operazioni davvero distruttive sulla produzione, come cancellare un post o modificare massivamente dei campi, sono in "chiedi" o in "nega", così che un comando irreversibile non possa partire per inerzia.

Il risultato è che un'operazione potenzialmente delicata, scritta su un sistema in produzione, avviene con il contesto corretto caricato da solo, la procedura applicata in modo coerente, ogni comando filtrato, e le azioni irreversibili sbarrate. Nessuno di questi controlli dipende dal fatto che il modello "si comporti bene" in quel momento: sono garanzie strutturali. E la parte interessante è che io, nel frattempo, non ho dovuto pensarci: lo scaffolding lavora sotto, e la mia attenzione resta sul merito, cioè se il contenuto è buono, non sulla meccanica del pubblicarlo. È esattamente la sensazione di una harness ben fatta: le cose giuste accadono da sole e le cose pericolose non possono accadere, mentre tu ti occupi del problema reale.

Vale la pena notare che questo stesso schema scala oltre il singolo sviluppatore. In un team, le rules diventano la conoscenza condivisa che non va ripetuta a voce, le skill diventano i processi aziendali codificati, il permission engine diventa la policy di chi può fare cosa, e gli hook diventano i controlli di conformità che valgono per tutti. La harness, da strumento personale, si trasforma nel modo in cui un'organizzazione mette l'AI al lavoro senza rinunciare al governo.

Dove finisce lo scaffolding e comincia il giudizio del modello

Messi insieme, i quattro strati raccontano una filosofia coerente: sicurezza, contesto, workflow e autorizzazione sono troppo importanti per affidarli alla variabilità del modello, quindi li ancoro a codice deterministico; tutto il resto, il ragionamento, la generazione, la diagnosi di un problema, resta dominio del modello, dove la sua flessibilità è esattamente ciò che voglio. Questo equilibrio è il cuore del mestiere di chi costruisce harness, ed è anche dove si commettono i due errori opposti. Sotto-scaffolding: dare all'agente shell e credenziali senza validatori né perimetro, e sperare che vada bene, che è la postura da cui nascono gli incidenti. Sovra-scaffolding: prescrivere ogni passo, trasformando un modello capace in una macchina a stati rigida che si rompe al primo caso non previsto, buttando via il motivo per cui usi un'AI invece di uno script.

La domanda da farsi davanti a ogni decisione dell'agente non è "il modello la prenderà giusta?", è "questa decisione tollera di essere sbagliata?". Se sì, lasciala al modello. Se no, ancorala allo scaffolding. È questa la linea che separa i due mondi.

Un'euristica concreta che applico per decidere da che parte sta una decisione: guardo il costo del peggior errore possibile e quanto è reversibile. Se l'errore peggiore è un paragrafo scritto male, riscrivibile in trenta secondi, lo lascio al modello senza esitazione, perché il guadagno della sua flessibilità supera di gran lunga il costo di un occasionale passo falso. Se l'errore peggiore è un file cancellato, una chiave esposta o una scrittura distruttiva in produzione, lo ancoro allo scaffolding, perché nessun guadagno di flessibilità giustifica un danno irreversibile. La maggior parte delle decisioni cade nettamente da una parte o dall'altra, e il mestiere consiste nel collocare le poche ambigue con onestà, sempre verso il lato prudente quando si è in dubbio. È un calcolo che faccio in continuazione mentre evolvo il setup, ed è la ragione per cui una harness non è mai "finita": cambia con i compiti che le affido.

La cosa che porto a casa da anni vissuti dentro questi strumenti è che la qualità di una harness non si misura dalla potenza del modello che incapsula, ma dalla precisione con cui ha disegnato quel confine. Un setup ben fatto è quasi invisibile quando lavori: le cose giuste accadono da sole, le cose pericolose non possono accadere, il contesto giusto compare quando serve, e tu ti concentri sul problema reale. È ingegneria, non magia, ed è replicabile da chiunque sia disposto a trattare l'agente per quello che è: un nucleo potente e imprevedibile che merita uno scaffolding all'altezza. Sul flusso di lavoro completo che ne risulta per uno sviluppatore senior ho scritto in Claude Code in produzione. Se vuoi impostare la tua organizzazione perché usi gli agenti di coding in modo produttivo e sicuro insieme, puoi usare il modulo di preventivo gratuito: sette domande, due minuti, e ti dico se il tuo caso rientra nel mio perimetro o se ti conviene un'altra figura.

Ultima modifica: