Fase 20: Arquitectura de Bots Federados

Arc OS — de "una oficina" a "centro de comando para todos los proyectos" Autor: Rick (Arquitecto Principal) | Fecha: 2026-04-02 Estado: 20.1–20.5 COMPLETO Aprobado por: CEO


El Problema

El CEO gestiona múltiples proyectos (Arc OS, Msolution, RTS_001) desde un teléfono. Arquitectura actual: un bot de Telegram → una sesión Claude → una ventana de contexto. Esto se rompe con 3+ proyectos:

La Solución: Federación

CEO ↔ @citadel_master_bot (Master)          ← solo comandos globales
       │
       ├── /status          → hace polling a todos los hijos
       ├── /emergency-stop  → señal de kill a todos
       ├── /deploy all      → deploy en cascada
       │
       ├── @citadel_v2_bot (Hijo 1)          ← chat separado, contexto separado
       │    └── Sesión Claude #1, cwd=/opt/repos/citadel-v2
       │
       ├── @msolution_bot (Hijo 2)           ← puedes añadir al diseñador al chat
       │    └── Sesión Claude #2, cwd=/opt/repos/msol
       │
       └── @rts_bot (Hijo 3)                ← puedes añadir al agente Morty
            └── Sesión Claude #3, cwd=/opt/repos/rts-001

Análisis de Decisión: Bot Único vs Federación

Opción A: Bot Único + Selector de Proyectos

Criterio Valoración Detalles
Complejidad del código Baja (1 bot) Añadir variable activeProject, /switch cambia cwd
Aislamiento de contexto DÉBIL Una sesión Claude = una ventana de contexto para todos los proyectos. Cambiar contamina el contexto.
Comodidad del CEO Media Hay que recordar /switch. Riesgo: enviar tarea al proyecto incorrecto. Sin separación visual.
Multi-usuario IMPOSIBLE Un chat = un CEO. No se puede invitar a personas a un chat de ámbito de proyecto.
Contexto de respuesta ROTO Responder a mensaje de otro proyecto = Claude confundido.

Veredicto: Funciona para un CEO en solitario con 1-2 proyectos. Se rompe a partir de 3.

Opción B: Bots Federados (Master + Hijos) — ELEGIDA

Criterio Valoración Detalles
Complejidad del código Media (N+1 bots) Cada bot = tmux + sesión Claude separados. Master = coordinador ligero.
Aislamiento de contexto PERFECTO Cada sesión Claude = ventana de contexto propia, CLAUDE.md propio, cwd propio. Cero contaminación.
Comodidad del CEO ALTA Chats de Telegram separados = "salas" separadas. Desliza entre proyectos. UX móvil nativo.
Multi-usuario NATIVO Añade @designer al chat de @msolution_bot. Solo ve su proyecto.
Contexto de respuesta PERFECTO Responder en el chat de @citadel_v2_bot = 100% contexto de citadel. Telegram preserva el hilo de forma nativa.

Veredicto: Solución correcta. Más complejidad de infraestructura, pero resuelve TODOS los problemas.

Por Qué Gana la Federación

  1. Aislamiento de contexto — factor decisivo. Una sesión Claude para 3+ proyectos = desbordamiento de contexto en 30 minutos de trabajo activo. La federación le da a cada proyecto 200K tokens limpios.
  2. Multi-usuario desde el inicio — no es una "funcionalidad futura", es una base. Sin ello Arc OS no puede convertirse en un producto.
  3. Respuesta = RAG nativo — Telegram ya resolvió el problema de contexto. Solo mapeamos respuesta → prompt GSD.

Arquitectura de Emergency Stop

CEO toca /emergency-stop en el chat del Master
        │
        ▼
Master Bot (Node.js/Bun, ligero, NO es una sesión Claude)
        │
        ├── 1. Lee config/bot_registry.json
        │      { "children": [
        │          { "name": "citadel-v2", "tmux": "citadel", ... },
        │          { "name": "msolution", "tmux": "msolution", ... }
        │      ]}
        │
        ├── 2. Para cada hijo (en paralelo):
        │      a) tmux send-keys -t $SESSION "C-c" Enter      ← graceful: Ctrl+C
        │      b) sleep 2
        │      c) tmux send-keys -t $SESSION "/exit" Enter     ← salida explícita
        │      d) sleep 2
        │      e) tmux kill-session -t $SESSION                 ← force kill si sigue vivo
        │
        ├── 3. Actualiza office-state.json: todos los agentes → idle
        │
        └── 4. Responde al chat del Master:
               "EMERGENCY STOP executed.
                citadel-v2: STOPPED (was: working on hooks)
                msolution: STOPPED (was: idle)
                All agents reset to idle."

Protocolo de Kill (3 niveles)

Nivel Acción Timeout Cuándo
1. Graceful Ctrl+C via tmux 2s Siempre primero
2. Explícito comando /exit 2s Si el graceful no funcionó
3. Force tmux kill-session inmediato Último recurso

