Files
fit-boilerplate-wox/docs/eval-strategy.md
Felipe Arentsen b089c2ef18
Some checks failed
CI — Lint + Evals / lint (push) Has been cancelled
CI — Lint + Evals / smoke (push) Has been cancelled
feat: v1 — boilerplate WxO + web
Boilerplate completo para construir soluciones agénticas sobre IBM
watsonx Orchestrate (ADK 2.x) con una capa web encima.

Destilado de cotemar-poc-n1 y dun-casos-prueba. Incluye:

- 11 docs (best practices, architecture patterns, ADK cheatsheet,
  observability, tool authoring, deployment, RUNBOOK, DEPLOY_TO_NEW_WOX,
  known-issues con 16 errores reales y fix, eval strategy, INDEX)
- 13 templates WxO (orchestrator/specialist/single-meta agents,
  3 connections, KB + runbook, observable_tool decorator, coercion
  helpers, Python tools, OpenAPI spec, backend filter endpoint, webhook
  validator HMAC, MCP connection)
- 6 scripts (deploy idempotente con fallback ADK, undeploy, reset,
  check-adk-version, new-specialist scaffold, eval-agents runner)
- 4 eval pieces (linter de best practices, runner, smoke-test, direct
  backend probe) + scenario templates
- 8 subagentes Claude (.claude/agents/) — wxo-architect, wxo-agent-author,
  wxo-tool-author, runbook-author, mock-builder, backend-tool-builder,
  eval-author, web-layer-builder
- Skill bundle fit-wxo-bootstrap/ (SKILL.md + 3 templates) listo para
  copiar a ~/.claude/skills/
- Web layer default FastAPI+HTMX con vista timeline observable + endpoint
  receptor de trazas
- Docker compose Coolify-ready (healthcheck wget -qO-, sin labels Traefik,
  network split internal:true)
- CI Gitea workflow con lint + smoke

Best practices enforced por evals/lint_wxo_yaml.py:
- A1: máx 10 tools por agente
- A3: orchestrator sin tools de remediación
- A6: agente sin propósito (react sin tools ni KB)
- T1: @observable_tool obligatorio, no @tool directo
- T3: _compat shim inline en tools.py
- D1: docker-compose sin wget --spider
- I-005: OpenAPI con description per-operation
- I-009: sin labels Traefik manuales

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 14:59:44 +00:00

248 lines
6.4 KiB
Markdown

