docs/AGENT-PROTOCOL.md

294 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 |
---
### 4.6 Attachments (файлы)
Файлы — это аттачменты к сообщениям (Message). Чтобы прикрепить файл к задаче, отправляется сообщение с `task_id` + attachment.
| Method | Path | Description | Status |
|--------|------|-------------|--------|
| POST | `/api/v1/messages/{id}/attachments` | Загрузить файл | **TODO** |
| GET | `/api/v1/attachments/{id}` | Скачать файл | **TODO** |
| GET | `/api/v1/attachments?task_id=X` | Список файлов задачи | **TODO** |
Модель `Attachment` в БД уже есть: `id, message_id, filename, mime_type, size, storage_path`.
---
## 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 модель |