docs: AGENT-PROTOCOL.md v1.0 — single source of truth
This commit is contained in:
parent
49ac1f5261
commit
58388d3021
279
AGENT-PROTOCOL.md
Normal file
279
AGENT-PROTOCOL.md
Normal 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 модель |
|
||||
Loading…
Reference in New Issue
Block a user