In questo articolo
- 🔍 Cos'è coder_eval e cosa non è
- 📄 Un task è un file YAML, niente di più
- 🎯 skill_triggered: la skill è scattata o no?
- ⚖️ Criteri pesati, non un pass/fail secco
- 🔁 A/B, dataset e gate in continuous integration
- 💡 Perché lo trovo interessante, per chi sviluppa e per una PMI
- ⚠️ Cosa mettere in conto prima di provarlo
- ✅ Da dove partire
🔍 Cos'è coder_eval e cosa non è
coder_eval si autodefinisce «la palestra degli agenti di coding»: un framework riproducibile per valutare, benchmarkare e confrontare in A/B agenti di coding. Oggi supporta Claude Code, OpenAI Codex e Google Antigravity (Gemini), con un plugin SPI per aggiungerne altri. La meccanica è semplice da raccontare: prende un task scritto in YAML, prepara una sandbox, lancia l'agente vero con il suo giro di tool, e poi controlla i file e i comandi che sono usciti da quel giro.
La distinzione che conta è con i benchmark a dataset fisso. SWE-bench o SkillsBench misurano modelli su un insieme canonico di problemi e producono una classifica; coder_eval non ha classifica e non ha dataset proprio, valuta i task che scrivi tu. È anche diverso dagli strumenti che giudicano l'output testuale di un modello: qui non si valuta una stringa, si valuta il risultato di un agente che ha letto, scritto ed eseguito cose in una directory.
repo UiPath/coder_eval cosa valuta e benchmarka agenti di coding e le loro skill agenti claude-code · codex · antigravity (Gemini) · plugin SPI come task YAML → sandbox → agente reale → criteri pesati 0.0–1.0 chicca skill_triggered: la skill è davvero scattata? sì/no + metriche licenza Apache-2.0 · Python 3.13+ · pip install coder-eval
Repo ufficiale · UiPath/coder_eval ↗
📄 Un task è un file YAML, niente di più
L'unità di lavoro è un file YAML con quattro cose: un prompt, la configurazione dell'agente, una sandbox e i criteri di successo. I campi obbligatori sono `task_id`, `description`, `initial_prompt` e almeno un criterio; `agent` e `sandbox` sono opzionali e, se omessi, vengono risolti dal layer degli esperimenti. Ci sono anche `tags` per filtrare le esecuzioni, `reference` per una soluzione di riferimento, `pre_run` e `post_run` per comandi prima e dopo l'agente.
La sandbox ha due driver: `tempdir`, il default, che prepara una directory temporanea con un ambiente Python; e `docker`, il container, l'unico che la documentazione considera accettabile per task non fidati — e lo dice esplicitamente, `tempdir` non è un confine di sicurezza. Sul lato agente si configurano `type`, `model`, `permission_mode` (`acceptEdits` è quello consigliato per le valutazioni) e la lista di tool ammessi.
task_id: "hello_world"
description: "Create a Python script that prints Hello, World!"
initial_prompt: "Create hello.py that prints 'Hello, World!'"
agent:
type: "claude-code"
permission_mode: "acceptEdits"
allowed_tools: ["Read", "Write", "Bash"]
sandbox:
driver: "tempdir"
python: {}
success_criteria:
- type: "file_exists"
path: "hello.py"
description: "hello.py must be created"
- type: "run_command"
command: "python hello.py"
timeout: 10
description: "Script must execute successfully"Task Definition Guide · schema completo e tipi di criterio ↗
🎯 skill_triggered: la skill è scattata o no?
Questo è il criterio per cui vale la pena guardare il progetto. `skill_triggered` è un classificatore binario che scandisce le trace del run e cerca due segnali alternativi: una chiamata esplicita al tool `Skill` il cui parametro combacia con `skill_name` — i prefissi di namespace vengono rimossi, quindi `uipath-agents` intercetta anche `uipath-coded-agents:uipath-agents` — oppure, per un agente che il tool `Skill` non ce l'ha (Codex, per esempio), un comando che legge i file della skill da disco sotto `skills/<skill_name>/`.
L'etichetta osservata è «yes» se uno dei due segnali compare, «no» altrimenti; quella attesa è «yes» solo se `expected_skill` combacia con `skill_name`. Il punteggio è binario: 1.0 quando osservato e atteso coincidono, 0.0 altrimenti. Il pattern consigliato è etichettare ogni riga di un dataset con la skill che dovrebbe scattare — stringa vuota per le righe negative, dove la skill non deve partire — e impilare un criterio `skill_triggered` per skill sullo stesso dataset. Ognuno produce la propria matrice di confusione dalle stesse trace, e si può mettere una soglia su accuracy, F1 o precision/recall per etichetta.
- type: "skill_triggered"
description: "uipath-agents activation"
skill_name: uipath-agents # la skill da rilevare
expected_skill: "${row.expected_skill}" # attesa della riga; "" = negativa
suite_thresholds:
recall.yes: 0.70
precision.yes: 0.80Documentazione del criterio skill_triggered ↗
⚖️ Criteri pesati, non un pass/fail secco
Ogni criterio ha un `weight` (default 1.0) e una `pass_threshold` (default 0.9). Il task passa quando tutti i criteri raggiungono la propria soglia; in parallelo viene sempre calcolato un punteggio pesato con la formula `weighted_score = sum(score * weight) / sum(weight)`, utile per vedere il trend anche quando l'esito booleano è già noto. È il punto in cui questo approccio si stacca dagli script fatti in casa: il credito parziale esiste, e un peggioramento si vede prima che diventi un fallimento.
I tipi di criterio coprono un ventaglio ampio. Ci sono i controlli statici sui file (`file_exists`, `file_contains`, `file_check` con includes/excludes/regex, `file_matches_regex`, `json_check` con asserzioni JMESPath e JSON Schema), quelli sull'esecuzione (`run_command` con exit code e match su stdout, `command_executed`), il confronto con una soluzione di riferimento (`reference_comparison` con soglia di similarità) e i due giudici LLM: `llm_judge`, che valuta con una rubrica testuale, e `agent_judge`, che è un intero agente secondario con difese di sicurezza obbligatorie sui path sensibili.
A occhio, come si fa di solito
- Provo tre prompt e vedo se «sembra» che scatti
- Il modello cambia e non me ne accorgo
- Due skill con descrizioni simili si rubano i trigger
- Nessun numero da confrontare fra una settimana e l'altra
Con un criterio skill_triggered
- Righe positive e negative etichettate in un dataset
- Matrice di confusione con accuracy, precision, recall, F1
- Soglie di suite che fanno uscire il run con codice diverso da zero
- Storico dei punteggi pesati, quindi trend leggibili
Il valore non è il tool in sé: è passare da un'impressione a una metrica ripetibile.
🔁 A/B, dataset e gate in continuous integration
Sopra ai task c'è un layer di esperimenti che permette di far girare gli stessi task su varianti diverse: modello contro modello, prompt contro prompt, tool acceso contro tool spento, e — il caso più interessante per chi scrive skill — plugin della skill installato contro non installato. È il complemento naturale di `skill_triggered`: si misura quanto la skill sposta davvero il risultato, invece di assumerlo. Con la modalità dataset si prende un singolo task e lo si moltiplica su molte righe, ottenendo una suite di dimensioni serie da poche decine di righe di YAML.
L'ultimo pezzo è il gate in CI. Esiste una composite action pubblicata sul Marketplace GitHub che installa la CLI pinnata, esegue i task, scrive un report JUnit, appende il riepilogo al job summary e fa fallire lo step su qualunque task o soglia non rispettata. C'è anche un `minimum-task-score` opzionale, un pavimento stretto sul punteggio pesato che si somma all'exit code della CLI. La documentazione insiste su due cose: pinnare la versione, perché un aggiornamento del framework non deve spostare silenziosamente i risultati; e non esporre segreti a PR di fork, perché i task eseguono codice generato dall'agente.
- uses: actions/setup-node@v4 # l'agente claude-code ha bisogno della CLI…
with: { node-version: '20' }
- run: npm install -g @anthropic-ai/claude-code
- uses: UiPath/coder_eval@v0 # …poi gira il gate
with:
tasks: tests/tasks/**/*.yaml
model: claude-sonnet-5
minimum-task-score: "0.8"
env: |
ANTHROPIC_API_KEY=${{ secrets.ANTHROPIC_API_KEY }}Composite action coder_eval sul Marketplace GitHub ↗
💡 Perché lo trovo interessante, per chi sviluppa e per una PMI
Sul lato sviluppo il ragionamento è quello dei test di regressione, applicato a un pezzo di sistema che finora non ne aveva. Una skill, un server MCP, un CLAUDE.md: sono tutti artefatti che influenzano il comportamento di un agente senza che nessuno li verifichi mai in modo automatico. Il giorno in cui il modello cambia versione, l'unica cosa che si nota è che «l'agente si comporta un po' diverso». Un task YAML con due o tre criteri, eseguito su schedule, trasforma quella sensazione in una riga rossa nella pipeline.
Sul lato azienda il punto è la ripetibilità nel tempo. Se in un team si stanno introducendo agenti nei processi — revisione del codice, generazione di documentazione, triage dei ticket — la domanda che prima o poi arriva è «come sappiamo che continua a funzionare?». Avere una suite di task eseguibile è la differenza fra un'adozione governata e una serie di aneddoti. Aggiungo che la telemetria per tool call, token e costo che il framework raccoglie è utile quanto lo scoring: rende visibile quanto costa davvero un flusso agentico prima di generalizzarlo su tutto il team.
- 01Scrivo la skillSKILL.md con la descrizione che decide se e quando scatterà
- 02Scrivo 5-10 righe di datasetcasi positivi dove deve scattare, negativi dove non deve
- 03Un task YAMLskill_triggered + un paio di criteri sull'esito concreto (file, comandi)
- 04Run localecoder-eval plan per validare senza spendere token, poi run e report
- 05Gate schedulatol'action in CI su ogni modifica alla skill e a cadenza fissa
Il costo di ingresso è basso: il valore arriva quando il run diventa periodico, non alla prima esecuzione.
⚠️ Cosa mettere in conto prima di provarlo
Tre cose vanno dette con chiarezza. La prima: il progetto è molto giovane. Poche stelle, pochissimi commit sul ramo principale, versione ancora sotto l'1.0 — la action stessa si referenzia come `@v0` in attesa del rilascio stabile. Ha però una base solida attorno: pacchetto su PyPI, action sul Marketplace, sito di documentazione, licenza Apache-2.0 e una CI pubblica. È materiale da studiare e da usare in un progetto interno, non ancora da mettere al centro di un processo critico.
La seconda: valutare costa. Ogni run lancia un agente vero con credenziali vere — Anthropic, Bedrock o Gemini — e coder_eval non fa da proxy né fornisce accesso al modello. Il comando `plan` valida un task senza spendere token, ed è il primo posto dove abituarsi a passare. La terza: la telemetria d'uso anonima è attiva di default e si disattiva con `TELEMETRY_ENABLED=false`; la documentazione precisa che non cattura prompt, contenuti dei file o path del repository, ma è una scelta consapevole da fare prima di installarlo in azienda. Infine, richiede Python 3.13 o superiore.
✅ Da dove partire
Il percorso più corto è il tutorial ufficiale: clonare il repo, `uv sync --extra dev`, e far girare `coder-eval plan tasks/hello_date.yaml` per vedere la validazione senza consumare nulla. Solo dopo il `run` e il `report`. Chi vuole usarlo su un progetto proprio installa il pacchetto pubblicato — `uv tool install coder-eval` oppure `pip install coder-eval` — e punta la CLI ai propri file di task, pinnando la versione se finisce in una pipeline.
Il segnale più ampio che leggo in questo repo, però, va oltre il tool. Le skill e i server MCP stanno diventando artefatti di prodotto: hanno una superficie pubblica, un comportamento osservabile e delle regressioni. È esattamente la fase in cui in ogni altro ambito del software sono comparsi i test. Che sia coder_eval o un altro framework a vincere conta poco: il pattern — descrivo il comportamento atteso in un file, lo eseguo in sandbox, lo misuro e lo gate in CI — è quello che vale la pena portarsi a casa.
Domande frequenti su coder_eval
Che cos'è coder_eval e a cosa serve?
È un framework open source Apache-2.0 pubblicato da UiPath per valutare e benchmarkare agenti di coding e le loro skill. Esegue un agente reale (Claude Code, Codex o Antigravity/Gemini) dentro una sandbox contro task scritti in YAML, poi assegna un punteggio ai file e ai comandi effettivamente prodotti usando criteri pesati da 0.0 a 1.0. Serve a trasformare in metrica ripetibile qualcosa che di solito si giudica a occhio.
Come faccio a sapere se una skill di Claude Code è davvero scattata?
Con il criterio `skill_triggered`. È un classificatore binario che scandisce le trace del run cercando una chiamata al tool Skill con parametro corrispondente, oppure — per agenti senza quel tool — la lettura dei file della skill sotto `skills/<nome>/`. Su un task alimentato da dataset, con righe positive e negative, produce accuratezza, precision, recall, F1 e matrice di confusione, e si può gatare con soglie di suite.
coder_eval è un benchmark come SWE-bench?
No, ed è una differenza sostanziale. SWE-bench e SkillsBench sono dataset fissi che producono una classifica di modelli su problemi canonici. coder_eval non ha classifica né dataset proprio: valuta i task, le skill e i workflow che scrivi tu, con criteri pesati e soglie decise da te. Può comunque incapsulare un dataset esterno tramite la modalità bring-your-own-dataset.
Quanto costa far girare una suite di valutazione?
Dipende dai token consumati dall'agente, perché ogni run lancia un agente vero con le tue credenziali: coder_eval non fa da proxy e non fornisce accesso ai modelli. Il comando `plan` valida i task senza spendere nulla, ed è il modo giusto per iterare sullo YAML. Il framework raccoglie inoltre telemetria per tool call, token e costo, quindi il conto di ogni suite è visibile nei report.
Posso usarlo come gate in continuous integration?
Sì: esiste una composite action sul Marketplace GitHub che installa la CLI pinnata, esegue i task, scrive un report JUnit e fa fallire lo step su qualunque task o soglia non rispettata, con un `minimum-task-score` opzionale come pavimento sul punteggio pesato. Due avvertenze dalla documentazione: pinnare la versione e non esporre segreti a pull request di fork, perché i task eseguono codice generato dall'agente.
Parliamone
Se questo tema ti riguarda, scrivimi: confrontarsi su codice e AI è sempre tempo speso bene.



