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:
- Contaminación de la ventana de contexto (200K tokens compartidos entre proyectos no relacionados)
- Sin aislamiento de proyectos (el código de msolution se filtra en los prompts de citadel)
- Sin capacidad multi-usuario (no se puede invitar a un diseñador al chat de un proyecto)
- Contexto de respuesta roto (responder a un mensaje del proyecto incorrecto = caos)
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
- 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.
- Multi-usuario desde el inicio — no es una "funcionalidad futura", es una base. Sin ello Arc OS no puede convertirse en un producto.
- 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
- Servicio Bun/Node.js ligero (~300 líneas)
- Telegram Bot API (long-polling)
- Lee
config/bot_registry.jsonpara el registro de hijos - Endpoint de health HTTP:
/api/master/health - Contenedor Docker en compose compartido
Lo que NO ES el Master Bot
- NO es una sesión Claude (sin IA, sin llamadas LLM)
- NO es un proxy de mensajes (no reenvía mensajes a los hijos)
- NO es un almacén de estado (lee el estado de los archivos de los hijos)
Protocolo del Child Bot
Cada child bot debe:
- Registrarse en
config/bot_registry.jsonal arrancar - Enviar heartbeat (cada 60s) al Master via archivo:
state/heartbeat_<name>.json - Manejar
reply_to_message→ inyección de CONTEXT GSD - Guardar los últimos 50 mensajes en
state/thread_history.json - Responder a la señal de emergency-stop (Ctrl+C graceful → /exit → kill)
- Usar el logger estructurado (
shared/logger.ts) — logs en/var/log/citadel/<name>/ - Aceptar la variable de entorno
BOT_NAMEpara nombrado dinámico - Exponer
/api/child/healthpara 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
- Bot Telegram Bun + TypeScript (long-polling)
config/bot_registry.json— registro de hijos- Comandos:
/status,/emergency-stop,/list,/health - Contenedor Docker en
docker/docker-compose.yml - Endpoint de health:
/api/master/health - Sin IA, sin sesión Claude — orquestrador puro
20.2 — Protocolo del Child Bot (Primer Hijo)
- Definir protocolo de registro del child bot
- Middleware de mensajes:
reply_to_message→ inyección de CONTEXT GSD - Historial de hilo: últimos 50 mensajes en
state/thread_history.json - Protocolo de apagado graceful (reacciona a emergency-stop)
- Piloto: migrar
@citadel_v2_botde Canal Claude a bot personalizado - Heartbeat al Master (cada 60s via archivo)
20.3 — Motor de Onboarding (HECHO)
/new_project <name>— entrevista interactiva de 4 pasos- Coincidencia de skills (registro + library), detección de blueprints
- Auto-provisioning: directorios, CLAUDE.md, MANIFEST.md, .env, registro, tmux
20.4 — Skill Library y Eliminación de Proyectos (HECHO)
/remove_project <name>— triple confirmación + nombres protegidos- Skills de biblioteca auto-coincidentes y copiados durante el onboarding
- Hook de recarga de registro para actualizaciones en memoria
20.5 — Infraestructura Phantom-Ready (HECHO)
shared/logger.ts— logging estructurado JSONL, división diaria de archivosshared/vault.ts— secretos cifrados AES-256-GCM (tokens en vault, no en .env)master-bot/watchdog.ts— monitor auto-curativo con backoff exponencial- Comando
/watchdogpara estado de hijos en tiempo real - Config de logrotate + script de configuración VPS
- Todos los console.log → logger estructurado
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+)
- Multi-tenancy SaaS (JWT, facturación Stripe)
- Dashboard web alternativo a Telegram
- Comandos de voz via Telegram
- Editor de sprites de agentes y personalización de la oficina
- Mecanismo de rotación de claves del vault
- Monitoreo de health entre múltiples VPS
Arquitectura Fase 20 por Rick (Arquitecto Principal). Fases 20.1–20.5 completas. Aprobado por CEO 2026-04-02.