# Valutare un agente con un benchmark: harness, pass^k e varianza

Un benchmark per agenti è task fissi, ambiente pulito, grader automatico e k ripetizioni. Senza il quarto numero il risultato è un aneddoto.

> Pagina: https://ui.eneawork.it/blog/agent-eval-benchmark
> Markdown: https://ui.eneawork.it/blog/agent-eval-benchmark.md

*2026-11-01*

Un benchmark per agenti è fatto di quattro parti: task fissi, un ambiente che si resetta, un grader automatico e k ripetizioni per task. Se manca il quarto numero, il risultato è un aneddoto.

L'harness locale backend/llm-bench.js, letto il 1 novembre 2026, esegue 2 task su 6 modelli, cioè 12 esecuzioni per giro: un task JSON con 6 slot attesi e 14 componenti ammessi, e un task di composizione JSX. La temperatura è fissata a 0,1 e le penalità sono costanti: -15 per uno slot mancante, -12 per un componente non ammesso, -10 per un titolo assente, -4 per un tag sbilanciato. Dodici esecuzioni sono uno smoke test, non un benchmark: mancano le ripetizioni e i task sono due. L'endpoint EneUI ha risposto a tools/list con 3.655 byte in 218 ms, misurati il 1 novembre 2026. Il catalogo dietro conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, letti da /api/stats.

## Le quattro parti di un harness

Il grader è la parte che si sbaglia più spesso. Un test che l'agente può modificare non è un grader, è un suggerimento: va eseguito da fuori, su file che l'agente non può toccare. Lo stesso vale per il tempo limite e per il numero massimo di file modificati, che vanno decisi prima e non dopo aver visto il risultato.

## pass@k e pass^k

pass@k risponde a «almeno uno dei k tentativi riesce», ed è la metrica giusta per la capacità: un agente che non ci arriva mai è fuori. pass^k risponde a «tutti i k tentativi riescono», ed è la metrica giusta per l'affidabilità: un agente che riesce una volta su tre non è pronto per un flusso automatico.

node -e "const p=0.8;for(const k of [1,3,5])console.log('pass^'+k,(100*p**k).toFixed(0)+'%')"

Con una probabilità di successo dell'80%, il comando stampa pass^1 80%, pass^3 51% e pass^5 33%. Lo stesso agente sembra ottimo con un tentativo e mediocre con cinque: la differenza non è nel modello, è nella domanda che il benchmark pone.

## La varianza con 20 task

node -e "const n=20,p=0.8,se=Math.sqrt(p*(1-p)/n);console.log((100*p).toFixed(0)+'% +/- '+(196*se).toFixed(0)+' pt')"

Il comando stampa 80% +/- 18 pt: con venti task un 80% misurato vale fra il 62% e il 98%. Due modelli che differiscono di dieci punti su venti task sono indistinguibili. Per scendere a un margine di cinque punti servono centinaia di task, oppure meno task ma con un grader più fine di pass o fail.

## Tre grader, tre verità

Per un agente di codice il primo è obbligatorio, il secondo è utile sui task piccoli, il terzo serve solo dove non esiste un oracolo. Un giudice automatico va validato contro un campione giudicato a mano: se non concorda su venti casi, il numero che produce non è una misura.

## Contaminazione e rumore

Un task pubblico è quasi sempre già visto in addestramento, quindi il punteggio misura la memoria del modello e non la capacità. Anche l'harness introduce rumore: prompt diversi da quelli reali, cache calda al primo giro, tool che rispondono con latenze diverse. La difesa è noiosa: task presi da bug chiusi del tuo repository, ambiente ricreato a ogni giro, stesso prompt per tutti, ripetizioni dichiarate.

## Cosa riportare

## La limitazione

Il nostro harness esegue due task: serve a verificare che un modello produca JSON valido e JSX coerente, non a classificare modelli. Anche un harness grande resta cieco su ciò che non misura: un agente può passare tutti i task e restare inutilizzabile perché lento, caro o insicuro sul disco. Il punteggio è un filtro, la decisione resta umana.

## Dove continuare

La costruzione della fixture e il costo per attività riuscita sono in valutare un modello per il codice, l'ordine dei passi in orchestrare agenti multi-step, i rischi di scrittura su disco in sicurezza di un agente di coding. Il catalogo che alimenta i task è in 111.985 componenti e 1.556 blocchi; un record citabile è agent dock di dqnamo.

## FAQ

### Quanti task servono per un benchmark credibile?

Venti task distinguono solo differenze grandi. Con venti task e un successo dell'80% l'intervallo è di circa 18 punti, quindi due modelli a dieci punti di distanza non sono separabili. Per differenze fini servono centinaia di task o un grader più fine.

### Che differenza c'è fra pass@k e pass^k?

pass@k chiede se almeno un tentativo su k riesce, e misura la capacità. pass^k chiede se tutti i k tentativi riescono, e misura l'affidabilità. Un agente con pass^1 all'80% scende al 51% con pass^3 e al 33% con pass^5.

### Posso usare un LLM come giudice?

Solo dove non esiste un oracolo, e solo dopo averlo validato su un campione giudicato a mano. Un giudice senza accordo misurato premia le risposte lunghe, ignora i dettagli e produce un numero che sembra una misura.

### Come evito la contaminazione?

Usando task che non esistono in pubblico: bug chiusi del tuo repository, con il diff atteso già disponibile. Ruota i task quando il repository cambia forma e non riusare lo stesso set per anni.

### Mi fido dei punteggi dei benchmark pubblici?

Come primo filtro sì, per escludere chi non sa scrivere codice. Non per scegliere fra i primi cinque, perché i task sono noti e il formato del prompt è diverso dal tuo. La fixture decide, il benchmark orienta.
