---
title: "API"
id: "1688"
type: "page"
slug: "api"
published_at: "2026-09-04T04:41:18+00:00"
modified_at: "2026-09-05T01:25:59+00:00"
url: "https://pastukhov.com/agents/agent/docs/api"
markdown_url: "https://pastukhov.com/agents/agent/docs/api.md"
excerpt: "API Pastukhov Agent — это способ отдавать команды агенту и получать ответы без браузера. Другие…"
---

# API

[https://pastukhov.com/agents/agent/docs/api.md](https://pastukhov.com/agents/agent/docs/api.md)

**API Pastukhov Agent — это способ отдавать команды агенту и получать ответы без браузера.** Другие программы могут создавать чаты, отправлять промпты и забирать результаты по набору адресов (эндпоинтов): из сборочных конвейеров, внешних инструментов и обёрток. Тот же ключ открывает и расширенные возможности (чаты, навыки, модели, настройки, git, аналитику и распознавание речи) и подписку на живые события — именно так Research Agent подключается к своему полю ввода, микрофону и аналитике. Раздел ниже — справочник этих адресов для разработчиков; если вы впервые слышите об API, достаточно понять общую идею: программа общается с агентом по тем же правилам, что и человек в интерфейсе.

## Аутентификация

API включается установкой переменной окружения `AGENT_API_KEY`. В ней хранится не сам ключ, а его «отпечаток» (SHA-256 хеш — короткая строка, по которой ключ восстановить нельзя); при каждом запросе сервер вычисляет отпечаток присланного ключа и сравнивает с сохранённым.

Ключ передаётся в заголовке `X-API-Key` — служебном поле запроса, где программа указывает свой ключ доступа:

```
X-API-Key: my-secret-api-key
```

Для живых подключений (WebSocket/SignalR) заголовки задать нельзя, поэтому тот же ключ принимается и как параметр адреса `api_key`:

```
/svelteChatHub?api_key=my-secret-api-key
```

### Как получить хеш ключа

Вычислить отпечаток ключа можно на странице входа приложения (кнопка «SHA256 generator» под формой входа) или вручную:

```
# Linux / macOS
echo -n "my-secret-api-key" | sha256sum | awk '{print $1}'

# Windows PowerShell
$hash = [System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes("my-secret-api-key"))).Replace("-", "").ToLower()
$hash
```

Полученный отпечаток укажите в `AGENT_API_KEY` (переменная уровня приложения, задаётся до запуска — системной переменной, аргументом командной строки или через `.env`).

### Коды при ошибках аутентификации

- **401 Unauthorized** — ключ не передан или неверный;
- **503 Service Unavailable** — переменная `AGENT_API_KEY` не задана: «API disabled», API отключён целиком.

## Команды /api/remote

Эндпоинт — это адрес, по которому программа обращается к серверу, чтобы что-то получить или сделать. Все команды `/api/remote` описаны ниже.

### Создание чата

```
POST /api/remote/chats
```

Создаёт новый чат. Промпт, если он передан, **ставится в очередь** и обрабатывается автоматически — напрямую он не отправляется. Чат можно дополнительно привязать к боту (`botId`); привязка «молчаливая»: она никогда не спамит в Telegram и не может помешать созданию чата, а её исход возвращается флагами `botLinked` и `botLinkNote`.

#### Тело запроса

- `prompt` (опц.) — начальное сообщение; при наличии чат создаётся со статусом `queued`, без него — `created`;
- `title` (опц.) — название чата (по умолчанию «Remote API Chat»);
- `model` (опц.) — модель для чата (см. [Модели](/agents/agent/docs/models) );
- `skill` (опц.) — навык; отсутствие = «none» (без наследования);
- `systemPrompt` (опц.) — системный промпт, сохраняется на чате;
- `botId` (опц.) — id бота для молчаливой привязки чата.

#### Ответ (201 Created)

```
{
  "chatId": 123,
  "url": "/123",
  "status": "queued",
  "createdAt": "2026-09-04T10:00:00Z",
  "botLinked": null,
  "botLinkNote": ""
}
```

#### Пример

```
curl -X POST http://localhost:5173/api/remote/chats \
  -H "X-API-Key: my-secret-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Explain what this code does",
    "title": "Code Analysis",
    "model": "claude-sonnet"
  }'
```

### Статус чата

```
GET /api/remote/chats/{chatId}/status
```

Возвращает текущий статус обработки: `processing` — агент работает, `queued` — чат свободен, но в его очереди есть сообщения, иначе `completed`. Вместе со статусом приходят заголовок, метки времени, количество сообщений и накопленная стоимость. Поле `error` в ответе всегда пустое.

```
{
  "chatId": 123,
  "status": "processing",
  "title": "Code Analysis",
  "createdAt": "2026-09-04T10:00:00Z",
  "updatedAt": "2026-09-04T10:00:15Z",
  "messageCount": 2,
  "totalCost": 0.005
}
```

Пример:

```
curl http://localhost:5173/api/remote/chats/123/status \
  -H "X-API-Key: my-secret-api-key"
```

### Сообщения чата

```
GET /api/remote/chats/{chatId}/messages?since={timestamp}
```

Инкрементальное чтение сообщений — программа забирает только то, что появилось после указанной метки, и не разбирает всю историю заново. Параметр `since` (ISO 8601) возвращает сообщения от указанной метки включительно и сам отражается в ответе; неверное значение `since` молча игнорируется — возвращается полная история. Содержимое упрощается по типу: сообщение пользователя — его текст; ответ агента — текст без разметки кнопок; ошибка — текст ошибки; использование инструмента — `Tool: <имя>`.

```
{
  "chatId": 123,
  "messages": [
    {
      "id": 456,
      "role": "user",
      "content": "Explain what this code does",
      "createdAt": "2026-09-04T10:00:00Z",
      "tokens": { "input": 120, "output": 0 },
      "cost": 0.0001
    },
    {
      "id": 457,
      "role": "assistant",
      "content": "This module handles ...",
      "createdAt": "2026-09-04T10:00:20Z",
      "tokens": { "input": 140, "output": 320 },
      "cost": 0.003
    }
  ],
  "since": "2026-09-04T10:00:00Z"
}
```

Примеры:

```
# Все сообщения
curl http://localhost:5173/api/remote/chats/123/messages \
  -H "X-API-Key: my-secret-api-key"

# Только новые с указанной метки
curl "http://localhost:5173/api/remote/chats/123/messages?since=2026-09-04T10:00:10Z" \
  -H "X-API-Key: my-secret-api-key"
```

### Очередь промптов

Пять команд под `/api/remote/chats/{chatId}/queue` управляют промптами, ожидающими отправки агенту. В отличие от внутренних команд очереди, удалённые строже: неизвестный чат или промпт, которого нет в очереди (никогда не было, принадлежит другому чату или уже отправлен), — ошибка `404`; пустой или состоящий из пробелов текст — `400`.

#### Список очереди

```
GET /api/remote/chats/{chatId}/queue
```

Очередь в порядке отправки: `id`, `prompt`, `isPaused`, `model` (переопределение для сообщения), `createdAt`. Приостановленные промпты включены и помечены `isPaused`.

```
{
  "chatId": 123,
  "prompts": [
    {
      "id": 456,
      "prompt": "Refactor the auth module",
      "isPaused": false,
      "model": "",
      "createdAt": "2026-09-04T10:00:00Z"
    },
    {
      "id": 457,
      "prompt": "Then update the README",
      "isPaused": true,
      "model": "claude-sonnet",
      "createdAt": "2026-09-04T10:01:00Z"
    }
  ]
}
```

#### Добавить промпт в конец очереди

```
POST /api/remote/chats/{chatId}/queue
```

Дописывает промпт в конец очереди (как любой другой источник сообщений). `prompt` обязателен и непустой; `model` — необязательное переопределение модели для этого сообщения. Ответ `201` — добавленный промпт с его id.

```
curl -X POST http://localhost:5173/api/remote/chats/123/queue \
  -H "X-API-Key: my-secret-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Now add unit tests for the refactored module"
  }'
```

#### Переписать текст одного промпта

```
PUT /api/remote/chats/{chatId}/queue/{promptId}
```

Изменяет только текст: id, позиция, модель и пауза строки сохраняются. `400` при пустом тексте; `404`, если промпта нет в очереди этого чата или он уже отправлен.

```
curl -X PUT http://localhost:5173/api/remote/chats/123/queue/456 \
  -H "X-API-Key: my-secret-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "prompt": "Refactor the auth module and update the docs" }'
```

#### Удалить один промпт

```
DELETE /api/remote/chats/{chatId}/queue/{promptId}
```

Удаляет промпт из очереди; успех — `204 No Content`.

```
curl -X DELETE http://localhost:5173/api/remote/chats/123/queue/456 \
  -H "X-API-Key: my-secret-api-key"
```

#### Заменить очередь целиком

```
PUT /api/remote/chats/{chatId}/queue
```

Переданный массив становится всей очередью. Правила замены:

- элемент с `id`, совпавшим с существующим, сохраняет идентичность — ту же строку, модель и паузу (если `isPaused` не задан явно);
- элемент без `id` (или с `id: 0`) создаёт новый промпт;
- существующие промпты, которых нет в массиве, удаляются — включая добавленные другими источниками после вашего последнего чтения (last writer wins);
- порядок массива становится порядком диспетчеризации — перестановка массива меняет очередь;
- пустой массив (`[]`) очищает очередь;
- id уже отправленного промпта пропускается (не воскрешается) — повторная отправка продублировала бы сообщение, которое агент уже обрабатывает.

Ошибки `400`: массив не передан; любой элемент с пустым текстом; один и тот же положительный `id` встречается дважды.

```
curl -X PUT http://localhost:5173/api/remote/chats/123/queue \
  -H "X-API-Key: my-secret-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "prompts": [
      { "id": 457, "prompt": "Refactor the auth module (edited)" },
      { "prompt": "Then update the README" }
    ]
  }'
```

### Список ботов

```
GET /api/remote/bots
```

Только чтение: каждый настроенный бот возвращается с `id`, `title`, `enabled`, `running` и `pollingError` — достаточно, чтобы внешняя программа показала ботов со статусными точками. Никаких токенов, промптов и управления: боты настраиваются только в интерфейсе Pastukhov Agent.

```
{
  "bots": [
    {
      "id": "release-bot",
      "title": "Release Bot",
      "enabled": true,
      "running": true,
      "pollingError": null
    }
  ]
}
```

## Статусы чата

| created | чат создан без начального промпта, ждёт ввода |
| --- | --- |
| queued | чат создан с промптом, сообщение в очереди |
| processing | агент обрабатывает сообщение |
| completed | все сообщения обработаны, чат бездействует |
| error | ошибка обработки (в удалённом API поле error в ответе всегда пустое) |

## Расширенная поверхность по API-ключу

**Тот же ключ открывает гораздо больше, чем `/api/remote`.** Передав его на эти пути, вы действуете под ролью **Manager** — как при входе менеджером:

- `/api/chats`, `/api/chat` — чтение чатов и работа с ними;
- `/svelteChatHub` — живой SignalR-хаб (см. ниже);
- `/api/skills` — навыки (список, выбор);
- `/api/models` — модели (список, выбор);
- `/api/autofix` — статус и переключение автоисправления;
- `/api/settings` — настройки (`settings/all`, `settings/set`);
- `/api/skills-settings` — цвета навыков из `skills.yml`;
- `/api/git` — статус и коммит рабочего репозитория;
- `/api/MessageQueue` — правка, удаление, пауза очереди сообщений;
- `/api/analytics` — аналитика чатов (только чтение);
- `/api/speechrecognition` — транскрибация аудио движками распознавания речи.

Когда ключ не задан или не передан, эти пути работают как раньше — по обычному входу в интерфейс. Ничего не ломается: хранилище ключей и вход в систему сосуществуют.

## Подписка на живые события (SignalR)

Вместо постоянных опросов статуса внешняя система может подписаться на живые события — получать уведомления, когда в чатах что-то происходит. Подключитесь к `/svelteChatHub`, передав ключ заголовком `X-API-Key` или параметром адреса `api_key` (для WebSocket обязателен параметр адреса — заголовки задать нельзя):

```
const connection = new signalR.HubConnectionBuilder()
    .withUrl("http://localhost:5173/svelteChatHub?api_key=my-secret-api-key")
    .build();

connection.on("messageUpdate", (chatId, message) => {
    console.log("Новое сообщение в чате", chatId, message.content);
});

connection.start();
```

События приходят при изменениях: новые сообщения, обновления чатов (включая статусы обработки), изменения очереди сообщений и промптов, смена настроек, навыков и моделей. Для соединений включено аккуратное переподключение — разрыв не теряет подписку. Именно так Research Agent показывает интерфейс Pastukhov Agent.

## Пример рабочего потока

Типичный сценарий: создать чат → опрашивать статус → забрать сообщения → дописать промпт в очередь → заменить очередь. Полный цикл на Python:

```
import time, requests

API_KEY = "my-secret-api-key"
BASE = "http://localhost:5173/api/remote"
H = {"X-API-Key": API_KEY}

# 1. Создать чат — промпт встанет в очередь
resp = requests.post(f"{BASE}/chats", headers=H, json={
    "prompt": "Add error handling to the login endpoint",
    "title": "Error Handling",
    "model": "claude-sonnet"
})
chat_id = resp.json()["chatId"]

# 2. Опрашивать статус до завершения
while True:
    status = requests.get(f"{BASE}/chats/{chat_id}/status", headers=H).json()["status"]
    if status in ("completed", "error"):
        break
    time.sleep(2)

# 3. Забрать ответы (инкрементально через since)
messages = requests.get(f"{BASE}/chats/{chat_id}/messages", headers=H).json()["messages"]
for msg in messages:
    if msg["role"] == "assistant":
        print(msg["content"])

# 4. Дописать follow-up в конец очереди
requests.post(f"{BASE}/chats/{chat_id}/queue", headers=H,
    json={"prompt": "Now add unit tests"})

# 5. Заменить очередь целиком
requests.put(f"{BASE}/chats/{chat_id}/queue", headers=H, json={
    "prompts": [
        {"prompt": "Fix the auth flow"},
        {"prompt": "Update the README"}
    ]
})
```

## Формат ошибок

Все ошибки следуют единому формату `{error, message, details}`:

```
{
  "error": "NotFound",
  "message": "Chat 123 not found",
  "details": ""
}
```

- `Unauthorized` — 401, ключ не передан или неверный;
- `BadRequest` — 400, неверное тело запроса (пустой промпт, дубль id, нет массива);
- `NotFound` — 404, чат или промпт не найден;
- `Remote API is disabled` — 503, переменная `AGENT_API_KEY` не задана;
- `InternalServerError` — 500, неожиданная ошибка сервера (`details` содержит текст исключения).

## Связанные разделы

- [Удалённое управление через Яндекс.Диск](/agents/agent/docs/remote-control) — файловая очередь и десктоп-приложение AgentRemote;
- [Управление очередью из интерфейса](/agents/agent/docs/prompts) — диалог промптов и серверный AutoSend;
- [Модели](/agents/agent/docs/models) — какие модели можно передавать в `model`.

**[← Удалённое управление](/agents/agent/docs/remote-control)**

**[Промпты →](/agents/agent/docs/prompts)**
