MÓDULO 4.4

🛠️ Como Criar: Walkthrough Completo com Evals

Um exemplo trabalhado de ponta a ponta: do intent (4 perguntas) ao SKILL.md, test prompts realistas, evals.json com assertions verificáveis, rodar com-skill vs baseline e iterar. Templates JSON prontos para copiar.

6
Tópicos
50
Minutos
Prático
Nível
Hands-on
Tipo
intent draft evals rodar iterar repetir até satisfazer

Vamos construir uma skill de verdade do começo ao fim: "margem-xlsx" — recebe uma planilha de vendas e adiciona uma coluna de margem de lucro em %. Acompanhe cada estágio.

1

🎯 Estágio 1 — Capturar o intent (4 perguntas)

Antes de escrever uma linha, o skill-creator faz 4 perguntas. Se a conversa já tem o workflow, extraia das mensagens e só pergunte o que falta. Confirme antes de seguir.

as 4 perguntas → respostas do nosso 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)

💡 Saída verificável → vale testar

A pergunta 4 decide o resto do walkthrough. Transformações de arquivo, extração de dados e geração de código têm saída objetiva — merecem evals. Skills de estilo/arte se avaliam só qualitativamente. Como o nosso caso é uma transformação de planilha, vamos full evals.

2

📝 Estágio 2 — Draft do SKILL.md

Com o intent fechado, escreva o draft: name, description (o gatilho — pushy, com o que faz E quando usar) e o corpo no imperativo, explicando o porquê.

SKILL.md — draft 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 fraca

"Mexe em planilhas de vendas."

Vaga, não diz quando disparar, vai subdisparar.

✓ description pushy

Lista verbos + contextos: "margem, lucro, rentabilidade... mesmo sem pedir coluna".

O que faz E quando usar, com near-triggers cobertos.

3

🧪 Estágio 3 — 2-3 test prompts realistas

Crie de 2 a 3 prompts como um usuário real escreveria — com backstory, paths e detalhes. Mostre ao usuário, salve em evals/evals.json sem assertions ainda.

evals/evals.json — TEMPLATE pronto (só 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"]
    }
  ]
}

🎯 Valide antes de rodar

Diga ao usuário: "Aqui estão os casos de teste que quero tentar. Estão certos ou quer adicionar mais?". Prompts ruins geram avaliação enganosa — esta confirmação é barata e evita rodar tudo à toa.

4

📊 Estágio 4 — Assertions verificáveis

Enquanto as runs rodam (não fique parado), escreva as assertions: objetivamente verificáveis, com nomes descritivos, de preferência checadas por script. Cada test case ganha um eval_metadata.json.

eval_metadata.json — TEMPLATE pronto (com 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 ruim

  • "a planilha ficou boa" (subjetivo)
  • "check_1" (nome opaco no viewer)
  • "arquivo existe" (passa com ou sem skill)

✓ assertion boa

  • "Valores batem com (C-D)/C" (script confere)
  • Nome legível: "coluna formatada como %"
  • Discrimina with_skill de baseline
5

⚖️ Estágio 5 — Rodar com-skill vs baseline

Para cada test case, dispare dois subagents no mesmo turno: um com a skill, um sem (baseline = sem skill, pois é skill nova). Organize a saída por iteração e por eval. Capture total_tokens e duration_ms da notificação assim que cada run terminar.

estrutura do workspace + 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 que no mesmo turno

Lance with_skill e without_skill juntos para terminarem por volta do mesmo tempo. Não rode os com-skill primeiro e volte depois para os baselines — isso introduz viés e dificulta comparar. O timing.json só pode ser capturado quando a notificação chega; processe cada uma na hora.

6

🔁 Estágio 6 — Avaliar e iterar (timeline)

Com tudo rodado, feche o loop. A timeline numerada abaixo é o ciclo do skill-creator, do grading até a próxima iteração.

1

Grade cada run

Um grader avalia cada assertion → grading.json com campos text, passed, evidence. Para checagens programáticas, rode um script em vez de olhar no olho.

2

Agregue o benchmark

python -m scripts.aggregate_benchmark iteration-1 --skill-name margem-xlsx → pass_rate, tempo e tokens por config, com média ± desvio e delta.

3

Abra o viewer ANTES de você julgar

generate_review.py com --benchmark. Ponha os outputs na frente do humano primeiro. Não escreva HTML próprio.

4

Leia o feedback e generalize

Feedback vazio = ok. Onde há reclamação, generalize a correção (não overfit), mantenha enxuto, explique o porquê. Script repetido nas 3 runs → bundle em scripts/.

5

Rerode em iteration-2 e repita

Nova iteração com baselines, reviewer com --previous-workspace. Pare quando o usuário estiver feliz, o feedback vazio ou sem progresso.

💡 O que aconteceu no nosso caso

As 3 runs com-skill escreveram um calc_margem.py quase idêntico — sinal forte de bundlar. Na iteração 2, o script foi para scripts/ e o SKILL.md passou a apontá-lo. Resultado: pass_rate subiu e os tokens por run caíram, porque cada invocação parou de reinventar a roda.

Resumo do Módulo

Intent em 4 perguntas — habilita o quê, quando dispara, formato, vale testar (saída verificável → sim)
Draft com description pushy — o que faz E quando usar, corpo imperativo com o porquê
evals.json sem assertions, depois eval_metadata.json com — templates JSON prontos para copiar
Rodar com-skill vs baseline no mesmo turno — workspace por iteração e eval, capturar timing.json na hora
Grade → agregue → viewer → feedback → itere — script repetido vira bundle, e o loop fecha

Próximo:

Módulo 4.5 — 🚀 Dicas Avançadas: Otimização de Description e Benchmark — split 60/40, near-misses, blind comparison e como ler o benchmark sem se enganar.