PTENES
MÓDULO 4.4

🛠️ Cómo crear: recorrido completo con evals

Un ejemplo completo y detallado: desde el intent (4 preguntas) hasta el SKILL.md, test prompts realistas, evals.json con assertions verificables, ejecución con-skill vs baseline e iteración. Plantillas JSON listas para copiar.

6
Temas
50
Minutos
Práctico
Nivel
Práctica
Tipo
intent borrador evals ejecutar iterar repetir hasta satisfacer

Vamos a construir una skill de verdad de principio a fin: "margen-xlsx" — recibe una hoja de cálculo de ventas y agrega una columna de margen de ganancia en %. Sigue cada etapa.

1

🎯 Etapa 1 — Capturar el intent (4 preguntas)

Antes de escribir una sola línea, skill-creator hace 4 preguntas. Si la conversación ya tiene el workflow, extráelo de los mensajes y pregunta solo lo que falta. Confirma antes de seguir.

las 4 preguntas → respuestas de nuestro caso:

1. O que habilita?  → adicionar coluna de margem (%) num xlsx de vendas
2. Quando dispara?  → usuário menciona planilha, margem, lucro, vendas
3. Formato saída?   → mesmo xlsx + nova coluna formatada como %
4. Vale testar?     → SIM (saída objetivamente verificável)

💡 Salida verificable → vale la pena probar

La pregunta 4 decide el resto del walkthrough. Las transformaciones de archivos, la extracción de datos y la generación de código tienen resultados objetivos: merecen evals. Las skills de estilo y arte se evalúan solo cualitativamente. Como nuestro caso es una transformación de una hoja de cálculo, haremos evals completos.

2

📝 Etapa 2 — Borrador del SKILL.md

Con el intent definido, escribe el draft: name, description (el disparador — directo, con lo que hace Y cuándo usarlo) y el cuerpo en imperativo, explicando por qué.

SKILL.md — borrador inicial:

---
name: margem-xlsx
description: Adiciona uma coluna de margem de lucro (%) a planilhas
  de vendas .xlsx. Use sempre que o usuário enviar uma planilha e
  mencionar margem, lucro, rentabilidade ou comparar receita e
  custos — mesmo sem pedir "coluna" explicitamente.
---

# Margem XLSX

Calcule a margem como (receita - custo) / receita e grave numa
nova coluna formatada como porcentagem.

## Passos
1. Abra o .xlsx e identifique as colunas de receita e custo
   (pergunte se ambíguo — não chute).
2. Crie a coluna "Margem" à direita, formatada como %.
3. Preserve abas, fórmulas e formatação existentes.
4. Salve mantendo o nome original com sufixo "-margem".

✗ description débil

"Modifica hojas de cálculo de ventas."

Es vago, no indica cuándo activarse y se activará con poca frecuencia.

✓ description insistente

Enumera verbos + contextos: «margen, lucro, rentabilidad... incluso si no pide una columna».

Qué hace Y cuándo usarlo, con los activadores cercanos cubiertos.

3

🧪 Etapa 3 — 2-3 prompts de prueba realistas

Crea de 2 a 3 prompts como los escribiría un usuario real, con historia de fondo, rutas y detalles. Muéstraselos al usuario, guárdalos en evals/evals.json sin assertions todavía.

evals/evals.json — TEMPLATE listo (solo prompts):

{
  "skill_name": "margem-xlsx",
  "evals": [
    {
      "id": 1,
      "prompt": "minha chefe mandou 'Q4 sales final FINAL v2.xlsx' (tá em Downloads) e quer margem de lucro em %. receita na col C, custo na D acho",
      "expected_output": "xlsx com coluna Margem em % à direita",
      "files": ["Q4 sales final FINAL v2.xlsx"]
    },
    {
      "id": 2,
      "prompt": "tenho esse relatorio de vendas mensal, da pra ver quanto a gente lucra de verdade em cada produto? planilha anexa",
      "expected_output": "coluna de rentabilidade por linha em %",
      "files": ["vendas_mensal.xlsx"]
    },
    {
      "id": 3,
      "prompt": "preciso comparar receita vs custo por SKU nessa planilha e ver a margem",
      "expected_output": "coluna Margem = (receita-custo)/receita",
      "files": ["skus.xlsx"]
    }
  ]
}

🎯 Valida antes de ejecutar

Dile al usuario: "Estos son los casos de prueba que quiero probar. ¿Están bien o quieres agregar más?". Los prompts malos generan evaluaciones engañosas: esta confirmación cuesta poco y evita ejecutarlo todo en vano.

4

📊 Etapa 4 — Assertions verificables

