Phase 20: Федеративная архитектура ботов
Arc OS — от "одного офиса" к "командному центру для всех проектов" Автор: Rick (Lead Architect) | Дата: 2026-04-02 Статус: 20.1–20.5 COMPLETE Одобрено: CEO
Проблема
CEO управляет несколькими проектами (Arc OS, Msolution, RTS_001) с телефона. Текущая архитектура: один Telegram-бот → одна Claude-сессия → одно контекстное окно. При 3+ проектах это ломается:
- Загрязнение контекстного окна (200K токенов между несвязанными проектами)
- Нет изоляции проектов (код msolution утекает в prompts citadel)
- Нет мультипользовательских возможностей (нельзя пригласить дизайнера в чат проекта)
- Контекст ответов сломан (ответить на сообщение из другого проекта = хаос)
Решение: Федерация
CEO ↔ @citadel_master_bot (Master) ← только глобальные команды
│
├── /status → опрашивает всех дочерних
├── /emergency-stop → kill signal для всех
├── /deploy all → каскадный деплой
│
├── @citadel_v2_bot (Child 1) ← отдельный чат, отдельный контекст
│ └── Claude session #1, cwd=/opt/repos/citadel-v2
│
├── @msolution_bot (Child 2) ← можно добавить дизайнера в чат
│ └── Claude session #2, cwd=/opt/repos/msol
│
└── @rts_bot (Child 3) ← можно добавить агента Morty
└── Claude session #3, cwd=/opt/repos/rts-001
Анализ решений: Single Bot vs Federation
Вариант A: Single Bot + Project Switcher
| Критерий | Оценка | Детали |
|---|---|---|
| Сложность кода | Низкая (1 бот) | Добавить переменную activeProject, /switch меняет cwd |
| Изоляция контекста | СЛАБАЯ | Одна Claude-сессия = одно контекстное окно для всех проектов. Переключение загрязняет контекст. |
| Удобство для CEO | Среднее | Нужно помнить /switch. Риск: отправить задачу не в тот проект. Нет визуального разделения. |
| Мультипользователь | НЕВОЗМОЖНО | Один чат = один CEO. Нельзя пригласить людей в проектный чат. |
| Контекст ответов | СЛОМАН | Ответить на сообщение из другого проекта = Claude запутается. |
Вердикт: Работает для одиночного CEO с 1-2 проектами. Ломается при 3+.
Вариант B: Федеративные боты (Master + Children) — ВЫБРАНО
| Критерий | Оценка | Детали |
|---|---|---|
| Сложность кода | Средняя (N+1 ботов) | Каждый бот = отдельная tmux + Claude сессия. Master = лёгкий координатор. |
| Изоляция контекста | ИДЕАЛЬНАЯ | Каждая Claude-сессия = своё контекстное окно, свой CLAUDE.md, свой cwd. Нулевое загрязнение. |
| Удобство для CEO | ВЫСОКОЕ | Отдельные чаты Telegram = отдельные "комнаты". Свайп между проектами. Нативный мобильный UX. |
| Мультипользователь | НАТИВНЫЙ | Добавить @designer в чат @msolution_bot. Она видит только свой проект. |
| Контекст ответов | ИДЕАЛЬНЫЙ | Ответить в чате @citadel_v2_bot = 100% контекст citadel. Telegram нативно сохраняет тред. |
Вердикт: Правильное решение. Больше инфраструктурной сложности, но решает ВСЕ проблемы.
Почему федерация побеждает
- Изоляция контекста — решающий фактор. Одна Claude-сессия для 3+ проектов = переполнение контекста за 30 минут активной работы. Федерация даёт каждому проекту чистые 200K токенов.
- Готовность к мультипользователю — не "будущая фича", а фундамент. Без неё Arc OS не может стать продуктом.
- Reply = нативный RAG — Telegram уже решил проблему контекста. Мы просто маппим reply → GSD prompt.
Архитектура Emergency Stop
CEO нажимает /emergency-stop в чате Master
│
▼
Master Bot (Node.js/Bun, легковесный, НЕ Claude-сессия)
│
├── 1. Читает config/bot_registry.json
│ { "children": [
│ { "name": "citadel-v2", "tmux": "citadel", ... },
│ { "name": "msolution", "tmux": "msolution", ... }
│ ]}
│
├── 2. Для каждого дочернего (параллельно):
│ a) tmux send-keys -t $SESSION "C-c" Enter ← graceful: Ctrl+C
│ b) sleep 2
│ c) tmux send-keys -t $SESSION "/exit" Enter ← явный выход
│ d) sleep 2
│ e) tmux kill-session -t $SESSION ← принудительное завершение если ещё жив
│
├── 3. Обновить office-state.json: все агенты → idle
│
└── 4. Ответить в чат Master:
"EMERGENCY STOP executed.
citadel-v2: STOPPED (was: working on hooks)
msolution: STOPPED (was: idle)
All agents reset to idle."
Kill Protocol (3 уровня)
| Уровень | Действие | Таймаут | Когда |
|---|---|---|---|
| 1. Graceful | Ctrl+C через tmux |
2с | Всегда первым |
| 2. Explicit | команда /exit |
2с | Если graceful не сработал |
| 3. Force | tmux kill-session |
немедленно | Последнее средство |
Failsafe
Cron-задача каждые 5 минут проверяет /tmp/emergency-stop.flag. Если файл существует и свежий (<10 мин), выполняет kill-последовательность. Покрывает случай, когда Master Bot сам упал.
Smart Context Recall
Проблема
CEO отвечает на сообщение 3-дневной давности и пишет "сделай то же самое, но для другого модуля". Claude понятия не имеет о referenced сообщении.
Решение: Reply → GSD Prompt Transformation
Telegram Bot API предоставляет объект reply_to_message с полным оригинальным текстом.
CEO отвечает на: "Я задеплоил хуки на VPS, всё работает"
CEO пишет: "сделай то же для msolution"
│
▼
Child Bot получает:
{
"message": {
"text": "сделай то же для msolution",
"reply_to_message": {
"text": "Я задеплоил хуки на VPS, всё работает",
"date": 1743580800,
"message_id": 847
}
}
}
│
▼
Бот строит GSD prompt для Claude:
┌─────────────────────────────────────┐
│ CONTEXT (from reply): │
│ > [2026-04-02] "Я задеплоил хуки │
│ > на VPS, всё работает" │
│ │
│ TASK (new message): │
│ "сделай то же для msolution" │
│ │
│ PROJECT: msolution (from bot scope) │
└─────────────────────────────────────┘
Deep Recall (более старые сообщения)
Слой 1: Thread History (быстрый)
Бот хранит последние 50 сообщений в state/thread_history.json для каждого чата.
Reply → бот находит оригинал → вставляет в блок CONTEXT.
Слой 2: Library Recall (fallback)
Если сообщения нет в thread history (>50 сообщений назад) →
бот запускает /citadel-recall с текстом reply →
подтягивает контекст из library-export/ → вставляет в prompt.
Флоу: reply_to_message → thread_history → library-export/ → GSD prompt
Ключевой принцип
Claude НИКОГДА не знает о Telegram reply напрямую. Middleware бота ВСЕГДА трансформирует reply в чистый блок CONTEXT + TASK перед отправкой в Claude-сессию.
Спецификация Master Bot
Что Master Bot ЯВЛЯЕТСЯ
- Лёгкий Bun/Node.js сервис (~300 строк)
- Telegram Bot API (long-polling)
- Читает
config/bot_registry.jsonдля реестра дочерних ботов - HTTP health endpoint:
/api/master/health - Docker-контейнер в shared compose
Что Master Bot НЕ ЯВЛЯЕТСЯ
- НЕ является Claude-сессией (нет AI, нет LLM-вызовов)
- НЕ является message proxy (не пересылает сообщения дочерним)
- НЕ является хранилищем состояния (читает состояние из файлов дочерних)
Протокол Child Bot
Каждый дочерний бот должен:
- Регистрироваться в
config/bot_registry.jsonпри запуске - Отправлять heartbeat (каждые 60с) в Master через файл:
state/heartbeat_<name>.json - Обрабатывать
reply_to_message→ вставку GSD CONTEXT - Хранить последние 50 сообщений в
state/thread_history.json - Реагировать на сигнал emergency-stop (graceful Ctrl+C → /exit → kill)
- Использовать структурированный logger (
shared/logger.ts) — логи в/var/log/citadel/<name>/ - Принимать env var
BOT_NAMEдля динамического именования - Открывать
/api/child/healthдля watchdog health checks
Оценка ресурсов
| Ресурс | Текущее | Phase 20 |
|---|---|---|
| VPS RAM | ~4GB используется / 11GB всего | ~5.5GB (+ ~500MB на дочернюю сессию) |
| Docker-контейнеры | 2 (bridge + frontend) | 4-5 (+ master + 2 дочерних) |
| Токены Telegram-ботов | 1 | 3-4 (@BotFather, бесплатно) |
| tmux-сессии | 1 (citadel) | 3-4 (master + дочерние) |
| Порты | 18889, 19200 | + 19201-19203 (child APIs) |
Подфазы Phase 20
20.1 — Основа Master Bot
- Telegram-бот Bun + TypeScript (long-polling)
config/bot_registry.json— реестр дочерних ботов- Команды:
/status,/emergency-stop,/list,/health - Docker-контейнер в
docker/docker-compose.yml - Health endpoint:
/api/master/health - Без AI, без Claude-сессии — чистый оркестратор
20.2 — Child Bot Protocol (первый дочерний)
- Определить протокол регистрации дочернего бота
- Message middleware:
reply_to_message→ вставка GSD CONTEXT - Thread history: последние 50 сообщений в
state/thread_history.json - Протокол graceful shutdown (реакция на emergency-stop)
- Пилот: мигрировать
@citadel_v2_botиз Claude Channel в кастомный бот - Heartbeat в Master (каждые 60с через файл)
20.3 — Onboarding Engine (DONE)
/new_project <name>— 4-шаговое интерактивное интервью- Сопоставление скиллов (реестр + библиотека), определение blueprint
- Авто-provisioning: директории, CLAUDE.md, MANIFEST.md, .env, реестр, tmux
20.4 — Библиотека скиллов и удаление проектов (DONE)
/remove_project <name>— тройное подтверждение + защищённые имена- Library-скиллы автоматически сопоставляются и копируются при онбординге
- Хук перезагрузки реестра для обновлений в памяти
20.5 — Phantom-Ready Infrastructure (DONE)
shared/logger.ts— структурированное логирование JSONL, ежедневное разбиение файловshared/vault.ts— зашифрованные AES-256-GCM секреты (токены в vault, не в .env)master-bot/watchdog.ts— self-healing монитор с экспоненциальным бэкоффом- Команда
/watchdogдля статуса дочерних ботов в реальном времени - Конфиг logrotate + скрипт настройки VPS
- Все console.log → структурированный logger
Команды Master Bot (финальные)
| Команда | Действие | Ответ |
|---|---|---|
/status |
Читает состояние + health + heartbeat всех дочерних | Агрегированный дашборд |
/emergency_stop |
3-уровневая kill-последовательность для всех дочерних | Подтверждение с per-child статусом |
/list |
Показать зарегистрированных дочерних | Имя, статус, tmux-сессия |
/deploy <name|all> |
Триггер деплоя для дочернего(их) | Лог деплоя на каждого |
/health |
Проверить health endpoints всех дочерних | Health matrix |
/new_project <name> |
Начать onboarding-интервью | 4-шаговый разговор |
/remove_project <name> |
Удалить проект с подтверждением | Тройное подтверждение + очистка |
/watchdog |
Показать статус watchdog | Ошибки на дочернего, перезапуски, бэкофф |
/cancel |
Отменить активную операцию | Прервать onboarding/удаление |
Вне скоупа (Phase 21+)
- SaaS мультитенантность (JWT, Stripe billing)
- Web-дашборд в качестве альтернативы Telegram
- Голосовые команды через Telegram
- Редактор спрайтов агентов и кастомизация офиса
- Механизм ротации ключей Vault
- МультиVPS мониторинг health партнёров
Архитектура Phase 20 от Rick (Lead Architect). Phases 20.1–20.5 завершены. Одобрено CEO 2026-04-02.