MÓDULO 4.5

🚀 Dicas Avançadas: Otimização de Description e Benchmark

O loop de otimização de description (split 60/40, near-misses, best_description pelo test score), como o triggering realmente funciona, blind comparison e como ler o benchmark sem se enganar com assertions não-discriminantes.

6
Tópicos
50
Minutos
Avançado
Nível
Tuning
Tipo
train 60% test 40% loop (≤5x) propor + reavaliar best_desc pelo test score test só decide, nunca treina → evita overfit
1

🎚️ O loop de otimização de description

A description é o mecanismo primário de disparo. O run_loop.py automatiza a afinação: divide o eval set em 60% train / 40% held-out test, avalia a description atual (rodando cada query 3 vezes para um trigger rate confiável), chama o Claude para propor melhorias com base no que falhou e reavalia — até 5 iterações.

rodar o loop em background:

python -m scripts.run_loop \
  --eval-set trigger-eval.json \
  --skill-path ./margem-xlsx \
  --model <model-id-da-sessão> \
  --max-iterations 5 \
  --verbose
1

Split 60/40

Train para guiar as propostas, test held-out para decidir. O test nunca treina.

2

3 runs por query

Disparo é estocástico; rodar 3x dá um trigger rate estável em vez de um sim/não barulhento.

3

Propor → reavaliar → repetir

O Claude vê o que falhou e propõe nova description; o loop reavalia em train e test, até 5x.

💡 Use o model ID da sessão

Passe o model que está rodando a sessão atual, para o teste de disparo bater com o que o usuário realmente experimenta. Rode em background e dê updates periódicos tailando a saída — o loop demora.

2

🎯 Queries: should-trigger / should-not e near-misses

Gere ~20 queries realistas — o que um usuário real digitaria, com paths, nomes de coluna, backstory, às vezes em minúsculas ou com typos. Metade should-trigger, metade should-not. O ouro está nos near-misses.

✓ should-trigger (8-10)

  • Mesmo intent, fraseados diferentes (formal/casual)
  • Usuário não nomeia "margem" mas precisa dela
  • Usos incomuns; disputa com outra skill onde esta deve vencer

✗ should-not-trigger (8-10)

  • Near-miss: "limpe os duplicados dessa planilha de vendas" (mesmo arquivo, outra tarefa)
  • Domínio adjacente, frase ambígua
  • Evite negativos óbvios: "escreva um fibonacci" não testa nada

trigger-eval.json — queries rotuladas:

[
  {"query": "boss mandou Q4 sales.xlsx, quer margem de lucro em %",
   "should_trigger": true},
  {"query": "remove as linhas duplicadas dessa planilha de vendas",
   "should_trigger": false},
  {"query": "qual a margem de erro dessa pesquisa de satisfação?",
   "should_trigger": false}
]

Por que near-misses pesam

"Margem de erro de uma pesquisa" compartilha a palavra "margem" mas não tem nada a ver com lucro em planilha. Negativos assim forçam a description a discriminar de verdade. Negativos óbvios passam sempre e não ensinam nada ao loop. Bad eval queries levam a bad descriptions.

3

🧲 Como o triggering realmente funciona

Skills aparecem na lista available_skills com name + description, e o Claude decide consultar pela description. O detalhe que muda tudo: o Claude só consulta skills para tarefas que não resolve fácil sozinho.

✗ query fraca pra testar

"leia este PDF"

"abra esse arquivo"

Simples demais. O Claude resolve direto com ferramentas básicas — não dispara skill, por melhor que a description seja.

✓ query substantiva

"pega esse xlsx de vendas, calcula a margem por SKU e me devolve formatado em %"

Multi-step e especializada — o Claude se beneficia de consultar a skill.

💡 Suas queries de teste precisam ser substantivas

Se você testar disparo com "leia o arquivo X", vai concluir que a description está ruim quando na verdade a query nunca dispararia skill nenhuma. Queries simples e de um passo só são péssimos casos de teste. Combine isso com o fato de o Claude tender a subdisparar: por isso a description deve ser um pouco pushy.

4

⚖️ Blind comparison: o novo é mesmo melhor?

