Valutazione degli agenti AI: come costruire gli evals e misurare l'affidabilità, non l'impressione
La valutazione degli agenti AI è l'esecuzione periodica di un insieme fisso di compiti reali con verifica automatica del risultato e calcolo delle metriche, invece dell'impressione di due sessioni riuscite. L'essenziale è misurare non solo pass@k (almeno uno dei k tentativi riesce), ma anche pass^k (riescono tutti i k tentativi), perché è la stabilità a determinare se si può affidare un lavoro all'agente senza supervisione.
Perché valutare gli agenti AI, se si vede già che funzionano
Proprio perché si vede poco. Un agente per una settimana non si è mai bloccato dopo la modifica del prompt: è stata una riparazione o solo una settimana di compiti semplici? Un ingegnere è convinto che il nuovo template abbia cambiato tutto, un altro ha letto lo stesso log e non ha notato differenze. Hanno ragione entrambi, nella misura in cui non hanno calcolato nulla.
La valutazione degli agenti AI (evals) sostituisce l'impressione con un numero. Si prende un insieme fisso di compiti, si esegue l'agente, si verifica automaticamente il risultato e si confrontano le metriche prima e dopo una modifica. Così la discussione «è migliorato?» si risolve con una tabella, non con l'autorità di qualcuno.
Senza evals ogni modifica dell'harness — prompt, AGENTS.md, set di strumenti, modello — è una scommessa alla cieca. Con gli evals diventa un esperimento con un risultato misurabile.
Perché l'impressione inganna
L'impressione del lavoro dell'agente è affetta da tre errori sistematici, e tutti spingono verso una falsa sicurezza.
- Errore del sopravvissuto. Le esecuzioni riuscite si ricordano e si mostrano ai colleghi, quelle fallite vengono rilanciate e dimenticate. Un'affidabilità calcolata sulle sole esecuzioni riuscite non dice dove l'agente si rompe davvero.
- Campione piccolo. Tre compiti riusciti di fila sono un evento normale anche per un agente che riesce nella metà dei casi. La probabilità è 0,5³ = 12,5%, cioè circa una serie su otto.
- Tono sicuro. L'agente scrive «fatto, tutti i test passano» con la stessa sicurezza sia quando è vero sia quando non lo è. La fiducia del modello non è calibrata: il tono della risposta non è un segnale di correttezza.
Da qui la regola: tutto ciò che non è registrato e ricalcolato è considerato non misurato.
pass@k e pass^k: due metriche che si confondono
L'agente non è deterministico: lo stesso compito, ripetuto, può riuscire o fallire. Per questo lo stesso compito si esegue più volte e si calcola una di due metriche.
pass@k — almeno un tentativo su k riesce
La metrica viene dalla valutazione della generazione di codice. Risponde alla domanda «il sistema è in grado, in linea di principio, di risolvere il compito se gli si danno più tentativi». È una metrica onesta per lo scenario in cui una persona sceglie la migliore di più varianti, o in cui esiste una verifica automatica affidabile che scarta quelle sbagliate.
pass^k — tutti e k i tentativi riescono
Questa metrica risponde a un'altra domanda: «quanto stabilmente l'agente risolve il compito». Descrive il lavoro senza supervisione, quando l'agente viene lanciato molte volte e ogni fallimento costa denaro o tempo.
La differenza tra le due è enorme. Supponiamo che l'agente risolva il compito con probabilità del 70% a tentativo e che i tentativi siano indipendenti:
| k | pass@k = 1 − 0,3^k | pass^k = 0,7^k |
|---|---|---|
| 1 | 70% | 70% |
| 3 | 97,3% | 34,3% |
| 5 | 99,8% | 16,8% |
| 10 | ~100% | 2,8% |
Con pass@5 l'agente sembra quasi perfetto, con pass^5 è inaffidabile. Entrambi i numeri sono corretti, descrivono solo cose diverse. Se intendete lasciare l'agente a lavorare in autonomia, guardate pass^k: è più vicino a ciò che vedrete nel lavoro reale.
Come calcolarle in pratica
Eseguite ogni compito n volte (per esempio 5) e registrate il numero di successi c. Per pass^k, la stima approssimata è la frazione di esecuzioni in cui tutti i k tentativi di fila riescono; più semplicemente, stimate la probabilità di successo p = c / n e portatela alla potenza k. Per l'insieme dei compiti, fate la media.
import json
from statistics import mean
# results.jsonl: {"task": "add-pagination", "runs": [true, true, false, true, true]}
rows = [json.loads(line) for line in open("results.jsonl")]
def pass_at_k(runs, k):
p = sum(runs) / len(runs)
return 1 - (1 - p) ** k
def pass_pow_k(runs, k):
p = sum(runs) / len(runs)
return p ** k
for k in (1, 3, 5):
print(k,
round(mean(pass_at_k(r["runs"], k) for r in rows), 3),
round(mean(pass_pow_k(r["runs"], k) for r in rows), 3))
La stima tramite p alla potenza k è grossolana con n piccolo, ma per confrontare tra loro versioni dell'harness di solito basta. È più importante che n e l'insieme dei compiti non cambino tra un confronto e l'altro.
Come costruire l'insieme di compiti per gli evals
L'insieme di compiti è il bene principale. Una buona metrica su compiti scadenti misura la cosa sbagliata.
Prendete i compiti dalla vostra realtà
I benchmark pubblici come SWE-bench sono utili per confrontare i modelli, ma i loro compiti sono selezionati: descrizione chiara, test già pronti. Nel vostro repository i requisiti sono vaghi e i test in alcuni punti mancano, quindi il numero del benchmark è quasi sempre più alto di quello che l'agente mostrerà da voi. La fonte migliore sono i ticket chiusi e i fallimenti reali dell'agente dal registro.
Composizione dell'insieme
- 20–50 compiti per iniziare. Meno, e il rumore cancella la differenza tra le versioni. Di più, e l'esecuzione diventa costosa e smette di essere lanciata.
- Tipi diversi: nuova funzione, correzione di bug, refactoring, compito su un modulo altrui, compito con una trappola (dove la risposta giusta è «così non si può fare» o «serve un chiarimento»).
- Ogni compito fallito nel lavoro diventa un test. Così l'insieme cresce insieme alla comprensione di dove l'agente è debole, e le regressioni non tornano inosservate.
- Stato iniziale fisso: un commit preciso, dipendenze bloccate, ambiente identico. Altrimenti si misura la deriva dell'ambiente, non l'agente.
Formato del compito
Ogni compito è una descrizione, uno stato iniziale e un criterio di successo verificabile senza persone.
id: add-pagination
repo_ref: 3f2c1ab
prompt: |
Aggiungi la paginazione a GET /payments: parametri limit (predefinito 20, massimo 100)
e cursor. La risposta contiene next_cursor.
check:
- pytest tests/test_payments_pagination.py
- mypy app/
limits:
max_changed_files: 6
Notate: il criterio di successo è la Definition of Done, scritta con dei comandi. Se non riuscite a scrivere il criterio di un compito, è il segnale che anche per l'agente il compito è formulato in modo ambiguo.
Controlli automatici o giudice LLM
Il risultato si può verificare con codice oppure con un altro modello. Ciascun metodo ha il proprio ambito.
| Controlli automatici (codice) | Giudice LLM | |
|---|---|---|
| Che cosa verificano | Test, tipi, linter, E2E, dimensione del diff, file vietati | Aderenza ai requisiti, leggibilità, stile, qualità della spiegazione |
| Determinismo | Completo | No: il giudizio varia da un'esecuzione all'altra |
| Costo | Quasi nullo | Un'ulteriore chiamata al modello per ogni compito |
| Rischio principale | Non controlla tutto: i test sono verdi ma la funzione è quella sbagliata | Il giudice approva una soluzione sicura di sé ma sbagliata |
Regola: prima il codice, il giudice sopra
Tutto ciò che si può verificare in modo deterministico, verificatelo in modo deterministico. Il giudice LLM va aggiunto solo per le proprietà che il codice non sa esprimere, e mai al posto dei test.
Come rendere utile il giudice LLM
- Contesto diverso dal generatore. Il giudice non deve vedere il ragionamento dell'agente, solo il compito, i criteri e il diff finale. Altrimenti ripete gli stessi errori: è la N-versione, due sguardi indipendenti invece di uno.
- Una rubrica invece di «valuta da uno a dieci». Domande precise con risposta sì/no: «c'è la validazione di limit > 100?», «sono stati modificati file fuori da app/payments?».
- Calibrazione su un'annotazione manuale. Annotate a mano 20–30 risultati e confrontateli con i verdetti del giudice. Se la coincidenza è bassa, si cambia la rubrica, non si dà più fiducia al giudice.
- Asimmetria degli errori. Un falso «fatto» costa più di un falso «non fatto»: il primo finisce in produzione, il secondo costa un riavvio. Configurate il giudice in modo che, nel dubbio, rifiuti.
Quali metriche calcolare oltre alla quota di successi
La quota dei compiti risolti è solo la punta. Per capire dove intervenire servono metriche di affidabilità dall'ingegneria classica.
- MTBF — quanti passi o compiti l'agente completa prima di bloccarsi. Mostra quanto raramente si rompe.
- MTTR — quanto tempo serve per tornare allo stato di lavoro dopo un guasto. Ridurlo costa quasi sempre meno che aumentare l'MTBF: un buon file di avanzamento e un ambiente riproducibile accorciano il ripristino di molte volte.
- Raggio di danno — quanto codice rovina un singolo passo sbagliato. Si limita con un tetto sul diff e con l'isolamento della copia di lavoro.
- Quota di falsi «fatto» — compiti in cui l'agente ha dichiarato il successo e la verifica è fallita. È la metrica più pericolosa: mostra se si può fidarsi del rapporto dell'agente.
- Costo e tempo — token e minuti per compito. Un harness che alza il successo del 5% ma raddoppia il costo non è sempre un guadagno.
Registro dei fallimenti: evals dal lavoro quotidiano
Non ogni team è pronto a costruire subito un sistema di esecuzione. La versione minima della valutazione è un registro dei fallimenti a tre colonne.
| Compito | Risultato | Livello |
|-------------------------|------------------------------------|---------------|
| paginazione /payments | «fatto», 2 test rossi | verifica |
| correzione timeout webhook | 30 min per pip install | ambiente |
| refactoring refunds | sintassi ORM vecchia | contesto |
Il livello è uno dei cinque punti in cui l'agente può rompersi: specifica del compito, contesto, ambiente di esecuzione, feedback della verifica, gestione dello stato. Dopo venti voci si vede il vero collo di bottiglia, e quasi mai è dove pensavate. Ogni riga del registro è un candidato per l'insieme di compiti degli evals.
Perché un modello potente non basta
La prima reazione ai fallimenti dell'agente è prendere un modello più costoso. A volte aiuta, ma più spesso il divario tra benchmark e realtà lo colma non il modello, bensì l'ambiente che lo circonda.
Se l'agente impiega mezz'ora a far partire l'ambiente, il problema è di livello ambiente, e il modello di punta impiegherà ugualmente mezz'ora. Se dichiara «fatto» con i test rossi, è un problema di livello verifica: non ha un comando che gli dica la verità. Se scrive codice nello stile sbagliato, non gli sono state date le convenzioni del progetto. Nessuno di questi problemi riguarda l'intelligenza del modello.
Gli evals permettono di verificarlo onestamente. Eseguite l'insieme con il modello attuale e con un modello più costoso, poi con il modello attuale e con un AGENTS.md che aggiunge i comandi di verifica. Spesso la seconda modifica dà un guadagno maggiore della prima, a costo zero. Ma non credeteci sulla parola: per confronti come questo l'insieme serve proprio a questo.
Piano in cinque passi: valutare gli agenti in una settimana
- Giorno 1. Aprite un registro dei fallimenti e annotate ogni errore dell'agente indicando il livello.
- Giorno 2. Selezionate 20 compiti dai ticket chiusi e dal registro. Per ciascuno fissate il commit e scrivete il criterio di successo con dei comandi.
- Giorno 3. Scrivete il runner: copia di lavoro pulita, avvio dell'agente con il prompt del compito, esecuzione delle verifiche, scrittura del risultato in JSONL.
- Giorno 4. Eseguite ogni compito 3–5 volte. Calcolate pass@1, pass^3, la quota di falsi «fatto», il costo medio.
- Giorno 5. Cambiate una sola cosa nell'harness ed eseguite di nuovo. Confrontate solo con lo stesso insieme e lo stesso numero di ripetizioni.
Cambiate una variabile alla volta. Se in un unico esperimento cambiate modello, prompt e strumenti, non saprete che cosa ha funzionato.
Errori tipici nella valutazione degli agenti
- Una sola esecuzione per compito. La non deterministicità dell'agente rende il risultato una lotteria. Minimo tre ripetizioni.
- L'insieme cambia tra un confronto e l'altro. Aggiungete nuovi compiti e cambiate il prompt nello stesso momento: i numeri non sono confrontabili.
- L'agente vede i test di verifica. Se i test sono nel repository, l'agente può adattare il codice ad essi o semplicemente modificarli. Tenete le verifiche nascoste fuori dalla copia di lavoro e controllate che l'agente non abbia toccato i file di test.
- Il rapporto dell'agente al posto della verifica. «Tutti i test sono passati» nella risposta del modello non è un risultato. Il risultato è il codice di ritorno del comando lanciato dal runner.
- Solo pass@k. Un numero bello da presentare e una previsione povera per il lavoro autonomo.
In breve
La valutazione degli agenti AI è un insieme fisso di compiti reali, verifiche automatiche e metriche ricalcolate dopo ogni modifica dell'harness. pass@k dice di che cosa l'agente è capace, pass^k dice se può essere lasciato senza supervisione. I controlli automatici danno la verità, il giudice LLM con una rubrica e un contesto separato li integra dove il codice non arriva. E il registro dei fallimenti per livelli indica che cosa correggere per primo: quasi sempre non è il modello. Le metriche di affidabilità e il ciclo diagnostico sono illustrati in pratica nel corso sull'harness engineering.
Domande frequenti
Quanti compiti servono per gli evals di un agente?
Per iniziare bastano 20–50 compiti reali con un criterio di successo automatico e 3–5 ripetizioni di ciascuno. Un insieme più piccolo non distingue un miglioramento dal rumore, uno più grande diventa costoso e smette di essere eseguito.
Si può valutare un agente solo con i benchmark pubblici?
No. I benchmark pubblici confrontano i modelli su compiti selezionati con test già pronti, mentre nel vostro repository requisiti e test sono diversi. Per le decisioni sul vostro harness serve un insieme di compiti proprio.
In che cosa pass@1 differisce da pass^1?
In nulla: con un solo tentativo le due metriche coincidono con la quota di esecuzioni riuscite. Iniziano a differire con k maggiore di uno.
Il giudice LLM può essere lo stesso modello dell'agente?
Sì, se ha un contesto separato: vede solo il compito, la rubrica e il diff finale, senza il ragionamento dell'agente. I suoi verdetti vanno comunque confrontati con un'annotazione manuale.
Con che frequenza eseguire gli evals?
Dopo ogni modifica rilevante dell'harness: prompt, file di istruzioni, set di strumenti, modello. È utile anche eseguire l'insieme periodicamente, per notare la deriva dell'ambiente e delle dipendenze.
Questo argomento è trattato in modo approfondito, con pratica, nel corso «Harness Engineering: инженерия надёжности AI-агентов».
- Метрики надёжности AI-агента: MTBF, MTTR, радиус поражения и закон Литтла
- Почему AI-агент ломается в проде: пять слоёв отказа и диагностическая петля