docs: AGENT-PROTOCOL.md v1.0 — single source of truth

This commit is contained in:
Markov 2026-02-23 13:57:31 +01:00
parent 49ac1f5261
commit 58388d3021

279
AGENT-PROTOCOL.md Normal file
View File

@ -0,0 +1,279 @@
# 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 <token>` (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 модель |