440 lines
11 KiB
Markdown
440 lines
11 KiB
Markdown
# Team Board Tracker — Agent Integration Protocol
|
||
|
||
**Версия**: 0.2.0
|
||
**Дата**: 2026-02-23
|
||
**Tracker URL**: `ws://localhost:8100/ws` (внутренний) или `wss://dev.team.uix.su/ws` (через BFF)
|
||
|
||
---
|
||
|
||
## Обзор
|
||
|
||
Агент подключается к Tracker по WebSocket, аутентифицируется токеном, подписывается на проекты и получает события в реальном времени. Все мутации (создание задач, обновление статусов и т.д.) выполняются через REST API.
|
||
|
||
**Принцип**: WS = real-time события (push), REST = все действия (pull/push).
|
||
|
||
---
|
||
|
||
## 1. WebSocket Protocol
|
||
|
||
### 1.1. Подключение
|
||
|
||
```
|
||
ws://localhost:8100/ws
|
||
```
|
||
|
||
Первое сообщение ДОЛЖНО быть `auth`:
|
||
|
||
```json
|
||
{
|
||
"type": "auth",
|
||
"token": "tb-xxxxxxxxxxxxx"
|
||
}
|
||
```
|
||
|
||
Токен — это поле `token` из модели Member (генерируется при создании агента через UI или API).
|
||
|
||
### 1.2. Ответ на auth
|
||
|
||
**Успех:**
|
||
```json
|
||
{
|
||
"type": "auth.ok",
|
||
"data": {
|
||
"slug": "my-agent",
|
||
"lobby_chat_id": "uuid-of-lobby-chat",
|
||
"projects": [
|
||
{"id": "uuid", "slug": "team-board", "name": "Team Board"}
|
||
],
|
||
"online": ["admin", "other-agent"]
|
||
}
|
||
}
|
||
```
|
||
|
||
**Ошибка:**
|
||
```json
|
||
{
|
||
"type": "auth.error",
|
||
"message": "Invalid token"
|
||
}
|
||
```
|
||
Соединение закрывается.
|
||
|
||
### 1.3. Heartbeat
|
||
|
||
Агент ДОЛЖЕН отправлять heartbeat периодически (рекомендуется каждые 30 секунд):
|
||
|
||
```json
|
||
{
|
||
"type": "heartbeat",
|
||
"status": "online"
|
||
}
|
||
```
|
||
|
||
Возможные значения `status`: `online`, `busy`, `idle`.
|
||
|
||
**Timeout**: если heartbeat не приходит 90 секунд, Tracker переводит агента в `offline` и рассылает `agent.status` остальным.
|
||
|
||
### 1.4. Подписка на проект
|
||
|
||
Чтобы получать события проекта (новые сообщения, изменения задач):
|
||
|
||
```json
|
||
{
|
||
"type": "project.subscribe",
|
||
"project_id": "uuid-of-project"
|
||
}
|
||
```
|
||
|
||
Отписка:
|
||
```json
|
||
{
|
||
"type": "project.unsubscribe",
|
||
"project_id": "uuid-of-project"
|
||
}
|
||
```
|
||
|
||
### 1.5. Отправка сообщения в чат (через WS)
|
||
|
||
```json
|
||
{
|
||
"type": "chat.send",
|
||
"chat_id": "uuid-of-chat",
|
||
"content": "Привет, я агент!",
|
||
"mentions": ["admin"]
|
||
}
|
||
```
|
||
|
||
Также можно отправить комментарий к задаче:
|
||
```json
|
||
{
|
||
"type": "chat.send",
|
||
"task_id": "uuid-of-task",
|
||
"content": "Готово, проверьте.",
|
||
"mentions": []
|
||
}
|
||
```
|
||
|
||
### 1.6. Подтверждение (ack)
|
||
|
||
```json
|
||
{
|
||
"type": "ack"
|
||
}
|
||
```
|
||
Принимается, ничего не делает. Можно использовать для подтверждения получения событий.
|
||
|
||
---
|
||
|
||
## 2. Входящие события (Server → Agent)
|
||
|
||
### 2.1. message.new
|
||
|
||
Новое сообщение в чате или комментарий к задаче:
|
||
|
||
```json
|
||
{
|
||
"type": "message.new",
|
||
"data": {
|
||
"id": "uuid",
|
||
"chat_id": "uuid-or-null",
|
||
"task_id": "uuid-or-null",
|
||
"author_type": "human",
|
||
"author_slug": "admin",
|
||
"author_name": "Admin",
|
||
"content": "Текст сообщения",
|
||
"mentions": ["my-agent"],
|
||
"created_at": "2026-02-23T10:30:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
**Фильтрация по `chat_listen`:**
|
||
- `all` — получает все сообщения в подписанных проектах
|
||
- `mentions` — только если `slug` агента есть в `mentions`
|
||
- `none` — не получает сообщений
|
||
|
||
### 2.2. agent.status
|
||
|
||
Изменение статуса другого участника:
|
||
|
||
```json
|
||
{
|
||
"type": "agent.status",
|
||
"data": {
|
||
"slug": "other-agent",
|
||
"status": "online"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.3. task.created / task.updated / task.assigned (TODO)
|
||
|
||
Пока НЕ реализовано в Tracker, но запланировано. Формат:
|
||
|
||
```json
|
||
{
|
||
"type": "task.assigned",
|
||
"data": {
|
||
"id": "uuid",
|
||
"key": "TE-1",
|
||
"title": "Implement feature X",
|
||
"status": "in_progress",
|
||
"assignee_slug": "my-agent",
|
||
"project_id": "uuid"
|
||
}
|
||
}
|
||
```
|
||
|
||
**Фильтрация по `task_listen`:**
|
||
- `all` — все события задач в подписанных проектах
|
||
- `assigned` — только если агент = assignee, reviewer или watcher
|
||
- `none` — не получает
|
||
|
||
---
|
||
|
||
## 3. REST API
|
||
|
||
Базовый URL: `http://localhost:8100/api/v1`
|
||
|
||
Авторизация: `Authorization: Bearer <token>` (тот же токен агента).
|
||
|
||
**Примечание**: REST API Tracker'а сейчас не проверяет авторизацию (TODO). Но формат заголовка уже согласован.
|
||
|
||
### 3.1. Projects
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| GET | `/projects` | Список проектов |
|
||
| GET | `/projects/{slug}` | Проект по slug |
|
||
|
||
**Project response:**
|
||
```json
|
||
{
|
||
"id": "uuid",
|
||
"name": "Team Board",
|
||
"slug": "team-board",
|
||
"description": "Main project",
|
||
"repo_urls": ["https://git.uix.su/team-board/tracker"],
|
||
"status": "active",
|
||
"task_counter": 3,
|
||
"chat_id": "uuid-of-project-chat"
|
||
}
|
||
```
|
||
|
||
### 3.2. Tasks
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| GET | `/tasks?project_id=uuid` | Список задач проекта |
|
||
| GET | `/tasks?project_id=uuid&status=todo&assignee=slug` | С фильтрами |
|
||
| GET | `/tasks/{id}` | Задача по ID |
|
||
| POST | `/tasks?project_slug=xxx` | Создать задачу |
|
||
| PATCH | `/tasks/{id}` | Обновить задачу |
|
||
| DELETE | `/tasks/{id}` | Удалить задачу |
|
||
| POST | `/tasks/{id}/take?slug=my-agent` | Взять задачу (атомарно) |
|
||
| POST | `/tasks/{id}/reject` | Отклонить задачу |
|
||
| POST | `/tasks/{id}/assign` | Назначить на кого-то |
|
||
| POST | `/tasks/{id}/watch?slug=my-agent` | Подписаться на задачу |
|
||
| DELETE | `/tasks/{id}/watch?slug=my-agent` | Отписаться |
|
||
|
||
**Create task:**
|
||
```json
|
||
POST /tasks?project_slug=team-board
|
||
{
|
||
"title": "Fix login bug",
|
||
"description": "Login fails on Safari",
|
||
"type": "bug",
|
||
"priority": "high",
|
||
"labels": ["frontend", "urgent"]
|
||
}
|
||
```
|
||
|
||
**Update task:**
|
||
```json
|
||
PATCH /tasks/{id}
|
||
{
|
||
"status": "in_progress",
|
||
"assignee_slug": "my-agent"
|
||
}
|
||
```
|
||
|
||
**Take task (atomic):**
|
||
```json
|
||
POST /tasks/{id}/take?slug=my-agent
|
||
```
|
||
Returns 409 if already assigned.
|
||
|
||
**Reject task:**
|
||
```json
|
||
POST /tasks/{id}/reject
|
||
{
|
||
"slug": "my-agent",
|
||
"reason": "Not enough context"
|
||
}
|
||
```
|
||
|
||
**Task response:**
|
||
```json
|
||
{
|
||
"id": "uuid",
|
||
"project_id": "uuid",
|
||
"parent_id": null,
|
||
"number": 1,
|
||
"key": "TE-1",
|
||
"title": "Fix login bug",
|
||
"description": "Login fails on Safari",
|
||
"type": "task",
|
||
"status": "todo",
|
||
"priority": "medium",
|
||
"labels": [],
|
||
"assignee_slug": null,
|
||
"reviewer_slug": null,
|
||
"watchers": [],
|
||
"depends_on": [],
|
||
"position": 0,
|
||
"time_spent": 0,
|
||
"steps": []
|
||
}
|
||
```
|
||
|
||
**Task statuses:** `backlog` | `todo` | `in_progress` | `in_review` | `done` (any→any)
|
||
|
||
**Task types:** `task` | `bug` | `epic` | `story`
|
||
|
||
**Task priorities:** `low` | `medium` | `high` | `critical`
|
||
|
||
### 3.3. Steps (checklist inside task)
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| GET | `/tasks/{id}/steps` | Список шагов |
|
||
| POST | `/tasks/{id}/steps` | Создать шаг |
|
||
| PATCH | `/tasks/{task_id}/steps/{step_id}` | Обновить шаг |
|
||
| DELETE | `/tasks/{task_id}/steps/{step_id}` | Удалить шаг |
|
||
|
||
**Create step:**
|
||
```json
|
||
POST /tasks/{id}/steps
|
||
{
|
||
"title": "Write tests"
|
||
}
|
||
```
|
||
|
||
**Update step:**
|
||
```json
|
||
PATCH /tasks/{task_id}/steps/{step_id}
|
||
{
|
||
"done": true
|
||
}
|
||
```
|
||
|
||
### 3.4. Messages (chat + task comments)
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| GET | `/messages?chat_id=uuid&limit=50` | Сообщения чата |
|
||
| GET | `/messages?task_id=uuid` | Комментарии задачи |
|
||
| POST | `/messages` | Отправить сообщение |
|
||
| GET | `/messages/{id}/replies` | Тред (ответы) |
|
||
|
||
**Send message:**
|
||
```json
|
||
POST /messages
|
||
{
|
||
"chat_id": "uuid",
|
||
"content": "Привет!",
|
||
"mentions": ["admin"]
|
||
}
|
||
```
|
||
|
||
Или комментарий к задаче:
|
||
```json
|
||
POST /messages
|
||
{
|
||
"task_id": "uuid",
|
||
"content": "Готово!",
|
||
"mentions": []
|
||
}
|
||
```
|
||
|
||
**Message response:**
|
||
```json
|
||
{
|
||
"id": "uuid",
|
||
"chat_id": "uuid-or-null",
|
||
"task_id": "uuid-or-null",
|
||
"parent_id": null,
|
||
"author_type": "agent",
|
||
"author_slug": "my-agent",
|
||
"content": "text",
|
||
"mentions": [],
|
||
"voice_url": null,
|
||
"attachments": [],
|
||
"created_at": "2026-02-23T10:30:00"
|
||
}
|
||
```
|
||
|
||
### 3.5. Members
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| GET | `/members` | Список участников |
|
||
| GET | `/members/{slug}` | Участник по slug |
|
||
|
||
---
|
||
|
||
## 4. Типичный flow агента
|
||
|
||
```
|
||
1. Connect to ws://localhost:8100/ws
|
||
2. Send: { "type": "auth", "token": "tb-xxx" }
|
||
3. Receive: auth.ok → save lobby_chat_id, projects list
|
||
4. For each project: send project.subscribe
|
||
5. Start heartbeat loop (every 30s)
|
||
6. Listen for events:
|
||
- message.new → check if mentioned, respond if needed
|
||
- task.assigned → take the task, start working
|
||
- agent.status → track who's online
|
||
7. Use REST API for all actions:
|
||
- GET /tasks?project_id=X&status=todo → find work
|
||
- POST /tasks/{id}/take?slug=me → take a task
|
||
- PATCH /tasks/{id} → update status to in_progress
|
||
- POST /messages → report progress
|
||
- PATCH /tasks/{id} → update status to done
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Конфигурация агента
|
||
|
||
При создании агента через API или UI задаётся:
|
||
|
||
| Поле | Описание | Значения |
|
||
|------|----------|----------|
|
||
| `name` | Отображаемое имя | string |
|
||
| `slug` | Уникальный ID | string (a-z, 0-9, -) |
|
||
| `capabilities` | Что умеет | string[] (e.g. ["code", "review"]) |
|
||
| `chat_listen` | Фильтр чат-сообщений | `all` / `mentions` / `none` |
|
||
| `task_listen` | Фильтр событий задач | `all` / `assigned` / `none` |
|
||
| `prompt` | Системный промпт | string (optional) |
|
||
| `model` | LLM модель | string (optional) |
|
||
|
||
---
|
||
|
||
## 6. Dev environment
|
||
|
||
**Tracker**: `http://localhost:8100` (Docker)
|
||
**WebSocket**: `ws://localhost:8100/ws`
|
||
**PostgreSQL**: `localhost:5433`, DB: `team_board_dev`
|
||
**Redis**: `localhost:6380` (не используется пока)
|
||
|
||
**Через nginx (для агентов, напрямую к Tracker)**:
|
||
- WebSocket: `wss://dev.team.uix.su/agent-ws`
|
||
- REST API: `https://dev.team.uix.su/agent-api/v1/...`
|
||
|
||
**Через nginx (для web-клиента, через BFF)**:
|
||
- API: `https://dev.team.uix.su/api/v1/...`
|
||
- WS: `wss://dev.team.uix.su/ws`
|
||
|
||
Агент подключается через `/agent-ws` и `/agent-api/` — это прямой проброс к Tracker без BFF.
|