Quando o usuário pergunta "a versão nova é realmente melhor?", existe a comparação cega. A ideia: dar dois outputs a um agente independente sem dizer qual é qual, deixar ele julgar qualidade, e depois analisar por que o vencedor venceu.

1

Anonimize os outputs

Output A e Output B, sem rótulo de versão. Um comparador independente avalia sem viés.

2

Julgue a qualidade

O agente escolhe o melhor. Por ser cego, não favorece "o novo" só por ser novo.

3

Analise por que venceu

Entender o motivo é mais útil que o placar — diz o que manter na próxima iteração.

Opcional, e tudo bem

Blind comparison exige subagents e a maioria dos casos não precisa — o loop de review humano costuma bastar. Guarde para quando a dúvida "melhorou de verdade?" for cara o suficiente para justificar o rigor extra.

5

📈 Ler o benchmark sem se enganar

O benchmark traz pass_rate, tokens e tempo por configuração, com média ± desvio e o delta. Mas o número sozinho mente. Faça uma passada de analista antes de comemorar.

benchmark.json (resumo) — o que olhar:

with_skill:    pass_rate 0.92 ± 0.05  | 84.8k tok | 23.3s
without_skill: pass_rate 0.41 ± 0.18  | 61.2k tok | 18.1s
delta:         +0.51 pass | +23.6k tok | +5.2s

# leia também: assertions que passam em AMBOS (não discriminam)
# e evals com desvio alto (possivelmente flaky)

✗ armadilhas de leitura

  • Assertion passa com E sem skill → não mede a skill
  • Desvio alto num eval → pode ser flaky, não melhora real
  • Comemorar pass_rate ignorando explosão de tokens/tempo

✓ leitura saudável

  • Olhar o delta entre with_skill e baseline
  • Cortar assertions não-discriminantes do set
  • Pesar tradeoff: ganho de qualidade vale o custo?

💡 Assertion não-discriminante é ruído

Se "arquivo existe" passa em with_skill e em without_skill, ela infla o pass_rate dos dois igualmente e esconde a diferença real. O sinal está nas assertions que só a skill faz passar. A passada de analista existe para revelar exatamente esses padrões que a média esconde.

6

🏆 Pro tips: aplicar best_description e empacotar

No fim do loop, pegue o best_descriptionescolhido pelo test score, não pelo train — aplique no frontmatter e mostre o antes/depois ao usuário com os scores. Depois, empacote.

saída do loop + aplicar + empacotar:

# run_loop retorna:
{ "best_description": "...nova description afinada...",
  "train_score": 0.94, "test_score": 0.89, "iterations": 4 }

# aplique no SKILL.md (frontmatter) e mostre antes/depois
# depois empacote a skill final:
python -m scripts.package_skill ./margem-xlsx
# → margem-xlsx.skill (pronto para instalar)

Checklist de pro tips

Escolha sempre pelo test score — o train infla por overfit, o held-out é honesto.

Otimize a description só depois de a skill estar boa no conteúdo; não afine o gatilho de algo que ainda muda.

Revise o eval set com o usuário antes de rodar — queries ruins geram descriptions ruins.

Mantenha a description pushy mas honesta — cobrir near-triggers sim, prometer o que a skill não faz não.

🎯 Por que o test score

Se você escolhesse a description pelo train, premiaria justamente a que decorou os exemplos de treino. O held-out test simula queries que o loop nunca viu — é a melhor proxy do mundo real. Decidir por ele é o que separa uma description que generaliza de uma que só brilha no laboratório.

Resumo do Módulo

Loop de otimização — split 60/40, 3 runs por query, propor → reavaliar até 5x, model ID da sessão
Near-misses são o ouro — should-not que compartilha palavras mas precisa de outra coisa; evite negativos óbvios
Triggering só dispara em tarefas não-triviais — queries de teste precisam ser substantivas
Blind comparison — cego e opcional; analise por que venceu, não só o placar
Ler benchmark com olho de analista — corte assertions não-discriminantes, cuidado com variância e tradeoff de tokens
best_description pelo test score — aplique no frontmatter, mostre antes/depois, empacote com package_skill

Próximo:

Trilha 5 — 🧠 O Que Pensar — princípios e armadilhas ao decidir o que vira skill, como mantê-las saudáveis e o que evitar no longo prazo.