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>
94 lines
3.2 KiB
YAML
94 lines
3.2 KiB
YAML
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Stack base del boilerplate. Coolify-ready.
|
|
#
|
|
# REGLAS DE ORO:
|
|
# - Healthchecks usan `wget -qO-` o `curl -sf`, NUNCA `wget --spider` (issue I-008)
|
|
# - SIN labels Traefik manuales — Coolify v4 los autogenera del panel FQDN (issue I-009)
|
|
# - Servicios sin internet → `internal: true` en su network (regla D3)
|
|
# - `image:` tag explícito para que Coolify haga el proxy-network attach
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
services:
|
|
|
|
web:
|
|
build:
|
|
context: .
|
|
dockerfile: web/_default_fastapi_htmx/Dockerfile
|
|
image: 'wox-web:latest'
|
|
environment:
|
|
PUBLIC_HOST: ${PUBLIC_HOST:-localhost}
|
|
WXO_INSTANCE_URL: ${WXO_INSTANCE_URL:-}
|
|
WXO_API_KEY: ${WXO_API_KEY:-}
|
|
WXO_AGENT_ID: ${WXO_AGENT_ID:-}
|
|
IBM_CLOUD_IAM_URL: ${IBM_CLOUD_IAM_URL:-https://iam.cloud.ibm.com/identity/token}
|
|
TRACE_SINK: ${TRACE_SINK:-sqlite}
|
|
TRACES_DB_PATH: /data/traces.db
|
|
volumes:
|
|
- web_data:/data
|
|
restart: unless-stopped
|
|
expose: ["8000"]
|
|
labels:
|
|
# Coolify Traefik — solo el toggle + network. NUNCA routers manuales.
|
|
- "traefik.enable=true"
|
|
- "traefik.docker.network=coolify"
|
|
networks:
|
|
- coolify
|
|
- internal
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-qO-", "http://localhost:8000/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
|
|
# ─── (Ejemplo) mock externo — descomentá y duplicá según necesites ─────────
|
|
# example_mock:
|
|
# build:
|
|
# context: .
|
|
# dockerfile: mocks/_example_mock/Dockerfile
|
|
# image: 'wox-example-mock:latest'
|
|
# environment:
|
|
# BASE_URL: http://example_mock:8000
|
|
# expose: ["8000"]
|
|
# restart: unless-stopped
|
|
# networks:
|
|
# - internal
|
|
# healthcheck:
|
|
# test: ["CMD", "wget", "-qO-", "http://localhost:8000/health"]
|
|
# interval: 30s
|
|
# timeout: 5s
|
|
# retries: 3
|
|
|
|
# ─── (Ejemplo) backend propio FastAPI ──────────────────────────────────────
|
|
# backend:
|
|
# build:
|
|
# context: .
|
|
# dockerfile: backend/Dockerfile
|
|
# image: 'wox-backend:latest'
|
|
# environment:
|
|
# DATABASE_URL: ${DATABASE_URL:-sqlite:///data/app.db}
|
|
# WXO_BACKEND_TOKEN: ${WXO_BACKEND_TOKEN}
|
|
# WEBHOOK_SECRET: ${WEBHOOK_SECRET}
|
|
# volumes:
|
|
# - backend_data:/data
|
|
# expose: ["8000"]
|
|
# restart: unless-stopped
|
|
# networks:
|
|
# - coolify # si necesita ser accesible para WxO
|
|
# - internal
|
|
# healthcheck:
|
|
# test: ["CMD", "curl", "-sf", "http://localhost:8000/health"]
|
|
# interval: 30s
|
|
# timeout: 5s
|
|
# retries: 3
|
|
|
|
volumes:
|
|
web_data:
|
|
# backend_data:
|
|
|
|
networks:
|
|
coolify:
|
|
external: true
|
|
internal:
|
|
driver: bridge
|
|
internal: false # cambiar a true en producción si no necesitan acceso a internet
|