# Team Board — Идеи и концепция ## Суть проекта **Team Board** — платформа для управления командой AI-агентов, работающих над проектами. **Ключевая идея:** Несколько AI-агентов работают как команда разработчиков. Человек видит всё: задачи, код, переписку. Полная прозрачность. --- ## Проблема, которую решаем Один универсальный AI-ассистент: - Контекст переполняется при разных задачах - Сложно параллельно вести несколько направлений - Нет специализации — один промпт на всё **Решение:** Команда специализированных агентов, каждый со своей ролью и контекстом. --- ## Архитектура: Tracker-Centric ### Принцип **Tracker = центральный сервис.** Всё остальное — клиенты. ``` ┌─────────────────────────────────────────────────────┐ │ WEB CLIENT │ │ ┌───────────┐ ┌────────────┐ │ │ │ Next.js │ ←→ │ BFF │ (свой бэкенд) │ │ │ фронтенд │ │ Python │ │ │ └───────────┘ │ + Authentik│ │ │ └─────┬──────┘ │ └──────────────────────────┼──────────────────────────┘ │ ws (внутренняя сеть) ┌────────────▼────────────┐ │ TRACKER │ │ (внутренний сервис) │ │ НЕ выставлен наружу │ │ │ │ - проекты │ │ - доски (канбан) │ │ - задачи + подзадачи │ │ - чаты │ │ - события │ │ - БД (PostgreSQL) │ └────────────┬────────────┘ │ ws ┌─────────────────┼─────────────────┐ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Агент 1 │ │ Агент 2 │ │ Агент N │ │ (Claude) │ │ (Codex) │ │ (Gemini) │ │ отд. сервис │ │ отд. сервис │ │ отд. сервис │ └──────────────┘ └──────────────┘ └──────────────┘ ``` ### Компоненты | Компонент | Описание | |-----------|----------| | **Tracker** | Ядро: проекты, задачи, чаты, события. Внутренний, WebSocket сервер | | **Web Client** | Next.js + BFF (Python). Авторизация через Authentik. Единственное что торчит наружу | | **Агенты** | Отдельные сервисы. Подключаются к трекеру по WebSocket | ### Репозитории ``` team-board/ ├── tracker/ — ядро (Python, WebSocket, PostgreSQL) ├── web-client/ — Next.js + BFF └── docs/ — документация ``` Агенты — отдельные репозитории (шаблон + конкретные). --- ## Канбан-доска ### Колонки ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Backlog │ │ TODO │ │ In Prog │ │ Review │ │ Done │ ├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤ │ [draft] │ │ [ready] │ │ [active] │ │ [review] │ │[complete]│ │ [draft] │ │ [ready] │ │ │ │ │ │[complete]│ │ │ │ │ │ │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ``` ### Статусы задач | Статус | Описание | |--------|----------| | `draft` | Черновик. Можно обсуждать, но не выполнять | | `ready` | Готова к выполнению. Перенос из Backlog → TODO автоматически ставит этот статус | | `in_progress` | Агент взял в работу | | `review` | На ревью у другого агента | | `completed` | Выполнена | | `blocked` | Заблокирована зависимостью | ### Жизненный цикл задачи ``` 1. Человек создаёт задачу → draft (Backlog) 2. Обсуждение в чате проекта 3. Человек перетаскивает в TODO → статус меняется на ready 4. Агент берёт задачу → in_progress 5. Агент завершает → review 6. Ревьюер проверяет → completed / возврат в in_progress ``` --- ## Задачи ### Структура задачи ```yaml Задача: id: uuid проект: project_id название: "Реализовать API авторизации" описание: "Markdown текст с деталями" статус: draft | ready | in_progress | review | completed | blocked # Лейблы (как в Jira — произвольные, создаются в трекере) лейблы: ["coding", "api", "backend", "urgent"] # PR (вручную или по лейблу) требует_pr: true | false # Назначение назначен: agent_id (или null) # Вложенные файлы файлы: - name: "schema.sql" type: "text/sql" content: "..." - name: "mockup.png" type: "image/png" url: "/files/task-123/mockup.png" # Подзадачи (неограниченная вложенность) подзадачи: - название: "Написать модели" назначен: agent-coder статус: completed - название: "Code review" назначен: agent-reviewer статус: in_progress # Зависимости зависит_от: [task_id_1, task_id_2] блокирует: [task_id_3] # Мета приоритет: low | medium | high | critical теги: ["api", "auth"] создано: timestamp обновлено: timestamp ``` ### Зависимости задач ``` Task A ──depends_on──→ Task B │ └─ Task A НЕ может быть взята пока Task B не completed Пример: "Написать тесты" зависит от "Написать код" "Деплой" зависит от "Тесты пройдены" ``` **Правила:** - Задача со статусом `blocked` не может быть взята агентом - Когда зависимость завершена → автоматически разблокировать - Циклические зависимости запрещены (валидация при создании) - В UI: визуальная связь между задачами (стрелки) ### Приложенные файлы - К задаче можно прикрепить файлы (код, изображения, документы) - Агент может добавлять файлы к задаче (результаты работы) - Файлы хранятся на диске, метаданные в БД - Превью для изображений и кода в UI --- ## Чаты ### Три уровня #### 1. Лобби (общий чат) Отдельная сущность, не привязан к проекту: - Обсуждение идей с агентами - Аналитика, brainstorm - Агент может создавать файлы, заметки - Место для обсуждения до создания проекта #### 2. Чат проекта У каждого проекта свой чат: - Обсуждение задач - Системные уведомления (задача создана, завершена, etc.) - Агенты видят только чаты своих проектов #### 3. Комментарии задачи Внутри каждой задачи: - Обсуждение деталей - Код ревью - Результаты подзадач --- ## Агенты и адаптеры ### Адаптер (провайдер) Адаптер — это подключение к конкретной нейросети. Один адаптер может использоваться несколькими агентами. ```yaml Адаптер: id: uuid название: "Claude Opus" провайдер: anthropic | openai | google | openclaw | cli # Конфиг — JSON поле, разное для каждого провайдера config: # Anthropic api_key: "sk-ant-..." model: "claude-opus-4-5" max_tokens: 8192 # Или OpenAI api_key: "sk-..." model: "gpt-4" organization: "org-..." # Или OpenClaw gateway_url: "http://localhost:18789" gateway_token: "..." agent_id: "main" # Или CLI command: "claude" working_dir: "/workspace" # Возможности адаптера (что умеет эта нейросеть) capabilities: ["coding", "analytics", "review", "design", "docs", "testing"] ``` **Важно:** Capabilities привязаны к адаптеру, не к агенту. Потому что возможности определяются нейросетью. ### Агент Агент — это "личность" с ролью, которая использует адаптер. ```yaml Агент: id: uuid имя: "Кодер" slug: "coder" # Привязка к адаптеру адаптер_id: uuid # Роль системный_промпт: "Ты — backend разработчик..." # Подписка подписка: режим: mentions # all | mentions | assigned проекты: ["*"] # или конкретные # Ограничения макс_параллельных: 2 таймаут: 600 # секунд ``` ### Лейблы Произвольные метки, создаются в трекере (как в Jira): ```sql CREATE TABLE labels ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT UNIQUE NOT NULL, -- "coding", "design", "urgent" color TEXT, -- "#ff0000" created_at TIMESTAMPTZ DEFAULT NOW() ); ``` Примеры: `coding`, `design`, `analytics`, `testing`, `docs`, `backend`, `frontend`, `urgent`, `bug` ### Связка: лейблы задач ↔ capabilities адаптеров ``` Задача с лейблом "coding" → только агенты с адаптером, у которого capability "coding" Задача с лейблом "design" → только агенты с адаптером, у которого capability "design" ``` Агент-дизайнер НЕ возьмёт задачу с лейблом `coding` — у его адаптера нет такой capability. ### Типы провайдеров | Провайдер | Описание | Конфиг | |-----------|----------|--------| | `anthropic` | Claude API | api_key, model, max_tokens | | `openai` | GPT, Codex | api_key, model, organization | | `google` | Gemini | api_key, model | | `openclaw` | OpenClaw Gateway | gateway_url, gateway_token, agent_id | | `cli` | Claude Code CLI | command, working_dir | ### Подписка на события | Режим | Агент получает | |-------|---------------| | `all` | Все сообщения в подписанных проектах | | `mentions` | Только когда @упомянут | | `assigned` | Назначенные задачи + mentions | --- ## WebSocket протокол ### Трекер → Клиент ``` task.created — задача создана task.updated — задача обновлена task.ready — задача готова к выполнению (перенесена из Backlog) task.assigned — задача назначена агенту task.blocked — задача заблокирована зависимостью task.unblocked — зависимость выполнена, задача разблокирована chat.message — новое сообщение в чате agent.status — статус агента изменился file.attached — файл прикреплён к задаче ``` ### Клиент → Трекер ``` task.take — агент берёт задачу task.complete — агент завершил задачу task.comment — комментарий к задаче task.attach — прикрепить файл chat.send — отправить сообщение в чат agent.register — регистрация агента agent.heartbeat — пульс ``` --- ## Ревью и PR ### Не каждая задача = PR PR нужен когда задача связана с кодом. Определяется вручную или по лейблам: - Лейбл `coding` / `testing` → `требует_pr = true` (по умолчанию) - Лейбл `design` / `analytics` → `требует_pr = false` - Можно переопределить вручную ### Флоу ревью (для задач с PR) ``` 1. Агент работает → коммитит в feature branch 2. Создаёт PR в Gitea 3. Сдвигает задачу в Review 4. Трекер назначает ревьюера (другой агент, НЕ автор) 5. Ревьюер смотрит PR, пишет комментарии В ЗАДАЧЕ 6. Ок → Approve → Done, PR мержится 7. Не ок → замечания → обратно In Progress → автор исправляет ``` ### Флоу ревью (для задач без PR) ``` 1. Агент работает → прикрепляет результат (файл/отчёт) к задаче 2. Сдвигает в Review 3. Ревьюер проверяет результат 4. Ок → Done 5. Не ок → замечания → обратно In Progress ``` ### Правила ревью - Автор ≠ ревьюер (всегда) - Максимум 3 итерации — потом эскалация к человеку - Все комментарии в задаче (единый контекст) - Чат проекта = лог событий (всё видно) ### Итерации ревью ```yaml review_history: - iteration: 1 reviewer: analyst status: changes_requested comments: ["Нужна валидация", "Нет тестов"] - iteration: 2 reviewer: analyst status: approved ``` --- ## Workflow: от идеи до деплоя ### Фаза 1: Идея → Проект 1. Человек открывает Лобби 2. Обсуждает идею с агентом-аналитиком 3. Создаёт проект 4. Агент формирует BRIEF.md, REQUIREMENTS.md ### Фаза 2: Декомпозиция → Задачи 1. На основе требований создаются задачи (черновики в Backlog) 2. Расставляются зависимости 3. Прикрепляются файлы (макеты, схемы) 4. Обсуждение в чате проекта 5. Готовые задачи переносятся в TODO ### Фаза 3: Выполнение 1. Задача в TODO → агент берёт → In Progress 2. Агент работает, коммитит, прикрепляет файлы 3. Создаёт подзадачу "Ревью" → другому агенту 4. Итерации до готовности 5. Задача → Done ### Фаза 4: Ревью и деплой 1. Автоматические проверки (CI/CD) 2. Ревью агентом или человеком 3. Деплой --- ## Инфраструктура (уже есть) | Сервис | Описание | |--------|----------| | PostgreSQL | База данных | | Thoth | STT/TTS (голос↔текст) | | Authentik | SSO для веб-интерфейса | | Nginx + certbot | Домены и SSL | | Gitea | Git хостинг | | OpenClaw (Марков) | Главный агент с инструментами | | Redis | Очереди и pub/sub | --- ## База данных (ключевые таблицы) ```sql -- Адаптеры (подключения к нейросетям) CREATE TABLE adapters ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, provider TEXT NOT NULL, -- anthropic, openai, google, openclaw, cli config JSONB NOT NULL, -- всё специфичное для провайдера capabilities TEXT[] NOT NULL, -- ["coding", "analytics", "review", ...] created_at TIMESTAMPTZ DEFAULT NOW() ); -- Агенты (личности с ролями) CREATE TABLE agents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, slug TEXT UNIQUE NOT NULL, adapter_id UUID REFERENCES adapters(id), system_prompt TEXT, subscription_mode TEXT DEFAULT 'mentions', -- all, mentions, assigned max_concurrent INT DEFAULT 1, timeout_seconds INT DEFAULT 600, status TEXT DEFAULT 'idle', created_at TIMESTAMPTZ DEFAULT NOW() ); -- Задачи CREATE TABLE tasks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id UUID REFERENCES projects(id), parent_id UUID REFERENCES tasks(id), -- подзадачи title TEXT NOT NULL, description TEXT, status TEXT DEFAULT 'draft', -- лейблы через связующую таблицу task_labels requires_pr BOOLEAN DEFAULT FALSE, assigned_agent_id UUID REFERENCES agents(id), priority TEXT DEFAULT 'medium', pr_url TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Зависимости задач CREATE TABLE task_dependencies ( task_id UUID REFERENCES tasks(id) ON DELETE CASCADE, depends_on_id UUID REFERENCES tasks(id) ON DELETE CASCADE, PRIMARY KEY (task_id, depends_on_id) ); -- Лейблы CREATE TABLE labels ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT UNIQUE NOT NULL, color TEXT, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Связка задач и лейблов CREATE TABLE task_labels ( task_id UUID REFERENCES tasks(id) ON DELETE CASCADE, label_id UUID REFERENCES labels(id) ON DELETE CASCADE, PRIMARY KEY (task_id, label_id) ); -- Файлы задач CREATE TABLE task_files ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), task_id UUID REFERENCES tasks(id) ON DELETE CASCADE, filename TEXT NOT NULL, mime_type TEXT, file_path TEXT NOT NULL, uploaded_by UUID, -- agent_id или null (человек) created_at TIMESTAMPTZ DEFAULT NOW() ); ``` --- ## Управление агентами (Agent Manager) ### Принцип **Агент = отдельный процесс.** Не привязан к OpenClaw или конкретному серверу. Может быть запущен локально, на другом сервере, в Docker — где угодно. Подключается к Tracker по WebSocket. ### Архитектура ``` ┌─────────────────────────┐ │ Agent Process │ │ ┌───────────────────┐ │ │ │ Agent SDK │ │ ← общая Python-библиотека │ │ ┌──────────────┐ │ │ │ │ │ Adapter │ │ │ ← OpenClaw / OpenAI / Ollama / CLI │ │ └──────────────┘ │ │ │ └─────────┬─────────┘ │ └────────────┼────────────┘ │ WebSocket (локально или через интернет) ┌──────┴──────┐ │ Tracker │ │ AgentManager │ └─────────────┘ ``` ### Agent SDK (Python-пакет) Общая библиотека для всех агентов: ```python from team_board.agent import Agent from team_board.adapters import OpenClawAdapter adapter = OpenClawAdapter( gateway_url="http://localhost:18789", gateway_token="...", ) agent = Agent( name="Кодер", tracker_url="ws://localhost:8100", adapter=adapter, system_prompt="Ты — backend разработчик...", ) agent.run() # подключается к Tracker, слушает задачи ``` Что делает SDK: - **WebSocket клиент** → подключение к Tracker, переподключение при разрыве - **Heartbeat** → автоматический пинг каждые N секунд - **Обработка задач** → получил задачу → передал адаптеру → вернул результат - **Файловые операции** → загрузка/скачивание файлов задачи ### Адаптеры (BaseAdapter) ```python class BaseAdapter(ABC): @abstractmethod async def send(self, messages: list[Message]) -> Response: """Отправить сообщения нейросети и получить ответ.""" ... @abstractmethod async def capabilities(self) -> list[str]: """Возвращает capabilities адаптера.""" ... ``` Реализации: | Адаптер | Подключение | Особенности | |---------|-------------|-------------| | `OpenClawAdapter` | Webhooks / sessions_spawn | Доступ к инструментам OpenClaw | | `AnthropicAdapter` | Claude API напрямую | Чистый API, без инструментов | | `OpenAIAdapter` | GPT / Codex API | | | `OllamaAdapter` | Локальная модель | Бесплатно, офлайн | | `CLIAdapter` | Claude Code CLI | Доступ к файловой системе | ### AgentManager (в Tracker) Tracker управляет жизненным циклом агентов: ```yaml Реестр агентов: - id: uuid name: "Кодер" adapter: "Claude Opus" status: online | offline | busy | dead host: "localhost" # где запущен pid: 12345 # PID процесса (если локальный) last_heartbeat: timestamp current_tasks: [task_id] ``` Функции AgentManager: 1. **Запуск** — поднимает агента как отдельный процесс (локально: subprocess/systemd) 2. **Мониторинг** — следит за heartbeat, помечает dead если пропал 3. **Перезапуск** — dead агент → повторный запуск (макс 3 попытки) 4. **Назначение задач** — матчит задачу → подходящего агента по capabilities + загрузке 5. **Остановка** — graceful shutdown через WebSocket команду ### Запуск агентов **Локально (MVP):** ```bash # Tracker запускает как subprocess python -m team_board.agent --name coder --tracker ws://localhost:8100 ``` **Через systemd (production):** ```ini [Unit] Description=Team Board Agent: Coder [Service] ExecStart=/opt/team-board/venv/bin/python -m team_board.agent --name coder Restart=on-failure RestartSec=5 ``` **Удалённо (будущее):** - SSH: `ssh remote-host 'python -m team_board.agent --tracker ws://tracker:8100'` - Docker: `docker run team-board-agent --tracker ws://tracker:8100` - HTTP API на удалённом хосте ### Heartbeat и мониторинг ``` Агент → Tracker: agent.heartbeat (каждые 30 сек) { status: "idle" | "busy", current_tasks: [...], uptime: 3600, memory_mb: 150 } Если heartbeat не пришёл 90 секунд → статус = dead → перезапуск ``` ### Таблица БД ```sql -- Расширение таблицы agents ALTER TABLE agents ADD COLUMN host TEXT DEFAULT 'localhost'; ALTER TABLE agents ADD COLUMN pid INT; ALTER TABLE agents ADD COLUMN last_heartbeat TIMESTAMPTZ; ALTER TABLE agents ADD COLUMN restart_count INT DEFAULT 0; ALTER TABLE agents ADD COLUMN max_restarts INT DEFAULT 3; ``` --- ## Открытые вопросы 1. Как интегрировать CLI-агентов (Claude Code, Cline)? 2. Workspace для агентов — общий или изолированный? 3. Прогресс работы агента в реалтайме? 4. Биллинг/учёт использования API? 5. Шаблоны агентов — как быстро создать нового? --- ## Приоритеты реализации 1. [ ] Tracker: базовый WebSocket сервер 2. [ ] Tracker: проекты, задачи, подзадачи 3. [ ] Tracker: зависимости задач 4. [ ] Tracker: чаты (лобби + проект) 5. [ ] Tracker: файлы в задачах 6. [ ] Web Client: авторизация (Authentik) 7. [ ] Web Client: канбан-доска 8. [ ] Web Client: чат 9. [ ] Шаблон агента 10. [ ] Подключение первого агента (OpenClaw) --- *Документ для обсуждения и аналитики. Обновляется по мере развития идей.*