Saltar a contenido

ADR-015 · Claudia v2 — arquitectura (rewrite + HTTP MCP + merge con cis-inbox)

Fecha: 2026-04-22 Source: /srv/projects/cis/cis-plan/DECISIONS.md (do not edit here — re-split desde la fuente)


Mergeado 2026-04-29 desde ADRs-borrador-013-015-016.md (P0.3). Numeración renumerada 2026-04-27 (era ADR-011 en el borrador; ese número fue tomado por Contabilidad in-house). Saltamos ADR-014 que ya está mergeado (consolidación user canon).

Contexto

cis-claudia v1 ya existe en /srv/projects/cds/cis/cis-claudia/:

  • Backend FastAPI :8172 (2 workers). Frontend Next.js :8158.
  • Brain (Tier 1): Claude Code CLI subprocess con MCP server (claudia_mcp_server.py, 9 tools: send_messages, stay_silent, create_task, save_memory, relay_message, schedule_continuation, improve_self, check_services, send_email). Transport: stdio (JSON lines, Claude Code 2.x).
  • Deep Session (Tier 2): Claude Code subprocess con illanes00-server MCP (69 tools infra).
  • Pipeline WhatsApp webhook → brain.
  • Mind git-versioned (personalidades Big Five, skills, pipelines).

CONTRACTS.md marca el MCP stdio como ⚪ propuesto y hoy stale: - Fila cis-core → Claudia (futuro): "Stdio path hoy stale. Pasar a HTTP MCP." - Fila cis-inbox → cis-claudia: "Pendiente implementar tools read_thread, draft_reply."

Backlog Bloque 4 queda bloqueado por este ADR (parking-lot #5 en DECISIONS.md: "Claudia v2: fork o rewrite?").

Consideración adicional: hoy el usuario habla con Claudia por WhatsApp pero lee sus correos en cis-inbox. El hop mental "¿dónde hablé con Claudia de X?" es ruidoso. Si Claudia vive dentro de la UI de inbox, unifica contexto.

Alternativas consideradas

  1. (a) Fork v1 + extender
  2. Preservar el código actual, seguir extendiendo.
  3. Pro: menor trabajo inmediato, no rompe lo que funciona.
  4. Contra: el stdio MCP no escala a multi-user (cada sesión spawnea subprocess, gestionar N concurrentes es frágil). La arquitectura WhatsApp-centric limita UX web. El código v1 carga mucho subprocess.spawn → decisiones en el subprocess que cuestan $$ por cada msg (contrario a ADR-002).

  5. (b) Rewrite + HTTP MCP + merge con cis-inboxpropuesta

  6. Claudia vive dentro de inbox.innovacionsantiago.cl como un "thread especial" (thread_type=claudia_assistant). Frontend reusa la UI de hilos del inbox. MCP servers expuestos por HTTP (no stdio).
  7. Pipelines deterministas (ADR-002) son el primer tier: cada acción frecuente (agendar, buscar, emitir factura) es un skill Python puro invocable por nombre. El LLM solo decide qué skill invocar y redacta output humano.
  8. Tier arquitectónico:

    • Tier 0 — Skills catalog: Python puro, testeable, sin LLM. Un skill = una función con input/output tipado + audit.
    • Tier 1 — Brain (routing): LLM decide qué skill invocar y redacta respuesta. HTTP MCP expone skills como tools.
    • Tier 2 — Deep sessions: para tareas multi-step (ej. reconciliar un mes entero). Claude Code CLI subprocess sigue siendo válido acá pero aislado, no en el loop normal.
    • Tier 3 — WhatsApp: último, cuando los 3 tiers anteriores están sólidos en la UI web.
  9. (c) Wrapper sobre Claude.ai

  10. Embebido (iframe o similar), menos control.
  11. Pro: cero mantenimiento de brain infra.
  12. Contra: ToS de Anthropic limita automatización, no tenemos control sobre prompts/memory/skills, no podemos inyectar tools del ecosistema CIS (cis-core, cis-inbox).

Decisión propuesta

Opción (b): rewrite + HTTP MCP + merge con cis-inbox.

Razones:

  • Stdio MCP no escala — chat requiere sesiones concurrentes por usuario. HTTP MCP es el path ganando tracción en el ecosistema (ver cis-core CONTRACTS fila "MCP tools").
  • Merge con inbox elimina el hop mental — "hablé con Claudia" y "recibí un mail" son la misma UI. El usuario no cambia de contexto.
  • Pipelines deterministas primero (ADR-002 extendido) — skills catalog es testeable sin pagar API de Anthropic. El LLM es borde, no centro.
  • Extraer Claudia v1 de cis-admin es prerequisito de ADR-013 (rewrite admin). Si v2 vive en otro proceso (inbox-backend), cis-admin puede apagar sus 3 timers actuales (claudia-followup, heartbeat, pulse).

Roadmap (alineado con Backlog Bloque 4)

  1. Fase 1 — Skills catalog (2 semanas): Python puro en cis-claudia/backend/app/skills/. Primeros 10 skills (agenda, search_thread, draft_reply, emit_dte, status_service, etc.). Tests unitarios. Cada skill es invocable desde CLI (cis-claudia skill run agenda --date=tomorrow).
  2. Fase 2 — HTTP MCP (1 semana): FastAPI endpoint POST /mcp/call que expone los skills como tools MCP v1.0. Auth via cis-auth JWT (user Claudia talks to == authenticated user).
  3. Fase 3 — Tier Brain en inbox (2 semanas): thread type claudia_assistant en cis-inbox. Frontend cis-inbox/frontend/src/app/(inbox)/thread/[id]/claudia.tsx. Brain invoca HTTP MCP tools. Transcripts persisten en PG.
  4. Fase 4 — Deep sessions (1 semana): subprocess Claude Code aislado, corre en background, actualiza thread asincrónicamente.
  5. Fase 5 — WhatsApp reconnect (1 semana): webhook WhatsApp → crea mensaje en el thread de Claudia del usuario correspondiente. UI web y WhatsApp son dos clientes del mismo thread.

Consecuencias

  • Positivo: un solo lugar para conversar (inbox), un solo protocolo MCP (HTTP), skills testeables sin pagar API, v1 se apaga limpio.
  • Negativo: rewrite grande (5-7 semanas total). Durante la transición v1 (WhatsApp) y v2 (web) pueden coexistir — definir regla "ventana que gana" (quien respondió primero).
  • Compatibilidad: el frontend de Claudia v1 (Next :8158) queda deprecado; no se mantiene después de Fase 3.
  • Multi-tenant: el assistant_id scoping de v1 se mantiene — cada tenant puede tener su propia Claudia.
  • Dependencia de ADR-013: cis-admin necesita apagar sus timers de Claudia v1 cuando Fase 3 esté lista. Coordinar cutover.
  • Riesgo de mind/: la "personalidad" git-versioned de v1 se porta a v2 sin cambios (archivos markdown + YAML no dependen del transport).