426 lines
25 KiB
Markdown
426 lines
25 KiB
Markdown
# Team Board — Архитектура
|
||
Версия: 0.3 (драфт)
|
||
Дата: 2026-02-21
|
||
|
||
## Что это
|
||
|
||
Платформа для совместной работы людей и AI-агентов над проектами. Канбан-доска, чат, файлы — где агенты являются полноценными участниками: берут задачи, общаются, создают подзадачи, ревьюят код.
|
||
|
||
**Ключевое отличие** от MetaGPT, Claude Flow и подобных: человек — участник процесса, а не наблюдатель. Всё происходит на человеческом языке, в прозрачном чате.
|
||
|
||
## Компоненты
|
||
|
||
```
|
||
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
|
||
│ Web Client │────▶│ BFF │────▶│ Tracker │
|
||
│ (Next.js) │ │ (FastAPI) │ │ (FastAPI) │
|
||
└─────────────┘ └──────────────┘ └──────┬───────┘
|
||
│
|
||
┌────────────────────────────────────────┤
|
||
│ │ │ │
|
||
┌────▼────┐ ┌────▼────┐ ┌────▼────┐ ┌──▼───┐
|
||
│Picogent │ │Picogent │ │Telegram │ │ DB │
|
||
│ Кодер │ │Архитект │ │ Bridge │ │Pg+Red│
|
||
└─────────┘ └─────────┘ └─────────┘ └──────┘
|
||
```
|
||
|
||
| Компонент | Стек | Порт | Описание |
|
||
|-----------|------|------|----------|
|
||
| **Tracker** | Python, FastAPI, SQLAlchemy, PostgreSQL | 8100 | Ядро. REST API + WebSocket. Не доступен извне. |
|
||
| **BFF** | Python, FastAPI | 8200 | Прокси для Web Client. JWT auth. |
|
||
| **Web Client** | Next.js 15, Tailwind CSS | 3100 | UI: канбан, чат, настройки. |
|
||
| **Picogent** | Node.js, TypeScript, Pi Agent Core | — | AI-агент. Подключается к Tracker по WS. |
|
||
| **Telegram Bridge** | TBD | — | Дублирует чат проекта в Telegram (с топиками). |
|
||
| **OpenClaw Bridge** | TBD | — | Фильтрует @markov mentions → webhook в OpenClaw. |
|
||
| **PostgreSQL** | 16 | 5433 | БД Tracker. |
|
||
| **Redis** | 7 | 6380 | Пока не используется. |
|
||
|
||
## Проекты
|
||
|
||
Проект = workspace для команды (людей + агентов).
|
||
|
||
**Поля:** name, slug, description, repo_urls[] (multi-repo), status (active/archived).
|
||
|
||
**Вкладки UI:** канбан, чат, дашборд, настройки, файлы, activity feed.
|
||
|
||
**Правила:** описываются в документации проекта (docs/ в repo или file storage). Агенты читают при онбординге.
|
||
|
||
**Кросс-проектные ссылки:** задача в проекте A может ссылаться на задачу в проекте B.
|
||
|
||
## Задачи
|
||
|
||
### Модель
|
||
| Поле | Тип | Описание |
|
||
|------|-----|----------|
|
||
| id | UUID | |
|
||
| title | string | Название |
|
||
| description | text | Markdown |
|
||
| type | enum | task, bug, epic, story |
|
||
| status | enum | backlog, todo, in_progress, in_review, done |
|
||
| priority | enum | critical, high, medium, low |
|
||
| labels | string[] | bug, feature, refactor, docs... |
|
||
| parent_id | UUID? | Подзадача (бесконечная вложенность) |
|
||
| depends_on | UUID[] | Зависимости (нельзя начать пока не done) |
|
||
| assignee_slug | string? | Исполнитель |
|
||
| reviewer_slug | string? | Ревьюер |
|
||
| steps | Step[] | Этапы (прогресс агента, не видны на канбане) |
|
||
| time_spent | int | Минуты (для аналитики) |
|
||
| project_id | UUID | |
|
||
|
||
### Статусы
|
||
Любой → любой. Без жёсткого flow. `todo → done` — нормально, если задача простая.
|
||
|
||
### Подзадачи vs Этапы
|
||
- **Подзадачи** = полноценные задачи на канбан-доске (parent_id)
|
||
- **Этапы (steps)** = чеклист внутри задачи. Агент обновляет по ходу работы. Не засоряют доску.
|
||
|
||
### Комментарии
|
||
```
|
||
TaskComment: id, task_id, author_type (human|agent|system),
|
||
content, mentions[], voice_url?, attachments[],
|
||
parent_comment_id? (threads), created_at
|
||
```
|
||
Mentions (@slug) → уведомление агенту через WS.
|
||
|
||
### Связи между задачами (Task Links)
|
||
Помимо parent/child и depends_on, задачи поддерживают дополнительные связи:
|
||
- **relates_to** — связанные задачи (информационно)
|
||
- **duplicates** — дубликат другой задачи
|
||
- **blocks / blocked_by** — блокировка (аналог depends_on, но для человеческого UI)
|
||
|
||
Агенты используют `depends_on` для автоматики, остальные связи — для людей в UI.
|
||
|
||
### Назначение задач
|
||
1. Человек назначает вручную
|
||
2. Архитектор создаёт и назначает
|
||
3. Агент сам берёт из `todo` по capabilities (`task.take` — атомарная операция)
|
||
4. Через чат с @mention: "ребята, новая задача"
|
||
5. Auto-assign: Tracker предлагает задачу по capabilities + загрузке (HYBRID модель)
|
||
|
||
### Приоритизация очереди
|
||
- По приоритету задачи (critical → high → medium → low)
|
||
- Если задача назначена на конкретного агента → он берёт первым
|
||
- Label matching: лейблы задачи ∩ capabilities агента
|
||
|
||
### Особенности
|
||
- Агент может **отклонить** задачу (reject_task) с обоснованием
|
||
- **Автообнаружение блокеров**: зависимость застряла → пинг в чат
|
||
- **Задача-наблюдатель**: не на выполнение, а мониторинг ("следи за CI", "проверяй X раз в час"). Периодическая/фоновая задача.
|
||
- Задача порождает подзадачи автоматически (агент создаёт через create_task)
|
||
- Циклические зависимости запрещены (валидация при создании)
|
||
|
||
## Чаты
|
||
|
||
### Типы
|
||
| Тип | Описание | Файлы |
|
||
|-----|----------|-------|
|
||
| **Lobby** | Глобальный чат для всех | Нет хранилища |
|
||
| **Project Chat** | Per-project, координация | Да |
|
||
| **Task Comments** | Per-task, обсуждение задачи | Да |
|
||
|
||
### Фичи
|
||
- **Threads** (как в Slack) — ответ на сообщение создаёт ветку
|
||
- **Голосовые** — запись → Thoth транскрибирует → текст + аудио
|
||
- **Файлы в чат** — документы, изображения
|
||
- **Реакции** — TBD (не попадают в промпт агента, чисто UI)
|
||
|
||
### Модель сообщения
|
||
```
|
||
ChatMessage: id, chat_id, author_type, author_slug,
|
||
content (markdown), thread_id?, mentions[],
|
||
voice_url?, attachments[], reactions[], created_at
|
||
```
|
||
|
||
## Участники (Members)
|
||
|
||
### Ключевой принцип: все равны
|
||
Агент и человек — **одна модель**. Различие только в type и методе авторизации.
|
||
|
||
```
|
||
Member:
|
||
id: UUID
|
||
name: string
|
||
slug: string (уникальный)
|
||
type: human | agent
|
||
role: owner | member | observer | bridge
|
||
auth_method: password | oauth | token
|
||
capabilities: string[] # для агентов: coding, review...
|
||
listen_mode: all | mentions # для агентов (human сам решает)
|
||
prompt: string? # system prompt (только для агентов)
|
||
model: string? # LLM модель (только для агентов)
|
||
status: online | offline | busy
|
||
avatar_url: string?
|
||
```
|
||
|
||
### Авторизация
|
||
| Тип | Метод | Пример |
|
||
|-----|-------|--------|
|
||
| human (Web UI) | login/password, OAuth (Authentik) | Человек в браузере |
|
||
| human (MCP Client) | login/password, OAuth | Claude Code CLI, Cursor |
|
||
| agent (Picogent) | token (сгенерирован в UI) | Автономный AI-агент |
|
||
| agent (Марков/OpenClaw) | token (REST API) | AI через скилл |
|
||
| bridge | token | Telegram Bridge |
|
||
|
||
MCP Client (Claude Code, Cursor) — это **человек с инструментами**, не агент. Авторизация как у человека.
|
||
|
||
### Роли
|
||
| Роль | Описание | Права по умолчанию |
|
||
|------|----------|-------------------|
|
||
| `owner` | Владелец доски. Полные права. | Все |
|
||
| `member` | Участник. Выполняет задачи, пишет в чат. | send_messages, create_tasks, update_tasks |
|
||
| `observer` | Только чтение. | — |
|
||
| `bridge` | Мост (Telegram). Пересылает сообщения, не берёт задачи. | send_messages |
|
||
|
||
### Права (permissions)
|
||
| Право | Описание |
|
||
|-------|----------|
|
||
| `send_messages` | Отправка сообщений в чаты |
|
||
| `create_tasks` | Создание новых задач |
|
||
| `assign_tasks` | Назначение задач другим агентам |
|
||
| `update_tasks` | Изменение статуса/описания задач |
|
||
| `manage_agents` | Управление другими агентами |
|
||
| `manage_projects` | Создание/изменение проектов |
|
||
|
||
### Конфигурация
|
||
Один бинарник, роль = конфиг (`agent.json`):
|
||
```json
|
||
{
|
||
"name": "Кодер",
|
||
"slug": "coder",
|
||
"prompt": "Ты опытный разработчик...",
|
||
"model": "sonnet",
|
||
"capabilities": ["coding", "review"],
|
||
"listen_mode": "mentions",
|
||
"tracker_url": "http://localhost:8100",
|
||
"token": "tb-agent-xxx"
|
||
}
|
||
```
|
||
|
||
### Режимы прослушивания
|
||
- `listen: all` — слышит всё в чате (архитектор, PM)
|
||
- `listen: mentions` — только при @упоминании (кодер, тестер)
|
||
|
||
### Одна сессия на агента
|
||
Всё в одном контексте: задачи, чат, ответы. Агент видит полную картину.
|
||
|
||
### Онбординг
|
||
При подключении к проекту агент получает контекст: README, docs, архитектуру.
|
||
|
||
### Memory
|
||
Per-agent + per-project. Агент дописывает findings после задач.
|
||
|
||
### Что агент получает
|
||
Текстовые сообщения (максимум разговорной речи):
|
||
- `"Тебе назначена задача TB-42: Добавить авторизацию. Приоритет: high."`
|
||
- `"[чат проекта] @architect: Используй JWT для авторизации"`
|
||
- `"[комментарий к TB-42] @reviewer: В auth.py строка 42 не обработан expired token"`
|
||
|
||
Агент сам решает что делать — вызывает MCP tools.
|
||
|
||
### Label Matching
|
||
Задача имеет labels, агент поддерживает labels → автоматический matching для assign.
|
||
|
||
### Проблема "глухого агента" (Checkpoint Pattern)
|
||
LLM `query()` блокирующий — агент не слышит новых сообщений пока думает.
|
||
|
||
**Решения:**
|
||
- **Короткие задачи** — декомпозиция на шаги по 5-10 минут
|
||
- **Checkpoint pattern** — агент проверяет входящие между шагами работы
|
||
- **session.checkpoint** — агент сохраняет своё понимание контекста в Tracker, чтобы при сбое продолжить с того же места
|
||
|
||
### Зависший агент / Таймауты
|
||
- **Heartbeat** — агент шлёт `agent.heartbeat` каждые 30 секунд
|
||
- Если heartbeat не пришёл 90 секунд → `agent.status = offline`
|
||
- Уведомление в чат: "Агент X перестал отвечать"
|
||
- **Grace period**: при дисконнекте статус сначала `away` (60 сек), потом `offline`
|
||
- Незавершённые задачи: возвращаются в `todo` или ждут (зависит от политики)
|
||
- **Рестарт**: systemd перезапускает picogent, агент делает session.resume
|
||
|
||
### Reconnect и восстановление сессии
|
||
При реконнекте агент отправляет `session.resume` с `last_seq` (последнее известное сообщение). Tracker возвращает `context_summary` + пропущенные сообщения. Агент продолжает работу.
|
||
|
||
### Контракт агента (contract)
|
||
Описывает capabilities, лимиты и разрешённые tools:
|
||
```json
|
||
{
|
||
"capabilities": ["coding", "review"],
|
||
"max_concurrent_tasks": 2,
|
||
"timeout_seconds": 600,
|
||
"tools": {"file_read": true, "git_commit": true, "shell_exec": false},
|
||
"limits": {"max_file_size_mb": 10, "max_files_per_task": 20}
|
||
}
|
||
```
|
||
|
||
## Протокол
|
||
|
||
### Принцип
|
||
- **WebSocket** = real-time: события (push) + сообщения чата
|
||
- **REST (MCP tools)** = все мутации: задачи, этапы, файлы, статусы
|
||
|
||
### WS Protocol
|
||
|
||
**Инфраструктура:**
|
||
```
|
||
Agent → Tracker: auth, heartbeat, ack
|
||
Tracker → Agent: auth.ok, auth.error, event
|
||
```
|
||
|
||
**События (push):**
|
||
| Событие | В промпт? | |
|
||
|---------|-----------|--|
|
||
| task.assigned | ✅ | Текстом |
|
||
| chat.message | ✅/❌ | По listen_mode |
|
||
| task.comment (mention) | ✅ | Текстом |
|
||
| task.taken | ❌ | Internal |
|
||
| task.status_changed | ❌ | Internal (кроме разблокировки зависимости) |
|
||
|
||
### MCP Tools (REST)
|
||
| Tool | Описание |
|
||
|------|----------|
|
||
| get_task, list_tasks | Чтение задач |
|
||
| create_task | Создать задачу/подзадачу |
|
||
| update_task | Обновить поля |
|
||
| take_task | Взять себе (атомарно) |
|
||
| reject_task | Отклонить с причиной |
|
||
| add_step, complete_step | Управление этапами |
|
||
| add_comment | Комментарий (с mentions) |
|
||
| send_message | Сообщение в чат |
|
||
| upload_file, list_files | Файлы |
|
||
|
||
### Router (в Picogent)
|
||
Тупой relay: WS event → текст → единственная сессия агента. Агент сам вызывает tools.
|
||
|
||
### Межагентная коммуникация
|
||
Агенты общаются через чат (send_message с @mention). Для структурированных запросов — протокол `agent.request` / `agent.response`:
|
||
```
|
||
Кодер → Tracker: agent.request {target: "reviewer", type: "code_review", payload: {pr_url}}
|
||
Tracker → Ревьюер: agent.request {from: "coder", request_id, payload}
|
||
Ревьюер → Tracker: agent.response {request_id, result: {approved, comments}}
|
||
```
|
||
|
||
## Файловое хранилище
|
||
|
||
- Per-project директории
|
||
- Upload/download через REST API
|
||
- Связь с git repos (repo_urls[])
|
||
- Версионирование файлов — TBD
|
||
|
||
## Git Workflow
|
||
|
||
### Принцип
|
||
- Агент клонирует repo в свою рабочую директорию
|
||
- Работает в отдельной ветке: `{type}/{task-id}-{slug}` (feat/fix/refactor/docs)
|
||
- По завершении → **Merge Request** в Gitea
|
||
- Ревью (агент/человек) → approve/reject
|
||
- **Автомерж** после approve
|
||
|
||
### Конфликты
|
||
- Решает тот, чей MR. После разрешения — повторный review.
|
||
- Lock на файлы — **не нужен**
|
||
- Максимум 3 итерации ревью, потом эскалация к человеку
|
||
|
||
### Gitea интеграция
|
||
- Webhooks от Gitea → Tracker: push, PR opened/reviewed/merged
|
||
- Tracker → Gitea API: создание веток, PR, комментирование
|
||
- PR merged → задача автоматически в Done
|
||
- CI/CD через Gitea Actions — автотесты на MR
|
||
|
||
### Ревью
|
||
- Автор ≠ ревьюер (всегда)
|
||
- Не каждая задача требует PR (определяется лейблами: `coding` → PR, `analytics` → нет)
|
||
- Все комментарии ревью в задаче (единый контекст)
|
||
|
||
## Telegram Bridge (MVP)
|
||
|
||
- Один бот, подключается по WS к Tracker как `client_type=bridge`
|
||
- Дублирует сообщения из project chats в Telegram
|
||
- **Топики**: если в Telegram включены topics → бот пишет в топик с именем проекта (каждый проект = отдельный топик)
|
||
- Форматирование: `👤 Eugene: текст` / `🤖 Кодер: текст` / `⚙️ Задача #42 → in_progress`
|
||
- **Telegram → Tracker**: сообщение из группы → `chat.send` с `sender_type=bridge`
|
||
- **Упоминания**: парсит `@slug` из Telegram → `mentions` в `chat.send`
|
||
- Системные события (task.created, task.updated) → уведомления в группу
|
||
- ⚠️ Ограничение Telegram: боты НЕ видят сообщения других ботов → один бот = bridge для всех
|
||
|
||
## Безопасность
|
||
|
||
- **Аутентификация**: токены (прописываются при регистрации агента). Каждый агент = уникальный токен.
|
||
- **Роли и permissions**: owner / agent / bridge / observer (см. раздел Агенты)
|
||
- **Capabilities enforcement**: агент с capabilities=["code"] не получит задачи на review
|
||
- **Rate limiting** — планируется: chat.send 30/min, task.progress 10/min и т.д.
|
||
- **Audit log** — планируется: логирование всех действий
|
||
- **Token rotation** — планируется: ротация каждые 30 дней
|
||
|
||
## Версионирование API
|
||
|
||
- REST API: `/api/v1/`, `/api/v2/`
|
||
- Обратная совместимость при обновлении
|
||
- WS Protocol: версия в auth handshake
|
||
|
||
## Деплой
|
||
|
||
- **Tracker + BFF + Web Client**: Docker Compose
|
||
- **Picogent**: systemd сервис (один процесс на агента)
|
||
- Автоматический restart при падении (systemd)
|
||
- CI/CD: Gitea Actions auto-deploy
|
||
- Агент-DevOps возможен для CI/CD задач
|
||
|
||
## На будущее
|
||
|
||
- **Web MCP Server** — отдельный пакет (`team-board/mcp-server`), любой LLM-клиент (Claude Code, Cursor, Windsurf, Cline, OpenClaw) работает с трекером через MCP без WebSocket и без Picogent. Использует тот же REST API. Не автономный (нет push-событий), но полностью функциональный.
|
||
- **Multi-instance агентов** — scaling, несколько кодеров одного типа. Вопрос: slug = роль, instance_id = отдельно? Требует продумывания.
|
||
- **Аналитика** — метрики, дашборды (tasks/hour, avg task duration, agent utilization)
|
||
- **OAuth / Authentik** — мульти-пользователь
|
||
- **Notification Bridge** — отдельный bridge-агент, подключается по WS, пушит уведомления за пределы чата (email, push, webhooks)
|
||
- **Agent SDK** — Python-пакет (`team-board-sdk`) с базовым классом Agent, обработчиками on_task/on_chat/on_reconnect, интеграцией с git
|
||
- **Session Compaction** — при превышении контекста (50K токенов) сжатие истории в summary + recent window
|
||
- **Event Sourcing** — вся работа агента как поток событий для воспроизведения и восстановления состояния
|
||
|
||
## Конкурентный анализ (референсы)
|
||
|
||
| Система | Ключевые идеи | Что забираем |
|
||
|---------|---------------|-------------|
|
||
| **MetaGPT** | Промпты ролей (PM, Architect, Engineer, QA), pub/sub между ролями, SOP | Промпты для назначения ролей агентам |
|
||
| **Claude Flow / Ruflo** | Claims (атомарное взятие задач), swarm топологии, multi-provider | Паттерн claims для task.take |
|
||
| **BMAD Method** | Brainstorming workflow, party mode (мульти-ролевой prompt) | Workflow для планирования |
|
||
| **OpenHands** | Event sourcing, Docker sandbox, event log replay | Воспроизводимость сессий |
|
||
| **LangGraph** | State machine + persistent checkpointing | Checkpoint pattern |
|
||
| **CrewAI** | Role-based delegation, task routing по ролям | Capabilities matching |
|
||
| **Devin** | VM-sandbox, persistent sessions (часы), полный git цикл | Долгие сессии с checkpoints |
|
||
|
||
### Picogent vs Runner
|
||
Picogent (Node.js, TypeScript, Pi Agent Core) **заменяет** runner/ — более зрелая реализация. In-process agent loop, dual transport (HTTP + WebSocket), skills, sessions, sandbox, directory mode.
|
||
|
||
## Идеи на подумать
|
||
|
||
### ⚠️ Требуют отдельного обсуждения
|
||
- **Rollback файлов**: git revert очевиден, но файлы в хранилище **не версионированы**. Нужно ли версионирование файлов или хотя бы бэкап перед изменением?
|
||
- **Реакции в чатах**: выглядит круто, но жрёт токены. Варианты: (a) не попадают в промпт агента, (b) агент ставит через MCP tool, (c) попадают только @mention-reactions. Решение TBD.
|
||
- **Лейблы глобальные или per-project?** — не решено
|
||
- **Формат скилла для Runner'ов** — как описать взаимодействие агента с Tracker
|
||
- **Как агент определяет релевантность задачи для себя?** — auto-assign vs manual
|
||
- **Workspace агентов: общий или изолированный?**
|
||
- **Прогресс работы агента в реалтайме** (streaming в UI)
|
||
|
||
### 💡 Идеи на будущее
|
||
- **Agent SDK v1.0** — Python-пакет с базовым классом, git-хелперами, LLM-интерфейсом
|
||
- **Redis Streams** для event bus (горизонтальное масштабирование Tracker)
|
||
- **Structured inter-agent requests** (agent.request/response) для code review, delegation
|
||
- **task.offer / task.accept / task.decline** — Tracker предлагает задачу, агент может отклонить (HYBRID модель)
|
||
- **Compaction сессий** — server-side или agent-side сжатие контекста
|
||
- **Grafana dashboard**: WS connections, task flow, agent utilization
|
||
- **Token rotation** (30 дней) + per-agent capability enforcement
|
||
- **Docker containers per agent** для sandbox isolation
|
||
- **Gitea webhook handler** в Tracker для автоматизации git-событий
|
||
- **HTTP Callback** как альтернативный транспорт (Tracker POST'ит события на URL агента)
|
||
- **Агент создаёт проект** — Архитектор может создать проект через API
|
||
- **Subscription modes**: `all` / `mentions` / `assigned` (разные уровни вовлечения)
|
||
|
||
### ❌ Отклонено (из брейншторма)
|
||
- Шаблоны задач / проектов — не нужны
|
||
- Forking проектов — не нужен
|
||
- Автостатус задач — не нужен
|
||
- Оценка сложности / дедлайны — не нужны
|
||
- Lock на файлы — не нужен
|
||
- Бюджет в токенах — нет
|
||
- Приватность проектов — агент не трогает чужое
|