Full protocol spec: WS + HTTP callback, agent model, roles, permissions, events, Telegram Bridge
This commit is contained in:
parent
ffe8f68806
commit
2edcdd8aed
@ -1,79 +1,191 @@
|
||||
# Team Board WebSocket Protocol
|
||||
# Team Board — Протокол взаимодействия
|
||||
|
||||
## Подключение
|
||||
## Транспорт
|
||||
|
||||
Два способа подключения агентов:
|
||||
|
||||
### 1. WebSocket (основной)
|
||||
```
|
||||
ws://localhost:8100/ws?client_type={type}&client_id={id}
|
||||
ws://{host}:8100/ws?client_type={type}&client_id={slug}
|
||||
```
|
||||
|
||||
- `client_type`: `human` | `agent` | `bridge`
|
||||
- `client_id`: уникальный идентификатор клиента (slug агента, имя bridge и т.д.)
|
||||
### 2. HTTP Callback (альтернативный)
|
||||
Агент регистрируется через REST API, указывает `callback_url`. Tracker отправляет события POST-запросами на этот URL.
|
||||
|
||||
## Формат сообщений
|
||||
```
|
||||
POST {callback_url}/events
|
||||
Content-Type: application/json
|
||||
|
||||
Все сообщения — JSON с полем `event`:
|
||||
{"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
|
||||
{"event": "event.name", ...payload}
|
||||
{
|
||||
"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
|
||||
Аутентификация (для агентов/bridge).
|
||||
```json
|
||||
{"event": "auth", "token": "agent-xxx"}
|
||||
{
|
||||
"event": "auth",
|
||||
"token": "agent-xxx",
|
||||
"name": "Кодер",
|
||||
"capabilities": ["code"]
|
||||
}
|
||||
```
|
||||
Ответ: `auth.ok` с `{"init": {}}`
|
||||
|
||||
### chat.subscribe
|
||||
Подписка на чат-комнату.
|
||||
```json
|
||||
{"event": "chat.subscribe", "chat_id": "uuid"}
|
||||
```
|
||||
Ответ: `chat.subscribed`
|
||||
|
||||
### chat.unsubscribe
|
||||
Отписка от чата.
|
||||
```json
|
||||
{"event": "chat.unsubscribe", "chat_id": "uuid"}
|
||||
```
|
||||
|
||||
### chat.send
|
||||
Отправка сообщения в чат.
|
||||
```json
|
||||
{
|
||||
"event": "chat.send",
|
||||
"chat_id": "uuid",
|
||||
"content": "текст сообщения",
|
||||
"sender_type": "human|agent|system|bridge",
|
||||
"sender_id": "optional-uuid",
|
||||
"sender_name": "Имя отправителя"
|
||||
"sender_type": "agent|bridge|human",
|
||||
"sender_name": "Кодер",
|
||||
"mentions": ["reviewer"] // @slug упоминания
|
||||
}
|
||||
```
|
||||
Сообщение сохраняется в БД и broadcast'ится всем подписчикам чата.
|
||||
|
||||
### agent.heartbeat
|
||||
Пинг от агента (статус).
|
||||
```json
|
||||
{"event": "agent.heartbeat", "status": "idle|busy"}
|
||||
```
|
||||
Ответ: `agent.heartbeat.ack`
|
||||
|
||||
## События: Сервер → Клиент
|
||||
|
||||
### auth.ok
|
||||
### task.take
|
||||
Агент берёт задачу в работу.
|
||||
```json
|
||||
{"event": "auth.ok", "init": {}}
|
||||
{"event": "task.take", "task_id": "uuid"}
|
||||
```
|
||||
|
||||
### chat.subscribed
|
||||
### task.complete
|
||||
Агент завершил задачу.
|
||||
```json
|
||||
{"event": "chat.subscribed", "chat_id": "uuid"}
|
||||
{"event": "task.complete", "task_id": "uuid"}
|
||||
```
|
||||
|
||||
### task.comment
|
||||
Комментарий к задаче.
|
||||
```json
|
||||
{
|
||||
"event": "task.comment",
|
||||
"task_id": "uuid",
|
||||
"content": "Готово, коммит abc123"
|
||||
}
|
||||
```
|
||||
|
||||
## События: Сервер → Клиент (broadcast)
|
||||
|
||||
Все события рассылаются **всем подключённым клиентам** (WS + HTTP callback).
|
||||
|
||||
### chat.message
|
||||
Новое сообщение в чате (broadcast всем подписчикам).
|
||||
```json
|
||||
{
|
||||
"event": "chat.message",
|
||||
@ -82,43 +194,99 @@ ws://localhost:8100/ws?client_type={type}&client_id={id}
|
||||
"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"
|
||||
}
|
||||
```
|
||||
|
||||
### error
|
||||
### task.created
|
||||
```json
|
||||
{"event": "error", "message": "описание ошибки"}
|
||||
{
|
||||
"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**: общий чат, ID: `25c20eaa-fbf1-4259-8501-0854cc926d0d`
|
||||
- **Project chat**: чат проекта (один на проект)
|
||||
- **Task chat**: чат задачи (один на задачу)
|
||||
| Тип | Описание |
|
||||
|-----|----------|
|
||||
| `lobby` | Общий чат (один на инстанс) |
|
||||
| `project` | Чат проекта (один на проект) |
|
||||
| `task` | Чат задачи (один на задачу) |
|
||||
|
||||
### REST API для чатов
|
||||
### REST API
|
||||
```
|
||||
GET /api/v1/chats/lobby — получить lobby
|
||||
GET /api/v1/chats/{id}/messages — история сообщений
|
||||
POST /api/v1/chats/{id}/messages — отправить (без WS)
|
||||
GET /api/v1/chats/lobby — lobby чат
|
||||
GET /api/v1/chats/{id}/messages?limit=20 — история
|
||||
POST /api/v1/chats/{id}/messages — отправить
|
||||
```
|
||||
|
||||
## Telegram Bridge (планируется)
|
||||
## Telegram Bridge
|
||||
|
||||
Bridge-клиент подключается как `client_type=bridge`, подписывается на нужные чаты и:
|
||||
Bridge-агент с `connection_type=bridge`:
|
||||
|
||||
1. **Tracker → Telegram**: получает `chat.message`, форматирует и отправляет в Telegram группу
|
||||
2. **Telegram → Tracker**: получает сообщения из Telegram, отправляет `chat.send` с `sender_type=bridge`
|
||||
3. **Системные события**: статус задачи, новая задача и т.д.
|
||||
4. **Теги агентов**: парсит `@slug` в сообщениях из Telegram
|
||||
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
|
||||
### Формат в Telegram
|
||||
```
|
||||
[Имя Агента] Текст сообщения
|
||||
```
|
||||
или
|
||||
```
|
||||
🤖 Кодер: Задача выполнена, коммит abc123
|
||||
👤 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`
|
||||
|
||||
Loading…
Reference in New Issue
Block a user