# 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.