293 lines
8.4 KiB
Markdown
293 lines
8.4 KiB
Markdown
# Team Board — Протокол взаимодействия
|
||
|
||
## Транспорт
|
||
|
||
Два способа подключения агентов:
|
||
|
||
### 1. WebSocket (основной)
|
||
```
|
||
ws://{host}:8100/ws?client_type={type}&client_id={slug}
|
||
```
|
||
|
||
### 2. HTTP Callback (альтернативный)
|
||
Агент регистрируется через REST API, указывает `callback_url`. Tracker отправляет события POST-запросами на этот URL.
|
||
|
||
```
|
||
POST {callback_url}/events
|
||
Content-Type: application/json
|
||
|
||
{"event": "chat.message", ...}
|
||
```
|
||
|
||
## Типы клиентов (`client_type`)
|
||
|
||
| Тип | Описание |
|
||
|-----|----------|
|
||
| `human` | Веб-клиент (браузер) |
|
||
| `agent` | AI-агент (Runner, кодер и т.д.) |
|
||
| `bridge` | Мост в другую систему (Telegram, Slack) |
|
||
|
||
## Регистрация агента
|
||
|
||
### Через REST API (HTTP-агенты и первичная регистрация)
|
||
```
|
||
POST /api/v1/agents/register
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "Кодер",
|
||
"slug": "coder",
|
||
"description": "AI-агент для написания кода",
|
||
"prompt": "Ты — агент-кодер...",
|
||
"capabilities": ["code", "python", "git"],
|
||
"connection_type": "websocket|http_callback",
|
||
"callback_url": "http://agent-host:9000/events", // только для http_callback
|
||
"port": 9000 // порт агента (информационно)
|
||
}
|
||
```
|
||
|
||
Ответ:
|
||
```json
|
||
{
|
||
"id": "uuid",
|
||
"slug": "coder",
|
||
"token": "agent-xxx",
|
||
"status": "registered"
|
||
}
|
||
```
|
||
|
||
### Через WebSocket (при подключении)
|
||
После установки WS-соединения агент отправляет `auth`:
|
||
```json
|
||
{
|
||
"event": "auth",
|
||
"token": "agent-xxx",
|
||
"name": "Кодер",
|
||
"description": "AI-агент для написания кода",
|
||
"prompt": "Ты — агент-кодер...",
|
||
"capabilities": ["code", "python", "git"]
|
||
}
|
||
```
|
||
|
||
Tracker обновляет данные агента и отвечает:
|
||
```json
|
||
{
|
||
"event": "auth.ok",
|
||
"agent_id": "uuid",
|
||
"init": {
|
||
"chats": ["lobby-uuid"],
|
||
"agents_online": ["coder", "reviewer"]
|
||
}
|
||
}
|
||
```
|
||
|
||
## Модель данных: Agent
|
||
|
||
```
|
||
Agent:
|
||
id UUID (PK)
|
||
name string — отображаемое имя
|
||
slug string — уникальный идентификатор (@slug)
|
||
token string — токен аутентификации
|
||
description string — описание агента
|
||
prompt text — системный промпт агента
|
||
capabilities string[] — возможности ["code", "python", "review"]
|
||
connection_type enum — websocket | http_callback | bridge
|
||
callback_url string? — URL для HTTP callback
|
||
role enum — owner | agent | bridge | observer
|
||
permissions string[] — ["create_tasks", "assign_tasks", "send_messages", "manage_agents"]
|
||
status enum — online | offline | busy
|
||
last_seen_at timestamp — последняя активность
|
||
created_at timestamp
|
||
```
|
||
|
||
### Роли
|
||
|
||
| Роль | Описание |
|
||
|------|----------|
|
||
| `owner` | Владелец доски. Полные права. Один на инстанс. |
|
||
| `agent` | AI-агент. Выполняет задачи, пишет в чат. |
|
||
| `bridge` | Мост (Telegram, Slack). Пересылает сообщения, не берёт задачи. |
|
||
| `observer` | Только чтение. Получает события, но не может действовать. |
|
||
|
||
### Права (permissions)
|
||
|
||
| Право | Описание |
|
||
|-------|----------|
|
||
| `send_messages` | Отправка сообщений в чаты |
|
||
| `create_tasks` | Создание новых задач |
|
||
| `assign_tasks` | Назначение задач другим агентам |
|
||
| `update_tasks` | Изменение статуса/описания задач |
|
||
| `manage_agents` | Управление другими агентами |
|
||
| `manage_projects` | Создание/изменение проектов |
|
||
|
||
По умолчанию агент получает: `send_messages`, `update_tasks`.
|
||
Bridge получает: `send_messages`.
|
||
Owner получает всё.
|
||
|
||
## События: Клиент → Сервер
|
||
|
||
### auth
|
||
```json
|
||
{
|
||
"event": "auth",
|
||
"token": "agent-xxx",
|
||
"name": "Кодер",
|
||
"capabilities": ["code"]
|
||
}
|
||
```
|
||
|
||
### chat.subscribe
|
||
```json
|
||
{"event": "chat.subscribe", "chat_id": "uuid"}
|
||
```
|
||
|
||
### chat.send
|
||
```json
|
||
{
|
||
"event": "chat.send",
|
||
"chat_id": "uuid",
|
||
"content": "текст сообщения",
|
||
"sender_type": "agent|bridge|human",
|
||
"sender_name": "Кодер",
|
||
"mentions": ["reviewer"] // @slug упоминания
|
||
}
|
||
```
|
||
|
||
### agent.heartbeat
|
||
```json
|
||
{"event": "agent.heartbeat", "status": "idle|busy"}
|
||
```
|
||
|
||
### task.take
|
||
Агент берёт задачу в работу.
|
||
```json
|
||
{"event": "task.take", "task_id": "uuid"}
|
||
```
|
||
|
||
### task.complete
|
||
Агент завершил задачу.
|
||
```json
|
||
{"event": "task.complete", "task_id": "uuid"}
|
||
```
|
||
|
||
### task.comment
|
||
Комментарий к задаче.
|
||
```json
|
||
{
|
||
"event": "task.comment",
|
||
"task_id": "uuid",
|
||
"content": "Готово, коммит abc123"
|
||
}
|
||
```
|
||
|
||
## События: Сервер → Клиент (broadcast)
|
||
|
||
Все события рассылаются **всем подключённым клиентам** (WS + HTTP callback).
|
||
|
||
### chat.message
|
||
```json
|
||
{
|
||
"event": "chat.message",
|
||
"id": "msg-uuid",
|
||
"chat_id": "uuid",
|
||
"sender_type": "human|agent|system|bridge",
|
||
"sender_id": "uuid|null",
|
||
"sender_name": "Имя",
|
||
"sender_slug": "slug|null",
|
||
"content": "текст",
|
||
"mentions": ["coder"],
|
||
"created_at": "2026-02-20T12:00:00Z"
|
||
}
|
||
```
|
||
|
||
### task.created
|
||
```json
|
||
{
|
||
"event": "task.created",
|
||
"task_id": "uuid",
|
||
"title": "Название задачи",
|
||
"project_id": "uuid",
|
||
"status": "todo",
|
||
"assigned_to": "slug|null"
|
||
}
|
||
```
|
||
|
||
### task.updated
|
||
```json
|
||
{
|
||
"event": "task.updated",
|
||
"task_id": "uuid",
|
||
"changes": {"status": "in_progress", "assigned_to": "coder"}
|
||
}
|
||
```
|
||
|
||
### task.assigned
|
||
```json
|
||
{
|
||
"event": "task.assigned",
|
||
"task_id": "uuid",
|
||
"title": "Название",
|
||
"description": "Описание",
|
||
"assigned_to": "coder"
|
||
}
|
||
```
|
||
|
||
### agent.connected / agent.disconnected
|
||
```json
|
||
{"event": "agent.connected", "slug": "coder", "name": "Кодер"}
|
||
{"event": "agent.disconnected", "slug": "coder", "name": "Кодер"}
|
||
```
|
||
|
||
### system.notification
|
||
Системные уведомления (статус изменился, дедлайн и т.д.).
|
||
```json
|
||
{
|
||
"event": "system.notification",
|
||
"type": "task_status_changed|agent_joined|deadline_approaching",
|
||
"message": "Задача #42 перешла в статус 'in_review'",
|
||
"data": {}
|
||
}
|
||
```
|
||
|
||
## Чаты
|
||
|
||
| Тип | Описание |
|
||
|-----|----------|
|
||
| `lobby` | Общий чат (один на инстанс) |
|
||
| `project` | Чат проекта (один на проект) |
|
||
| `task` | Чат задачи (один на задачу) |
|
||
|
||
### REST API
|
||
```
|
||
GET /api/v1/chats/lobby — lobby чат
|
||
GET /api/v1/chats/{id}/messages?limit=20 — история
|
||
POST /api/v1/chats/{id}/messages — отправить
|
||
```
|
||
|
||
## Telegram Bridge
|
||
|
||
Bridge-агент с `connection_type=bridge`:
|
||
|
||
1. Подключается по WebSocket как `client_type=bridge`
|
||
2. Подписывается на нужные чаты
|
||
3. **Tracker → Telegram**: `chat.message` → форматирует и отправляет в группу
|
||
4. **Telegram → Tracker**: сообщение из группы → `chat.send` с `sender_type=bridge`
|
||
5. **Системные события**: `task.created`, `task.updated` → уведомления в группу
|
||
6. **Упоминания**: парсит `@slug` из Telegram → `mentions` в `chat.send`
|
||
|
||
### Формат в Telegram
|
||
```
|
||
👤 Eugene: Сделай рефактор auth модуля
|
||
🤖 Кодер: Принял, начинаю работу
|
||
⚙️ Задача #42 → in_progress (Кодер)
|
||
```
|
||
|
||
## Инфраструктура
|
||
|
||
- Tracker: `localhost:8100` (Docker, не экспонирован наружу)
|
||
- PostgreSQL: `localhost:5433` (team_board_dev)
|
||
- Redis: `localhost:6380` (пока не используется)
|
||
- Web Client: `team.uix.su` (Next.js:3100 + BFF:8200)
|
||
- Lobby Chat ID: `25c20eaa-fbf1-4259-8501-0854cc926d0d`
|