Mientras se ejecutan las runs (no te quedes sin hacer nada), escribe las afirmaciones: verificables objetivamente, con nombres descriptivos y, de preferencia, comprobadas por un script. Cada test case recibe un eval_metadata.json.

eval_metadata.json — TEMPLATE listo (con assertions):

{
  "eval_id": 0,
  "eval_name": "margem-q4-receita-custo",
  "prompt": "...margem de lucro em %. receita col C, custo D...",
  "assertions": [
    "Arquivo .xlsx de saída existe com sufixo -margem",
    "Coluna 'Margem' presente à direita das demais",
    "Coluna Margem formatada como porcentagem (%)",
    "Valores batem com (C - D) / C por linha",
    "Abas e formatação originais preservadas"
  ]
}

✗ assertion deficiente

  • ✗"la hoja de cálculo quedó bien" (subjetivo)
  • ✗"check_1" (nombre opaco en el visor)
  • ✗"el archivo existe" (pasa con o sin la skill)

✓ assertion buena

  • ✓"Los valores coinciden con (C-D)/C" (el script lo comprueba)
  • ✓Nombre legible: "columna formateada como %"
  • ✓Distingue with_skill del baseline
5

⚖️ Etapa 5 — Ejecutar con skill vs. baseline

Para cada caso de prueba, activa dos subagentes en el mismo turno: una con la skill y otra sin ella (baseline = sin skill, porque es una skill nueva). Organiza la salida por iteración y por eval. Captura total_tokens e duration_ms de la notificación en cuanto termine cada run.

estructura del espacio de trabajo + timing.json:

margem-xlsx-workspace/
└── iteration-1/
    ├── margem-q4-receita-custo/
    │   ├── with_skill/outputs/   ← saída com a skill
    │   ├── without_skill/outputs/ ← baseline
    │   └── timing.json
    └── benchmark.json            ← gerado pela agregação

# timing.json
{ "total_tokens": 84852, "duration_ms": 23332,
  "total_duration_seconds": 23.3 }

Por qué en el mismo turno

Inicia with_skill y without_skill al mismo tiempo para que terminen más o menos a la vez. No ejecutes primero los casos con skill y vuelvas después para los baselines: eso introduce sesgo y dificulta la comparación. timing.json solo se puede capturar cuando llega la notificación; procesa cada una en el momento.

6

🔁 Etapa 6 — Evaluar e iterar (timeline)

Con todo ejecutado, cierra el loop. La timeline numerada de abajo es el ciclo de skill-creator, desde el grading hasta la siguiente iteración.

1

Califica cada ejecución

Un grader evalúa cada assertion → grading.json con campos text, passed, evidence. Para las verificaciones programáticas, ejecuta un script en vez de revisar a simple vista.

2

Agrega el benchmark

python -m scripts.aggregate_benchmark iteration-1 --skill-name margem-xlsx → pass_rate, tiempo y tokens por config, con promedio ± desviación y delta.

3

Abre el visor ANTES de juzgar

generate_review.py con --benchmark. Pon los outputs delante del humano primero. No escribas HTML propio.

4

Lee el feedback y generaliza

Feedback vacío = bien. Donde haya quejas, generaliza la corrección (no hagas overfit), mantenla concisa y explica el porqué. Script repetido en las 3 runs → bundle en scripts/.

5

Vuelve a ejecutar en iteration-2 y repite

Nueva iteración con baselines, reviewer con --previous-workspace. Detente cuando el usuario esté satisfecho, el feedback esté vacío o no haya progreso.

💡 Qué pasó en nuestro caso

Las 3 ejecuciones con skill escribieron un calc_margem.py casi idéntico — señal fuerte de bundling. En la iteración 2, el script pasó a scripts/ y el SKILL.md empezó a apuntar a él. Resultado: la tasa de aprobados subió y los tokens por ejecución bajaron, porque cada invocación dejó de reinventar la rueda.

✅ Resumen del módulo

✓
Intención en 4 preguntas — qué habilita, cuándo se activa, formato, ¿vale la pena probar? (salida verificable → sí)
✓
Borrador con description insistente — qué hace Y cuándo usarlo, cuerpo imperativo con el porqué
✓
evals.json sin assertions y luego eval_metadata.json con — templates JSON listos para copiar
✓
Ejecutar con-skill vs baseline en el mismo turno — workspace por iteración y eval; captura timing.json en el momento
✓
Califica → agrega → viewer → feedback → itera — un script repetido se convierte en bundle y el ciclo se cierra

Próximo:

Módulo 4.5 — 🚀 Consejos avanzados: optimización de description y benchmark — split 60/40, near-misses, blind comparison y cómo leer el benchmark sin engañarte.