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>
This commit is contained in:
178
docs/RUNBOOK.md
Normal file
178
docs/RUNBOOK.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# RUNBOOK — Operaciones
|
||||
|
||||
Cómo monitorear, recuperar, rotar y troubleshootear una solución
|
||||
desplegada con este template.
|
||||
|
||||
## URLs y endpoints clave
|
||||
|
||||
| URL | Para qué |
|
||||
|---|---|
|
||||
| `https://$PUBLIC_HOST/` | Landing con chat embed |
|
||||
| `https://$PUBLIC_HOST/web/` | App principal (UI) |
|
||||
| `https://$PUBLIC_HOST/health` | Healthcheck (200 = todo OK) |
|
||||
| `https://$PUBLIC_HOST/api/traces` | Vista timeline de tool calls (admin) |
|
||||
| WxO Console | Settings, agents, channels |
|
||||
| Coolify panel | Deploy, logs, env vars |
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Healthcheck simple
|
||||
```bash
|
||||
curl -sf "https://$PUBLIC_HOST/health" && echo OK || echo FAIL
|
||||
```
|
||||
|
||||
### Smoke test nightly
|
||||
Configurar CI/cron que corra cada noche:
|
||||
```bash
|
||||
./evals/smoke-test.sh
|
||||
```
|
||||
Si falla, alerta por email/Slack.
|
||||
|
||||
### Logs en tiempo real
|
||||
```bash
|
||||
# Local
|
||||
docker compose logs -f --tail=100
|
||||
|
||||
# Coolify
|
||||
# Panel → app → Logs tab
|
||||
```
|
||||
|
||||
Buscar:
|
||||
- `ERROR` o `Exception` en stdout
|
||||
- `recursion_limit` (issue I-001)
|
||||
- `kid not found` (issue I-004)
|
||||
- `422 Unprocessable Entity` (issue I-003)
|
||||
|
||||
## Recovery procedures
|
||||
|
||||
### El chat embed quedó en "Cargando..."
|
||||
1. Settings → Embed Security debe estar **Off**. Issue I-007.
|
||||
2. Verificar que el `agentId` y `agentEnvironmentId` del HTML
|
||||
coincidan con `orchestrate agents list --env live`.
|
||||
3. Browser console: buscar errores CORS o 401.
|
||||
|
||||
### Casos atascados en `executing` (issue I-012)
|
||||
El watchdog del backend los promueve a `paused` automáticamente
|
||||
después de 90s. Si no pasa:
|
||||
1. Ver logs: `grep "case_id=XXXX"`
|
||||
2. Si Orchestrate jamás llamó al callback, el run murió: re-trigger desde la UI
|
||||
3. Si el callback llegó pero la DB no actualizó, ver issue I-013
|
||||
|
||||
### El agente printea tool calls como texto (issue I-002)
|
||||
1. Verificar `llm:` en el YAML del agente = `groq/openai/gpt-oss-120b`
|
||||
2. Verificar que REGLA #0 está en el prompt
|
||||
3. Si persiste con gpt-oss-120b → reportar a IBM, es regresión del modelo
|
||||
|
||||
### Pydantic 422 en tool calls (issue I-003)
|
||||
1. Ver el payload exacto que el LLM mandó (logs del backend)
|
||||
2. Si stringificó algo que debería ser int/list → falta `@field_validator(mode="before")`
|
||||
3. Agregar el validator, redeployar el backend
|
||||
|
||||
### Deploy WxO falla con `kid not found` (issue I-004)
|
||||
```bash
|
||||
# Re-configurar la connection en live
|
||||
orchestrate connections configure -a <app_id> --env live --type team --kind <kind>
|
||||
orchestrate connections set-credentials -a <app_id> --env live -e "BASE_URL=..."
|
||||
|
||||
# Re-deployar agente
|
||||
orchestrate agents deploy --name <agent> --env live
|
||||
```
|
||||
|
||||
### Coolify dio 503 después de redeploy (issue I-008)
|
||||
1. `docker logs <container>` → buscar healthcheck failures
|
||||
2. Cambiar `wget --spider` a `wget -qO-` en el Dockerfile
|
||||
3. Rebuild
|
||||
|
||||
### Backend OK pero WxO no llega (issue I-008/I-009)
|
||||
```bash
|
||||
# Probar desde fuera
|
||||
curl -sf "https://$PUBLIC_HOST/api/v1/health"
|
||||
|
||||
# Si 200 OK pero WxO da timeout → firewall/network
|
||||
# Si 503 → Traefik/healthcheck
|
||||
# Si TRAEFIK DEFAULT CERT → labels manuales, ver I-009
|
||||
```
|
||||
|
||||
## Rotación de secretos
|
||||
|
||||
### API key del tenant WxO
|
||||
1. WxO Console → IAM → Generate new API key
|
||||
2. Actualizar `.env`: `ORCHESTRATE_API_KEY=<nuevo>`
|
||||
3. `docker compose up -d --force-recreate` (NO `restart`, issue I-011)
|
||||
4. `orchestrate env activate <env-name>` con el nuevo key
|
||||
|
||||
### Credenciales de connection
|
||||
```bash
|
||||
orchestrate connections set-credentials -a <app_id> --env draft -e "BASE_URL=..." -e "API_KEY=<nuevo>"
|
||||
orchestrate connections set-credentials -a <app_id> --env live -e "BASE_URL=..." -e "API_KEY=<nuevo>"
|
||||
```
|
||||
|
||||
No hay que re-deployar agentes — las connections se resuelven en runtime.
|
||||
|
||||
### Webhook signing secret
|
||||
1. Generar nuevo secret
|
||||
2. Actualizar `.env` + Coolify env vars: `WEBHOOK_SECRET=<nuevo>`
|
||||
3. `--force-recreate`
|
||||
4. Si el sistema externo usa el viejo secret, coordinar el switch
|
||||
|
||||
## Backup y restore
|
||||
|
||||
### Backup
|
||||
- **Código + YAMLs**: vive en Gitea. Backup automático del repo.
|
||||
- **Backend DB**: `docker exec <db-container> pg_dump > backup.sql` (o equivalente)
|
||||
- **Audit logs**: parte del backup de la DB
|
||||
- **Trazas SQLite**: `cp web/data/traces.db backup/`
|
||||
- **WxO config**: los YAMLs del repo. `orchestrate agents list` te dice qué está en live.
|
||||
|
||||
### Restore
|
||||
- **Código**: `git clone` y `./scripts/deploy-wxo.sh`
|
||||
- **DB**: `pg_restore < backup.sql`
|
||||
- **Traces**: si las perdés, no es crítico (son observabilidad histórica)
|
||||
|
||||
### Disaster recovery completo
|
||||
1. Clonar repo en nuevo host
|
||||
2. `.env` con credenciales del tenant (las que ya tenías guardadas)
|
||||
3. `./scripts/deploy-wxo.sh` — recrea todo en WxO desde los YAMLs
|
||||
4. `docker compose up -d` — levanta backend/web
|
||||
5. Restore DB si necesario
|
||||
6. Capturar nuevos IDs, propagar
|
||||
7. Smoke test
|
||||
|
||||
Tiempo objetivo: <30 min.
|
||||
|
||||
## Troubleshooting checklist
|
||||
|
||||
Cuando algo se rompe y no sabés por dónde empezar:
|
||||
|
||||
1. [ ] `curl -sf $PUBLIC_HOST/health` — ¿el servicio responde?
|
||||
2. [ ] `docker ps` — ¿los containers están healthy?
|
||||
3. [ ] `docker logs <container> --tail=200` — ¿hay errores recientes?
|
||||
4. [ ] `orchestrate agents list` — ¿el agente está en live?
|
||||
5. [ ] `./evals/direct-backend-probe.sh` — ¿la auth funciona?
|
||||
6. [ ] `./evals/smoke-test.sh` — ¿el flujo end-to-end?
|
||||
7. [ ] WxO Console → Runs → últimos runs — ¿qué error tienen?
|
||||
8. [ ] `docs/known-issues.md` — ¿coincide con algún I-XXX?
|
||||
|
||||
Si después de los 8 sigue roto, escalalo. Pero el 90% de los problemas
|
||||
están en uno de los 8.
|
||||
|
||||
## Versión / actualización del ADK
|
||||
|
||||
```bash
|
||||
./scripts/check-adk-version.sh
|
||||
```
|
||||
|
||||
Si hay nueva versión:
|
||||
1. **NO actualizar directamente.**
|
||||
2. Crear branch `chore/adk-X.Y.Z`
|
||||
3. `pip install ibm-watsonx-orchestrate==X.Y.Z`
|
||||
4. Re-deployar a un env de staging
|
||||
5. Correr todas las evals
|
||||
6. Si pasan, PR + merge + deploy a prod
|
||||
7. Actualizar el pin en `requirements.txt` + `check-adk-version.sh`
|
||||
|
||||
## Cuando todo lo demás falla
|
||||
|
||||
Ver `docs/known-issues.md` y `docs/adk-2x-cheatsheet.md`. Si tampoco
|
||||
está ahí, abrir issue en el repo del template para que la próxima
|
||||
persona no lo sufra.
|
||||
Reference in New Issue
Block a user