
Tools, state, memory, handoff, and guardrail
Tools, state, memory, handoff, and guardrails on GinnyTech: define which tools an agent can use and which actions require review with controls, ownership, and revisable outputs.
What you will learn
- Design AI workflows for data with controls, owners, and reviewable outputs
- Apply AI, AutoML or agentic AI to business analytics cases without losing rigor
- Recognize risks of leakage, drift, cost, privacy, and ungoverned automation
Tool, stato, memoria, handoff e guardrail
Dare a un agente il potere di interrogare un warehouse, lanciare una pipeline o proporre un modello sembra un salto di produttività, finché non arriva la domanda che blocca la review: come sei arrivato a questo numero, con quali permessi e chi lo ha approvato. Senza una risposta tracciabile, la velocità dell’agente diventa un passivo. Questa lezione, che appartiene al binario sistemi-llm, tratta i cinque meccanismi che separano un prototipo convincente da un sistema dati governato: i tool che definiscono cosa l’agente può toccare, lo stato che rende il lavoro ripristinabile, la memoria che evita di riscoprire ogni volta le stesse definizioni, l’handoff che trasferisce contesto senza perderlo, e i guardrail che bloccano le azioni pericolose prima che facciano danni.
Il filo conduttore è semplice: ogni azione autonoma deve lasciare una traccia che un revisore umano può leggere, contestare e riprodurre. Se un passaggio dipende da una conversazione non registrata, da un permesso implicito o da una soglia decisa al volo dal modello, il workflow non è pronto per dati reali, budget reali o decisioni che toccano clienti e compliance.
Il caso che useremo come sfondo è concreto. Un team segue ricavi e attivazioni su un dataset eventi con decine di milioni di righe, una pipeline dbt che gira di notte e un modello di forecast che alimenta il piano trimestrale. L’agente aiuta a esplorare cali, proporre query, profilare tabelle e preparare memo, ma non esegue query costose, non riscrive modelli e non tocca dati con identificativi personali senza approvazione. La differenza tra le due categorie di azioni è scritta in un file di configurazione versionato, non nella cortesia del prompt.
Perché un agente dati ha bisogno di confini prima che di strumenti
Il collo di bottiglia del lavoro dati non è scrivere la query, è decidere quale domanda merita risposta, quali tabelle sono affidabili, quale metrica sposta la decisione e quale rischio resta dopo la raccomandazione. Un agente senza confini accelera la parte sbagliata: produce SQL plausibile su definizioni fragili, spiega un calo con la stagionalità senza averla misurata, propone un segmento che non regge a un controllo di numerosità. Il risultato sembra lavoro fatto e invece sposta il costo sulla review, che deve rifare da zero ciò che l’agente ha saltato.
Conviene ragionare su quattro livelli prima di aprire qualsiasi SDK. Il compito dice quale fetta di lavoro viene accelerata: bozza di query, profilo di una tabella, checklist di qualità, prima stesura di un memo. Il contesto raccoglie ciò che rende l’output utilizzabile: schema, metrica con la sua definizione, periodo, granularità, segmento, policy di accesso. Il controllo stabilisce come scoprire che l’output è sbagliato: test di granularità, confronto con una baseline, verifica di leakage, review dell’owner. La decisione chiude il cerchio: cosa succede se il controllo regge, dal fix di una pipeline al lancio di un esperimento.
| Level | Domanda da chiudere | Example in data work |
|---|---|---|
| Task | Quale parte accelero? | Bozza SQL, profilo dati, checklist AutoML, memo |
| Context | Con quali input? | Schema, metric, period, segment, policy |
| Control | Come scopro l’errore? | Baseline, leakage check, review dell’owner |
| Decision | Cosa cambia se regge? | Fix pipeline, experiment, deploy, recommendation |
La disciplina sta nel chiudere questi quattro livelli per iscritto prima di eseguire. Tre righe bastano: la decisione concreta da migliorare, il dato o controllo che può sostenerla, il rischio che fa fermare tutto e chiede review umana. Se manca una riga, l’agente resta un supporto esplorativo, non una parte stabile del processo.
I tool come contratti, non come plugin
Un tool è un contratto firmato tra l’agente e il resto dell’infrastruttura: nome, input tipizzati, permessi, costo atteso, effetti collaterali, formato di output. Trattarlo come un plugin da attaccare al volo è il modo più rapido per ritrovarsi con un agente che lancia una scansione full-table da 400 euro o sovrascrive una tabella di metriche. La progettazione seria elenca pochi tool, ognuno con un solo effetto e un solo owner.
Una tassonomia pratica distingue lettura, scrittura reversibile e scrittura irreversibile. In lettura finiscono profilazione tabelle, ricerca nel catalogo, esecuzione di query con limite e dry-run di stima costi. Nella scrittura reversibile stanno la creazione di viste temporanee, l’apertura di branch dbt, la scrittura di bozze di memo. Nell’irreversibile tutto ciò che muove soldi, dati o produzione: deploy di modelli, merge su main, invio di comunicazioni, cancellazioni, accessi a colonne con dati personali. Solo la prima categoria gira senza approvazione; le altre due chiedono conferme diverse, e l’ultima richiede sempre un umano nominato.
# Registro dei tool: ogni voce dichiara permessi, costo e approvazione.
# Commenti in italiano: l'owner legge questo file in review.
TOOLS = [
# Lettura: sicura, nessun effetto collaterale, via libera.
{"nome": "catalog_search", "effetto": "lettura",
"permessi": ["metadata:read"], "serve_approvazione": False},
# Lettura con costo: stima prima, esegue solo sotto soglia.
{"nome": "warehouse_query", "effetto": "lettura",
"permessi": ["warehouse:query"], "soglia_scan_gb": 50,
"serve_approvazione": "sopra_soglia"},
# Scrittura reversibile: branch isolato, mai main.
{"nome": "dbt_branch_open", "effetto": "reversibile",
"permessi": ["repo:branch"], "serve_approvazione": False},
# Irreversibile: deploy e merge chiedono sempre un umano.
{"nome": "dbt_merge_main", "effetto": "irreversibile",
"permessi": ["repo:merge"], "serve_approvazione": True},
]
Il dettaglio che evita incidenti è la stima del costo prima dell’esecuzione. Prima di lanciare una query su una tabella partizionata per giorno, il tool esegue un dry-run, confronta i gigabyte stimati con la soglia e, se la supera, restituisce la stima invece del risultato e chiede all’agente di restringere periodo o colonne. Lo stesso vale per chiamate a modelli esterni: ogni tool dichiara un budget in token e si ferma quando lo esaurisce. Il trade-off è esplicito: qualche attrito in più per le azioni legittime, in cambio di un tetto certo sui danni delle azioni sbagliate.
Lo stato come filo del discorso che si può riavvolgere
Un agente che lavora sui dati attraversa una sequenza lunga: chiarisce la domanda, ispeziona il catalogo, propone query, esegue controlli, sintetizza. Se lo stato vive solo nella finestra di contesto del modello, basta un riavvio o una troncatura per perdere la definizione di conversione concordata al passo due e ritrovarsi con un memo che mescola due metriche diverse. Lo stato serve a rendere ogni passo ripristinabile e ispezionabile da fuori.
Il modello più robusto è una macchina a stati esplicita con record immutabili: ogni transizione scrive un evento con input, output, tool chiamato, timestamp e hash degli artefatti. Niente sovrascritture silenziose. Se l’agente corregge una query, la versione precedente resta nel log e la nuova punta alla precedente. Così il revisore ricostruisce il percorso, il sistema riparte dall’ultimo checkpoint dopo un errore, e due esecuzioni con gli stessi input producono lo stesso percorso o una divergenza spiegabile.
# Evento di stato: append-only, mai aggiornato sul posto.
# Ogni record basta da solo a capire cosa è successo e perché.
evento = {
"run_id": "rev-2026-08-w33", # identificativo dell'esecuzione
"passo": 4, # posizione nella sequenza
"stato": "query_verificata", # stato corrente della macchina
"input_hash": "sha:9f2c...", # hash degli input per riproducibilità
"tool": "warehouse_query", # quale contratto è stato invocato
"output_uri": "s3://run/rev-2026-08-w33/passo-04.parquet",
"padre": "evt-0003", # da quale evento deriva
}
Nella pratica conviene separare tre tipi di stato. Lo stato di lavoro contiene bozze, query candidate e risultati intermedi: si butta senza rimpianti. Lo stato decisionale contiene definizioni approvate, soglie e segmenti concordati: cambia solo con una transizione firmata. Lo stato di audit contiene il log completo: non cambia mai. Mescolare i tre piani in un unico blob JSON è l’errore classico, perché una correzione di bozza rischia di alterare retroattivamente la definizione su cui si basava la decisione. Il costo di questa separazione è qualche scrittura in più su object storage o database; il beneficio è poter rispondere in review a cosa sapevate quando avete deciso, senza ricostruzioni creative.
La memoria senza autoinganni
La memoria di un agente dati non è ricordare la conversazione, è non riscoprire ogni volta che la colonna revenue è in centesimi, che un canale è stato rimappato a marzo, che la retention si calcola sulla coorte di attivazione e non sugli utenti attivi del mese. Queste informazioni vivono in tre memorie diverse con garanzie diverse: la memoria di lavoro dentro il singolo run, la memoria episodica tra run con gli esiti passati, e la memoria semantica con le definizioni stabili versionate.
La memoria semantica merita il trattamento più severo perché è quella che avvelena tutto se sbaglia. Ogni definizione è un record con nome, formula SQL canonica, owner, versione e data di validità. L’agente non cita definizioni a memoria: le risolve dal catalogo e ne riporta versione e hash nel memo. Quando la definizione cambia, i memo vecchi restano legati alla versione vecchia e restano interpretabili. Un esempio tipico è il tasso di attivazione: al numeratore gli utenti con almeno un evento chiave entro sette giorni dall’iscrizione, al denominatore gli iscritti della stessa coorte, mai gli attivi del periodo. Scriverlo una volta nel catalogo evita dieci discussioni e un errore che sposta il KPI di tre punti percentuali.
La memoria episodica registra cosa è stato tentato e com’è andata: quel segmento sotto le 200 unità che produceva intervalli inutili, quella finestra di tre giorni troppo corta per la stagionalità settimanale, quel join che esplodeva le righe per una chiave duplicata. Ogni episodio riporta contesto, azione, esito e lezione in una riga. Il trade-off è noto: una memoria episodica troppo generosa spinge l’agente a riusare soluzioni vecchie su problemi nuovi. La contromisura è una politica di decadimento con punteggio di rilevanza e una regola semplice: sopra una certa età o sotto una certa similarità di contesto, l’episodio è solo un suggerimento citato, mai un default applicato.
Il passaggio di consegne che non perde contesto
A un certo punto l’agente deve passare il lavoro: a un altro agente specializzato, a un revisore umano, a un sistema a valle. È il momento in cui si perdono più informazioni, perché ciò che era ovvio nel run, quale baseline è stata usata, quali segmenti sono stati scartati per bassa numerosità, quale soglia è ancora da approvare, resta implicito. Un handoff serio è un pacchetto chiuso con mittente, destinatario, stato decisionale, artefatti con hash, controlli eseguiti, questioni aperte e criteri di accettazione.
Nel passaggio tra agenti, la regola d’oro è trasferire vincoli, non conclusioni. L’agente di esplorazione non dice che il calo è dovuto al tracking, dice: ho osservato un calo del 12 per cento sulle attivazioni dal 4 agosto sulla coorte Italia, ho escluso la stagionalità confrontando con le stesse settimane del trimestre precedente, resta aperta la verifica sul rilascio del tag manager del 2 agosto, artefatti ai percorsi indicati. L’agente a valle riparte dai dati, non dall’opinione. Nel passaggio verso l’umano, il pacchetto aggiunge ciò che serve per decidere in cinque minuti: decisione richiesta, opzioni con trade-off, rischio residuo e cosa farebbe cambiare idea.
-- Controllo di coerenza allegato all'handoff: la somma dei segmenti
-- deve tornare al totale, altrimenti il passaggio viene rifiutato.
-- Salva da join che duplicano righe o filtri applicati a metà.
SELECT
SUM(segment_users) AS somma_segmenti, -- totale ricostruito dai segmenti
MAX(total_users) AS totale_dichiarato, -- totale della query principale
SUM(segment_users) - MAX(total_users) AS scarto
FROM handoff_check; -- atteso: scarto = 0, altrimenti handoff bloccato
Il controllo di accettazione dell’handoff è automatico: schema valido, hash degli artefatti verificati, controlli minimi presenti, questioni aperte esplicite. Se manca un pezzo, il passaggio viene rifiutato con un motivo leggibile, non con un errore generico. Sembra burocrazia e invece è ciò che permette a tre agenti e due umani di lavorare sullo stesso calo senza pestarsi i piedi: ognuno sa cosa ha ricevuto, cosa deve produrre e quando può rimandare indietro il pacchetto.
I guardrail che bloccano davvero
I guardrail utili non sono frasi nel prompt ma controlli eseguiti dal sistema, fuori dalla portata del modello. Il modello può chiedere, il sistema decide. Questa separazione è l’unica difesa contro prompt injection, istruzioni ambigue e semplici allucinazioni operative: anche se l’agente si convince di dover cancellare una tabella, la chiamata non parte perché il suo ruolo non ha il permesso e il tool rifiuta con un errore strutturato.
Quattro famiglie coprono quasi tutto. I guardrail di permesso rispondono a chi può fare cosa: ruoli minimi, colonne con dati personali accessibili solo con approvazione e mascheramento, ambienti di produzione separati da quelli di sviluppo. I guardrail di costo rispondono a quanto si può spendere senza chiedere: soglie di scansione in gigabyte, budget in token, numero massimo di esecuzioni per run. I guardrail di qualità rispondono a cosa conta come prova: numerosità minima per segmento, intervalli obbligatori sopra una certa visibilità, divieto di confrontare coorti con definizioni diverse. I guardrail di stop rispondono a quando ci si ferma: deriva dei dati oltre soglia, leakage rilevato, disaccordo tra due controlli indipendenti.
| Famiglia | Controllo concreto | Chi lo esegue |
|---|---|---|
| Permessi | Colonne PII solo con approvazione e mascheramento | Sistema, prima del tool |
| Cost | Dry-run e blocco sopra 50 GB scansionati | Tool wrapper |
| Qualità | Segmenti sotto 200 unità marcati come non significativi | Validatore di output |
| Stop | Leakage train-test sopra soglia ferma il run AutoML | Monitor del run |
Un esempio numerico chiarisce il guardrail di qualità. Su un segmento da 150 utenti con 18 conversioni, il tasso osservato del 12 per cento ha un margine di diversi punti e un intervallo ampio quasi 11 punti: presentarlo come evidenza senza intervallo è fuorviante, e il validatore lo marca come indicativo. Il punto non è la sofisticazione statistica ma l’automatismo: nessun memo esce con numeri fragili spacciati per solidi.
Osservabilità e audit: ricostruire ogni decisione
Un workflow agentico senza osservabilità è una scatola nera con un logo sopra. L’osservabilità significa poter rispondere dopo settimane a tre domande: cosa ha fatto l’agente, con quali dati e con quali permessi. Servono tre strati: trace delle chiamate ai tool con input, output e latenza; lineage dei dati dagli artefatti alle tabelle sorgente con versione delle definizioni; log delle approvazioni con chi ha approvato cosa e quando. Ognuno ha un lettore diverso: la trace serve al debug, il lineage alla review metodologica, il log delle approvazioni alla responsabilità.
Il lineage merita attenzione perché è dove i workflow dati falliscono in silenzio. Ogni artefatto prodotto dall’agente punta alle tabelle sorgente con snapshot o timestamp, alla query esatta con hash, alla versione della definizione di metrica e ai controlli eseguiti con esito. Quando la tabella a monte viene ricaricata con una correzione, il sistema sa quali memo e quali modelli sono da rivedere. Senza questo legame, una correzione di pochi punti percentuali nel backfill invalida silenziosamente una raccomandazione già presentata allo stakeholder.
# Record di lineage allegato a ogni artefatto dell'agente.
# Permette di invalidare i memo quando la sorgente cambia.
lineage = {
"artefatto": "memo-calo-attivazioni-w33.parquet", # cosa ho prodotto
"sorgenti": ["events@2026-08-15", "users@2026-08-15"], # snapshot usati
"query_hash": "sha:41ab...", # query esatta, non "una query simile"
"metrica": "attivazione_7d@v3", # definizione versionata dal catalogo
"controlli": ["coerenza_segmenti:ok", "numerosita:ok", "leakage:n/a"],
}
La metrica di salute del sistema non è quanti run vanno a buon fine, ma quanti falliscono per il motivo giusto: bloccati da un guardrail con un messaggio leggibile, rifiutati in handoff per un controllo mancante, fermati per deriva dei dati. Un tasso di blocchi a zero non indica perfezione, indica guardrail decorativi. Al contrario, una quota stabile di run fermati con motivazione tracciata indica che i controlli lavorano e che gli incidenti restano confinati nei log invece di finire nelle dashboard.
Mettere tutto insieme in una pipeline governata
Il quadro si chiude con un esempio che attraversa tutti i meccanismi. Il trigger è un calo delle attivazioni del 12 per cento sulla coorte Italia nella settimana 33, rilevato dal monitoraggio. L’agente apre un run con stato iniziale che fissa decisione, periodo, coorte e soglie. Risolve la definizione di attivazione dal catalogo alla versione 3, profila le tabelle del periodo, propone due query candidate ed esegue quella sotto soglia di costo dopo il dry-run. I controlli di coerenza dei segmenti e di numerosità passano; il confronto con la baseline stagionale conferma che il calo è reale e non un effetto calendario.
A questo punto l’agente prepara l’handoff al revisore: memo con evidenza, ipotesi e raccomandazione tenute in sezioni separate, lineage completo, questione aperta sul rilascio del tag manager del 2 agosto. Il guardrail di qualità marca come indicativo il segmento iOS sotto le 200 unità con il suo intervallo. Il revisore approva la raccomandazione di rollback parziale del tag e chiede un controllo aggiuntivo sul consenso cookie. L’approvazione viene registrata con nome, timestamp e ambito. Due settimane dopo, quando il backfill corregge i dati di un giorno, il lineage segnala il memo come da rivedere e il sistema aggiorna i numeri senza riscrivere la storia: la versione originale resta nell’audit con la sua motivazione.
Funziona perché ogni meccanismo copre il punto debole degli altri: i tool limitano ciò che si può fare, lo stato rende il percorso riproducibile, la memoria evita errori già visti, l’handoff trasferisce il contesto senza comprimerlo in un’opinione, i guardrail bloccano ciò che il modello non può valutare da solo. Il costo è reale, più scritture, più approvazioni, più attrito sui casi semplici, ma è il prezzo che separa un esperimento da un sistema su cui un team può firmare. Quando un output non si può ricostruire, revisionare o fermare, non è automazione: è velocità senza governo, e sui dati la velocità senza governo si paga sempre con gli interessi.
Verdetto: dai all’agente pochi tool in lettura con dry-run obbligatorio, stato append-only e memoria versionata dal catalogo, e blocca tutto il resto dietro handoff validati e guardrail di sistema con owner nominato.
I cinque meccanismi in una frase
I cinque meccanismi di governo decidono cosa un agente può toccare in autonomia e cosa richiede review umana con traccia revisionabile.
La sequenza operativa in cinque passi
- Registra ogni tool come un contratto: permessi, tetto di costo e livello di approvazione dichiarati in un file versionato.
- Apri il run con uno stato iniziale che fissa decisione, periodo, coorte e soglie.
- Risolvi ogni metrica dal catalogo versionato e registra versione e hash nel memo.
- Trasferisci il lavoro con handoff validati che portano vincoli, artefatti e controlli.
- Blocca con guardrail di sistema le azioni fuori permesso, fuori budget o sotto numerosità.
Un incidente reale che insegna il rollout graduale
Il 19 luglio 2024 un aggiornamento difettoso di CrowdStrike ha mandato in boot loop circa 8,5 milioni di dispositivi Windows nel mondo. Compagnie aeree, ospedali e banche hanno fermato le operazioni per ore mentre i team ripristinavano a mano milioni di macchine. La causa era un controllo mancato a monte: un contenuto distribuito a scala globale senza rollout graduale né gate di arresto automatico. La lezione per i workflow agentici è identica: nessuna azione irreversibile parte senza permessi minimi, validazione e owner che firma.
Domande per chiudere la lezione
- Quale tool gira libero e quale richiede sempre un umano nominato?
- Cosa registra lo stato per rendere un run ripristinabile dopo un errore?
- Quando un handoff va rifiutato invece di passare al ruolo successivo?
- Quale guardrail ferma una query costosa prima dell’esecuzione?
Bloccato su questo argomento o vuoi applicarlo al tuo caso? Prenota una call di 15 minuti con un analista esperto.
Related Path
Lessons to read together
Questi collegamenti portano la lezione dentro il resto del corso: basi da riprendere, passaggi successivi e connessioni tematiche tra moduli.