# Agent Protocol v1.0 — Source of Truth **Дата**: 2026-02-23 **Статус**: Действующий. Все агенты и Tracker ДОЛЖНЫ соответствовать этому документу. --- ## 1. Подключение ### URLs **Напрямую к Tracker** (для локальной разработки): - REST: `http://localhost:8100` - WS: `ws://localhost:8100/ws` **Через nginx** (для удалённых агентов): - REST: `https://dev.team.uix.su/agent-api` → проксирует к Tracker - WS: `wss://dev.team.uix.su/agent-ws` → проксирует к `ws://localhost:8100/ws` ### Авторизация Токен агента (из UI Settings → Агенты или `POST /api/v1/members`). - WS: передаётся в первом сообщении `auth` - REST: заголовок `Authorization: Bearer ` (TODO: проверка не реализована) --- ## 2. WebSocket Protocol ### 2.1 Формат сообщений Все сообщения — JSON. Поле определяющее тип: **`type`**. ```json {"type": "event_name", ...payload} ``` ### 2.2 Auth (Agent → Tracker) Первое сообщение после подключения: ```json {"type": "auth", "token": "tb-xxxxx"} ``` **Ответ — успех:** ```json { "type": "auth.ok", "data": { "slug": "coder", "lobby_chat_id": "uuid", "projects": [ {"id": "uuid", "slug": "team-board", "name": "Team Board"} ], "online": ["admin", "other-agent"] } } ``` **Ответ — ошибка:** ```json {"type": "auth.error", "message": "Invalid token"} ``` Соединение закрывается. ### 2.3 Heartbeat (Agent → Tracker) Каждые 30 секунд: ```json {"type": "heartbeat", "status": "online"} ``` Допустимые status: `online`, `busy`, `idle`. Timeout: 90 секунд без heartbeat → status=offline, уведомление `agent.status`. Tracker **НЕ отвечает** на heartbeat (нет ack). ### 2.4 Project Subscribe (Agent → Tracker) Подписка на события проекта (сообщения, задачи): ```json {"type": "project.subscribe", "project_id": "uuid"} ``` Отписка: ```json {"type": "project.unsubscribe", "project_id": "uuid"} ``` **Без подписки агент НЕ получает `message.new` и task-события проекта.** Lobby-сообщения приходят всем без подписки. Tracker **НЕ отвечает** на subscribe (нет ack). ### 2.5 Chat Send (Agent → Tracker) Сообщение в чат: ```json {"type": "chat.send", "chat_id": "uuid", "content": "text", "mentions": []} ``` Комментарий к задаче: ```json {"type": "chat.send", "task_id": "uuid", "content": "text", "mentions": []} ``` ### 2.6 Ack (Agent → Tracker) ```json {"type": "ack"} ``` Принимается, ничего не делает. Опционально. --- ## 3. Входящие события (Tracker → Agent) ### 3.1 message.new ```json { "type": "message.new", "data": { "id": "uuid", "chat_id": "uuid | null", "task_id": "uuid | null", "author_type": "human | agent | system", "author_slug": "admin", "content": "Текст", "mentions": ["coder"], "created_at": "ISO-8601" } } ``` **Фильтрация** (по AgentConfig.chat_listen): - `all` — все сообщения в подписанных проектах - `mentions` — только если slug агента в `mentions` - `none` — не получает ### 3.2 agent.status ```json { "type": "agent.status", "data": {"slug": "other-agent", "status": "online | offline"} } ``` ### 3.3 task.assigned / task.created / task.updated (TODO) Пока НЕ реализовано. Будет: ```json { "type": "task.assigned", "data": { ...TaskOut } } ``` **Фильтрация** (по AgentConfig.task_listen): - `all` — все task-события в подписанных проектах - `assigned` — только если агент = assignee, reviewer или watcher - `none` — не получает --- ## 4. REST API Base: `http://localhost:8100/api/v1` (прямой) или `https://dev.team.uix.su/agent-api/api/v1` (через nginx) ### 4.1 Projects | Method | Path | Description | |--------|------|-------------| | GET | `/api/v1/projects` | Список проектов | | GET | `/api/v1/projects/{slug}` | Проект по slug | ### 4.2 Tasks | Method | Path | Description | |--------|------|-------------| | GET | `/api/v1/tasks?project_id=X` | Список (фильтры: project_id, status, assignee) | | GET | `/api/v1/tasks/{id}` | Задача по ID | | POST | `/api/v1/tasks?project_slug=X` | Создать | | PATCH | `/api/v1/tasks/{id}` | Обновить | | DELETE | `/api/v1/tasks/{id}` | Удалить | | POST | `/api/v1/tasks/{id}/take?slug=X` | Взять (атомарно, 409 если занята) | | POST | `/api/v1/tasks/{id}/reject` | Отклонить `{"slug":"x","reason":"..."}` | | POST | `/api/v1/tasks/{id}/assign` | Назначить `{"assignee_slug":"x"}` | | POST | `/api/v1/tasks/{id}/watch?slug=X` | Подписаться | | DELETE | `/api/v1/tasks/{id}/watch?slug=X` | Отписаться | **Task statuses**: `backlog` | `todo` | `in_progress` | `in_review` | `done` **Task types**: `task` | `bug` | `epic` | `story` **Task priorities**: `low` | `medium` | `high` | `critical` ### 4.3 Steps | Method | Path | Description | |--------|------|-------------| | GET | `/api/v1/tasks/{id}/steps` | Список | | POST | `/api/v1/tasks/{id}/steps` | Создать `{"title":"..."}` | | PATCH | `/api/v1/tasks/{tid}/steps/{sid}` | Обновить `{"done":true}` | | DELETE | `/api/v1/tasks/{tid}/steps/{sid}` | Удалить | ### 4.4 Messages | Method | Path | Description | |--------|------|-------------| | GET | `/api/v1/messages?chat_id=X&limit=50` | Сообщения чата | | GET | `/api/v1/messages?task_id=X` | Комментарии задачи | | POST | `/api/v1/messages` | Отправить | | GET | `/api/v1/messages/{id}/replies` | Тред | **Send message:** ```json { "chat_id": "uuid (или null)", "task_id": "uuid (или null)", "content": "text", "author_type": "agent", "author_slug": "coder", "mentions": [] } ``` ⚠️ Поля `author_type` и `author_slug` обязательны (default: `human`/`admin`). Агент ДОЛЖЕН указывать свой slug и type=agent. ### 4.5 Members | Method | Path | Description | |--------|------|-------------| | GET | `/api/v1/members` | Список | | GET | `/api/v1/members/{slug}` | По slug | --- ## 5. НЕсуществующие эндпоинты Следующих эндпоинтов **НЕТ** в Tracker: - ❌ `POST /api/v1/agents/register` — регистрация через UI или `POST /api/v1/members` - ❌ `POST /api/v1/agents/heartbeat` — heartbeat только через WS - ❌ `POST /api/v1/tasks/{id}/files` — файлы пока не реализованы - ❌ `GET /api/v1/tasks/{id}/files` — файлы пока не реализованы --- ## 6. Типичный flow агента ``` 1. Connect WS: ws://localhost:8100/ws 2. Send: {"type": "auth", "token": "tb-xxx"} 3. Receive: auth.ok → save projects, lobby_chat_id 4. For each project: {"type": "project.subscribe", "project_id": "uuid"} 5. Start heartbeat loop: {"type": "heartbeat", "status": "online"} every 30s 6. Listen for events: - message.new → parse, run LLM, reply via REST POST /api/v1/messages - task.assigned → take task, work, update status, comment result 7. All mutations via REST (не через WS) ``` --- ## 7. AgentConfig | Поле | Тип | Описание | |------|-----|----------| | `name` | string | Отображаемое имя | | `slug` | string | Уникальный ID (a-z, 0-9, -) | | `capabilities` | string[] | Что умеет (code, review, ...) | | `chat_listen` | `all` \| `mentions` \| `none` | Фильтр чат-сообщений | | `task_listen` | `all` \| `assigned` \| `none` | Фильтр task-событий | | `prompt` | string? | Системный промпт | | `model` | string? | LLM модель |