Failsafe

Cron job cada 5 minutos comprueba /tmp/emergency-stop.flag. Si el archivo existe y es reciente (<10 min), ejecuta la secuencia de kill. Cubre el caso de que el propio Master Bot haya fallado.


Recuperación de Contexto Inteligente

Problema

El CEO responde a un mensaje de hace 3 días y dice "haz lo mismo pero para otro módulo". Claude no tiene ni idea del mensaje referenciado.

Solución: Transformación Respuesta → Prompt GSD

La Telegram Bot API proporciona el objeto reply_to_message con el texto original completo.

CEO responde a: "Desplegué los hooks en VPS, todo funciona"
CEO escribe: "haz lo mismo para msolution"
        │
        ▼
Child Bot recibe:
{
  "message": {
    "text": "haz lo mismo para msolution",
    "reply_to_message": {
      "text": "Desplegué los hooks en VPS, todo funciona",
      "date": 1743580800,
      "message_id": 847
    }
  }
}
        │
        ▼
Bot construye prompt GSD para Claude:
┌─────────────────────────────────────┐
│ CONTEXT (de la respuesta):          │
│ > [2026-04-02] "Desplegué los hooks │
│ > en VPS, todo funciona"            │
│                                     │
│ TASK (nuevo mensaje):               │
│ "haz lo mismo para msolution"       │
│                                     │
│ PROJECT: msolution (del ámbito bot) │
└─────────────────────────────────────┘

Deep Recall (mensajes más antiguos)

Capa 1: Historial de Hilo (rápido)
  El bot guarda los últimos 50 mensajes en state/thread_history.json por chat.
  Respuesta → bot encuentra el original → inyecta en bloque CONTEXT.

Capa 2: Library Recall (fallback)
  Si el mensaje no está en el historial del hilo (>50 msgs atrás) →
  el bot ejecuta /citadel-recall con el texto de la respuesta →
  extrae contexto de library-export/ → inyecta en el prompt.

Flujo: reply_to_message → thread_history → library-export/ → prompt GSD

Principio Clave

Claude NUNCA sabe sobre las respuestas de Telegram directamente. El middleware del bot SIEMPRE transforma la respuesta en un bloque CONTEXT + TASK limpio antes de enviarlo a la sesión Claude.


Especificación del Master Bot

Lo que ES el Master Bot

Lo que NO ES el Master Bot

Protocolo del Child Bot

Cada child bot debe:

  1. Registrarse en config/bot_registry.json al arrancar
  2. Enviar heartbeat (cada 60s) al Master via archivo: state/heartbeat_<name>.json
  3. Manejar reply_to_message → inyección de CONTEXT GSD
  4. Guardar los últimos 50 mensajes en state/thread_history.json
  5. Responder a la señal de emergency-stop (Ctrl+C graceful → /exit → kill)
  6. Usar el logger estructurado (shared/logger.ts) — logs en /var/log/citadel/<name>/
  7. Aceptar la variable de entorno BOT_NAME para nombrado dinámico
  8. Exponer /api/child/health para health checks del watchdog

Estimación de Recursos

Recurso Actual Fase 20
RAM VPS ~4GB usada / 11GB total ~5,5GB (+ ~500MB por sesión de hijo)
Contenedores Docker 2 (bridge + frontend) 4-5 (+ master + 2 hijos)
Tokens de bot Telegram 1 3-4 (@BotFather, gratuito)
Sesiones tmux 1 (citadel) 3-4 (master + hijos)
Puertos 18889, 19200 + 19201-19203 (APIs de hijos)

Sub-Fases de la Fase 20

20.1 — Fundación del Master Bot

20.2 — Protocolo del Child Bot (Primer Hijo)

20.3 — Motor de Onboarding (HECHO)

20.4 — Skill Library y Eliminación de Proyectos (HECHO)

20.5 — Infraestructura Phantom-Ready (HECHO)

Comandos del Master Bot (Final)

Comando Acción Respuesta
/status Lee estado + health + heartbeat de todos los hijos Dashboard agregado
/emergency_stop Secuencia de kill de 3 niveles en todos los hijos Confirmación con estado por hijo
/list Muestra hijos registrados Nombre, estado, sesión tmux
/deploy <name|all> Dispara deploy para hijo(s) Log de deploy por hijo
/health Comprueba los endpoints de health de todos los hijos Matriz de health
/new_project <name> Inicia entrevista de onboarding Conversación de 4 pasos
/remove_project <name> Elimina proyecto con confirmación Triple confirmación + limpieza
/watchdog Muestra estado del watchdog Fallos, reinicios, backoff por hijo
/cancel Cancela la operación activa Abortar onboarding/eliminación

Fuera del Alcance (Fase 21+)


Arquitectura Fase 20 por Rick (Arquitecto Principal). Fases 20.1–20.5 completas. Aprobado por CEO 2026-04-02.