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

6.9 KiB
Raw Permalink Blame History

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?"

  • (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.