# Eval Strategy
Cómo validar que tu solución hace lo que debe. **Cuatro capas**, cada una
respondiendo una pregunta distinta.
---
## Capa 1 — Native (ADK)
**Pregunta:** ¿El agente responde algo razonable al input?
**Herramienta:** `orchestrate agents test`
```bash
orchestrate agents test mi_agente --input-file evals/scenarios/test1.json
```
Output:
- La respuesta del agente
- La traza de tool calls
- El timing
**Cobertura:**
- Happy path
- Casos límite (input ambiguo, datos faltantes)
- Casos de error (sistema externo caído, datos inválidos)
**Limitación:** no compara contra expected. Solo te muestra qué pasó.
**Fixture format** (`evals/scenarios/test1.json`):
```json
{
"messages": [
{ "role": "user", "content": "Necesito resetear la contraseña de juan.perez@cotemar.com" }
]
}
```
---
## Capa 2 — Agent behavior (custom)
**Pregunta:** ¿El agente llamó las tools correctas en el orden correcto?
**Herramienta:** `evals/runner.py` que consume trazas observables.
**Fixture format** (`evals/scenarios/scenario_reset.yaml`):
```yaml
name: reset_password_happy_path
input: "Necesito resetear la contraseña de juan.perez@cotemar.com"
expect:
agent_response_contains: ["TKT-"]
tool_calls_in_order:
- tool: lookup_user
inputs.username: "juan.perez@cotemar.com"
- tool: reset_password
- tool: create_ticket
inputs.status: "RESOLVED"
no_tool_calls:
- escalate_to_n2
```
**Cómo corre:**
1. Manda el input al agente vía WxO Runs API
2. Espera la respuesta
3. Lee las trazas emitidas durante el run (capa observability)
4. Compara contra `expect`
5. Pass/fail
**Por qué importa:** un agente puede dar la respuesta correcta llamando
las tools incorrectas (ej: dijo `RESOLVED` sin llamar `reset_password`).
Esto detecta esos casos.
---
## Capa 3 — Runbook compliance (custom)
**Pregunta:** ¿El estado final del sistema coincide con lo que el runbook
dice que debe pasar?
**Herramienta:** `evals/runner.py` con asserts sobre la DB del backend.
**Fixture format** (`evals/scenarios/scenario_reset.yaml` — sección
`final_state`):
```yaml
final_state:
query: "SELECT * FROM tickets WHERE created_at > $START_TIME"
expect_count: 1
expect_fields:
status: "RESOLVED"
category: "password_reset"
assigned_group: "Capital Humano"
extra.runbook: "01"
```
**Cómo corre:**
1. Captura timestamp inicial
2. Ejecuta el scenario (manda input al agente)
3. Query a la DB para ver qué se creó/actualizó
4. Asserts contra `final_state`
**Por qué importa:** la traza puede decir "todo bien" pero el ticket
final puede tener el grupo equivocado, falta de metadata, etc.
---
## Capa 4 — Web layer (custom, opcional)
**Pregunta:** ¿La UI muestra correctamente el resultado?
**Herramienta:** Playwright o `requests` + parsing HTML.
**Cuándo aplica:** si la solución incluye un control plane / kanban /
dashboard que el usuario consume directamente.
**Fixture format** (`evals/scenarios/scenario_reset.yaml` — sección `ui`):
```yaml
ui:
visit: "/insights"
expect_text:
- "Resueltos: 1"
- "Runbook 01"
visit: "/"
expect_selector: ".ticket-card--RESOLVED"
expect_count_selector:
selector: ".ticket-card"
count: ">=1"
```
---
## Runner
```bash
./evals/eval-agents.sh
```
Hace en orden:
1. `lint_wxo_yaml.py` — best practices estáticas (issue check antes de runtime)
2. Native eval por cada `evals/scenarios/*.json`
3. Behavior eval por cada `evals/scenarios/*.yaml`
4. Final state eval (parte del mismo YAML)
5. UI eval si existe sección `ui`
Reporta:
```
[lint] PASS
[native] PASS (5/5)
[behavior] PASS (4/5) — scenario "edge_case_inactive_user" FAILED
[final_state] PASS (4/5)
[ui] SKIP (no fixtures)
```
Exit code 0 si todo pasa, 1 si alguno falla.
---
## Smoke test (CI nightly)
`evals/smoke-test.sh` es el subset mínimo que debe pasar **siempre**:
1. Health endpoint responde 200
2. Un caso simple end-to-end (login → create → execute → poll → assert)
3. El audit log tiene las entries esperadas
4. La UI muestra el resultado
Si falla, algo de la infraestructura está mal (deploy, DNS, healthcheck,
auth, etc.). NO mira el agente en profundidad — para eso están las
capas 2/3.
```bash
./evals/smoke-test.sh
```
---
## Direct backend probe (diagnóstico)
`evals/direct-backend-probe.sh` golpea el backend directamente con
curl + el token de WxO. Para aislar problemas:
```bash
$ ./evals/direct-backend-probe.sh
[1/3] Healthcheck OK (200)
[2/3] Direct tool call OK (200) — got expected "case not found"
[3/3] Auth test OK (200 con token, 401 sin)
✓ Backend OK from WxO side. Si la solución falla, es el agente o el LLM.
```
Si los 3 pasan pero el agente igual falla, el problema está en:
- El prompt del agente
- El modelo (issue I-002)
- El recursion_limit (issue I-001)
- Los schemas (issue I-003)
---
## Estrategia recomendada por fase del proyecto
### Fase 1 — Desarrollo
- **Capa 1** (native) frecuente, manualmente
- **Lint** antes de cada commit (pre-commit hook)
### Fase 2 — Estabilización
- Agregar **Capa 2** (behavior) para cada scenario
- Agregar **Capa 3** (final_state) para cada scenario
- CI corre las 3 en cada PR
### Fase 3 — Demo / handoff
- Agregar **Capa 4** (UI) para los 2-3 paths críticos
- **Smoke test nightly** en CI
### Fase 4 — Producción
- Smoke test cada 15 min (cron)
- Direct backend probe en healthcheck
- Behavior eval suite semanal
---
## Archivos a crear por scenario
```
evals/scenarios/
├── scenario_reset_password.yaml ← Capas 2, 3, 4 unified
├── scenario_reset_password.input.json ← Capa 1 (input para `agents test`)
├── scenario_restart_service.yaml
├── scenario_restart_service.input.json
└── ...
```
El subagente `eval-author` (en `.claude/agents/eval-author.md`) genera
estos pares automáticamente cuando le das un runbook o un agente nuevo.
---
## Cuando una eval falla
1. Mirá `evals/last_run.log` — qué fixture, qué assert
2. Si es **Capa 1**: el agente respondió mal o no respondió. Ver prompt.
3. Si es **Capa 2**: el agente respondió bien pero llamó las tools mal.
Ver instructions del agente.
4. Si es **Capa 3**: tools se llamaron pero el resultado final está
incorrecto. Ver el handler del backend.
5. Si es **Capa 4**: backend OK pero UI no muestra. Ver el view / HTMX template.
Repará, corré la eval específica (`./evals/eval-agents.sh -s
scenario_x`), commit.