Un sistema agentico che sintetizza da più fonti produce due cose: una risposta e un debito. Il debito è la domanda «da dove viene questa frase?», e chi progetta il sistema decide se sarà pagata da una struttura dati o da un umano che rilegge tutto. Revisione umana e provenienza sono la stessa decisione vista da due lati, perché l’attenzione umana è il budget più scarso che hai.
L’autonomia si concede, non si presume
Il materiale di Anthropic sui team umano-agente mette la revisione in un ordine preciso: i migliori agenti long-running hanno molti modi di verificare il proprio lavoro prima che un umano lo guardi, e l’autonomia si concede in proporzione all’affidabilità dimostrata, poi si allarga deliberatamente. Le decisioni con compromessi difficili restano con un umano nel loop. Il corollario è meno ovvio: se ogni dubbio dell’agente diventa un’interruzione, hai solo spostato il collo di bottiglia sulla persona.
Dove si aggancia la revisione, nel codice
Nell’Agent SDK il punto di aggancio è la callback canUseTool, che scatta quando Claude vuole usare uno strumento che nessuna regola ha già approvato e quando chiama AskUserQuestion per un chiarimento. Le risposte possibili non sono due ma sei: approvare, approvare modificando l’input, approvare e ricordare, rifiutare, rifiutare suggerendo un’alternativa, o ridirigere via streaming input. Sul rifiuto la documentazione è precisa: «When denying, provide a message explaining why. Claude sees this message and may adjust its approach». Un no è un canale di comunicazione, non un muro.
Tre vincoli che cambiano l’architettura, e che si scoprono tardi se non li leggi prima:
1. "The callback never fires for auto-approved tools."
Un'allow rule o acceptEdits risolve la chiamata PRIMA di canUseTool.
Per logica che vale su OGNI chiamata: hook PreToolUse.
2. "Execution remains paused until your callback returns."
Se l'umano può metterci ore, non tenere il processo vivo:
hook PreToolUse con decisione "defer", e si riprende dalla sessione.
3. AskUserQuestion non è disponibile nei sottoagenti lanciati con
l'Agent tool: la domanda all'umano deve risalire al padre.
Per svegliare la persona giusta senza bloccare nulla c’è l’hook PermissionRequest, pensato per notifiche esterne come Slack, email o push. Il formato della domanda è vincolato: da 1 a 4 domande per chiamata, da 2 a 4 opzioni ciascuna, header di al massimo 12 caratteri. Se serve un modulo vero, servono custom tool.
Il grader dà un verdetto, non una probabilità
Nei Managed Agents la calibrazione ha una forma concreta. Definisci un outcome con una rubrica e «the harness automatically provisions a grader … The grader uses a separate context window to avoid being influenced by the main agent’s implementation choices». Il ciclo termina con satisfied, needs_revision, max_iterations_reached, failed o interrupted; le iterazioni hanno default 3 e massimo 20.
Due avvertenze valgono come principi di calibrazione. La rubrica va scritta a criteri verificabili, «“The CSV contains a price column with numeric values” rather than “The data looks good”», perché «The grader scores each criterion independently, so vague criteria produce noisy evaluations». E il giudizio non è ispezionabile: «The grader’s internal reasoning is opaque: you see that it’s working, not what it’s thinking». Ottieni un verdetto per criterio, non un punteggio di confidenza, e confonderli è l’errore più costoso.
L’unico segnale statistico descritto è il best-of-N: girare lo stesso prompt più volte e confrontare gli output, perché «Inconsistencies across outputs could indicate hallucinations». Rileva disaccordo, e il disaccordo non è una probabilità.
Provenienza: la citazione come struttura dati
Chiedere via prompt «cita le fonti» e attivare la feature Citations non producono la stessa cosa. Con la feature, «citations are guaranteed to contain valid pointers to the provided documents», il campo cited_text non conta nei token di output, e nelle valutazioni di Anthropic la feature «is significantly more likely to cite the most relevant quotes from documents than purely prompt-based approaches».
Per una sintesi multi-fonte servono i blocchi search_result, con tre campi obbligatori: source, title e content. Il source accetta qualunque stringa stabile, anche un identificatore interno come kb://article-1234: la provenienza non richiede una URL pubblica. La granularità però la decidi tu a monte, perché «The text block is the minimal citable unit: Claude cites whole blocks, not substrings within a block».
Quattro vincoli da mettere subito nel design. Le citazioni sui search_result sono disattivate di default. Sono tutto-o-niente: mescolare risultati con impostazioni diverse nella stessa richiesta produce un errore. I blocchi search_result stanno solo nei messaggi utente, tool result inclusi. E non si combinano con gli structured output: abilitare le citazioni e passare output_config.format nella stessa richiesta restituisce un 400, quindi contratto JSON rigido e provenienza sono due passaggi distinti.
Anche il vuoto è provenienza: quando una ricerca non trova nulla, la guida chiede di restituire un blocco di testo che descriva l’esito, non un’eccezione.
Incertezza dichiarata, non stimata
Le tecniche verificate sono poche e concrete: dare a Claude il permesso esplicito di ammettere l’incertezza («Allow Claude to say “I don’t know”»), estrarre citazioni testuali prima di analizzare, restringere la risposta alla sola conoscenza fornita, e far verificare ogni affermazione a posteriori — se non trova una citazione a supporto, «it must retract the claim».
E poi la frase che chiude il dominio, e che è essa stessa la calibrazione più onesta disponibile: «while these techniques significantly reduce hallucinations, they don’t eliminate them entirely. Always validate critical information, especially for high-stakes decisions». Il workflow di revisione umana non è quello che usi quando l’agente sbaglia: è quello che progetti sapendo che qualche volta sbaglierà.