Files
fit-boilerplate-wox/docs/architecture-patterns.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

193 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Architecture Patterns
Árbol de decisión que usa el subagente `wxo-architect` cuando arrancás un
caso nuevo. Te llevo pregunta por pregunta.
---
## Pregunta 1 — ¿Cuántos dominios distintos toca el caso?
Un "dominio" = una superficie funcional bien delimitada (identidad,
operaciones, RRHH, finanzas, CRM, etc.).
- **01 dominio** → 1 agente solo. Salí del árbol con la **Topología Single**.
- **25 dominios** → N specialists + 1 orchestrator. **Topología Multi-Specialist** (estilo Cotemar).
- **6+ dominios** → 2 capas: sub-orchestrators temáticos. **Topología Multi-Capa**.
---
## Pregunta 2 — ¿El flujo es lineal o ramificado?
- **Lineal y conocido** (caso entra → A → B → C → D → resultado, siempre el mismo orden): aplicá **Patrón Meta-Tool** (estilo Dun). Una sola tool `run_full_case` que el backend orquesta internamente. El agente invoca esa tool y listo.
- **Ramificado** (el agente decide qué hacer según el input): N tools individuales, agente razona. Cuidado con `recursion_limit=30` (ver `known-issues.md`).
- **Mixto**: parte lineal en meta-tool, parte ramificada en tools individuales. Es lo más común en casos reales.
---
## Pregunta 3 — ¿Cada agente necesita razonar sobre procedimientos escritos?
Para cada agente, preguntate: "¿el LLM necesita citar un runbook para
decidir bien?"
- **Sí** (procedural): este agente tiene **KB con runbooks**. Estilo
Cotemar AD specialist.
- **No** (API-driven): este agente **no tiene KB**. El system prompt
describe qué hace, las tools describen las acciones disponibles.
Estilo Dun QA Studio.
- **Mixto**: KB para el "qué" + tools para el "cómo". Solo cuando los
procedimientos son largos y variables.
---
## Pregunta 4 — ¿Qué tipo de tools va a tener cada agente?
Por cada dominio, elegí el tipo de tool:
### Opción A — OpenAPI (preferido si tenés backend propio)
**Cuándo:** tu solución incluye un backend (FastAPI, Express, lo que sea)
que ya define endpoints REST.
**Pros:**
- Una sola fuente de verdad (el spec)
- ADK importa todo en un comando
- Cambios al backend = re-import del spec, no toques YAML de tool
**Pattern del template (estilo Dun):**
- Backend expone `/orchestrate-tools-spec.json` (endpoint filtrado)
- Filtra el openapi.json a una allowlist `PUBLIC_TOOLS`
- Fuerza `description` y `security` per-operation
- Patch del `servers[0].url` en deploy time según env
Ver `wxo/tools/openapi/_backend_filter_endpoint.py` para el template.
### Opción B — Python `@tool` (preferido para mocks/PoC)
**Cuándo:** estás prototipando, mocks externos, lógica simple por tool,
sin backend que valga la pena mantener.
**Pros:**
- Rápido de escribir, una función = una tool
- Fácil de testear con pytest
- Bajo overhead
**Pattern del template (estilo Cotemar):**
- Una función `@observable_tool(name="x")` por endpoint mockeado
- Lee `BASE_URL` del environment de su connection
- `requests.post(...)` y devuelve dict
- `_compat.py` inline al inicio del archivo
Ver `wxo/tools/python/_template_tools.py`.
### Opción C — MCP (preferido si el sistema lo expone)
**Cuándo:** el sistema externo (HubSpot, Outline, una DB con MCP server,
GitHub vía MCP, etc.) ya expone un MCP server.
**Pros:**
- Trae types + permisos del sistema
- Mantenido por el vendor
- Una sola connection MCP da acceso a todas las tools del server
**Pattern del template:**
- Una `connection.yaml` de tipo MCP apuntando al server
- ADK descubre las tools y las hace disponibles al agente
- Ver `wxo/tools/mcp/_template_mcp_connection.yaml`
### Decisión
| Situación | Recomendación |
|---|---|
| Es PoC, mocks externos | Python @tool |
| Tengo backend propio (FastAPI/Express) | OpenAPI |
| Conecto a SaaS con MCP server | MCP |
| Conecto a SaaS sin MCP server | OpenAPI (escribís el spec a mano) o Python |
| Mezcla | Cada agente puede usar más de uno |
---
## Pregunta 5 — ¿Web layer: cuál stack?
Dos happy-paths probados:
### Stack A — FastAPI + HTMX + Jinja (default)
**Cuándo:** demos, PoCs, control planes, kanbans, paneles operativos
**Pros:** SSR, sin build step, polling con `hx-trigger` es trivial,
una sola persona la mantiene
**Contras:** menos interactivo, menos componibilidad
**Origen:** estilo Cotemar (UNUS Kanban + Control Plane)
### Stack B — FastAPI + React + Vite + Tailwind + zustand
**Cuándo:** app productiva con varios usuarios, mucha interacción, UI rica
**Pros:** ecosistema React, lazy loading, state management decente
**Contras:** build step, más superficie de mantenimiento
**Origen:** estilo Dun (QA Studio)
### Decisión
- **Demo / interno / PoC** → Stack A
- **Producción / multi-usuario / app rica** → Stack B
- **Híbrido** → Stack A para dashboards, Stack B para la app principal,
unidos por reverse proxy
El template trae Stack A en `web/_default_fastapi_htmx/`. Stack B viene
documentado pero no implementado (el subagente Claude `web-layer-builder`
te lo arma según el caso).
---
## Pregunta 6 — ¿Deploy: dónde corre esto?
Tres opciones soportadas:
| Target | Para qué | Ver |
|---|---|---|
| **Coolify** (FIT default) | Demos + PoCs productivos en `*.fitlabs.dev` | `docs/deployment-guide.md` |
| **Docker compose local** | Dev / testing | `docs/INSTRUCCIONES.md` |
| **K8s / Cloud Run / otro** | Producción del cliente | `docs/deployment-guide.md` § "Other targets" |
---
## Topologías resultantes
### Topología Single (1 agente)
```
[user] → [agente único] ──tools──→ [sistema externo]
└──KB──→ [opcional]
```
### Topología Multi-Specialist (Cotemar pattern)
```
┌──→ ad_specialist ──tools──→ AD
[user] → [N1] ────┼──→ ops_specialist ──tools──→ Ops
(orch) └──→ rrhh_specialist ──tools──→ HR
└─escalate→ runbook 03 (KB propia)
```
### Topología Meta-Tool (Dun pattern)
```
[user] → [agente único] ──run_full_case(id)──→ [backend orquesta:
step 1, step 2, ...
write_audit cada paso]
```
### Topología Multi-Capa (>5 dominios)
```
┌─→ [sub-orch identidad] ─→ ad, hr, vendors
[user] → [super-orch] ────┤
├─→ [sub-orch ops] ─→ dynatrace, k8s, db
└─→ [sub-orch finanzas] ─→ sap, billing
```
---
## Cuando dudes
- **¿1 agente o varios?** → Si los dominios son disjuntos, varios. Si todo es del mismo dominio, uno.
- **¿KB o no?** → Si hay procedimiento escrito que el LLM debe seguir literal, sí. Si no, no.
- **¿OpenAPI o Python?** → ¿Tenés backend? OpenAPI. ¿Mocks? Python.
- **¿Meta-tool o tools sueltas?** → ¿El flujo es lineal y conocido? Meta-tool. ¿El agente decide? Sueltas.
Cuando dudes, **arrancá con menos**. Es más fácil splittear un agente en
dos que mergear dos en uno.