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(опц.) — модель для чата (см. Модели);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содержит текст исключения).
Связанные разделы
- Удалённое управление через Яндекс.Диск — файловая очередь и десктоп-приложение AgentRemote;
- Управление очередью из интерфейса — диалог промптов и серверный AutoSend;
- Модели — какие модели можно передавать в
model.