OpenClaw Agent — API
URL-префикс: /api/v1/admin/agent/* (через admin-bff проксируется напрямую без преобразований).
Все эндпоинты требуют Authorization: Bearer <JWT>. Проверяется permission agent.use.
Чат (главный эндпоинт)
POST /api/v1/admin/agent/chat
Отправить сообщение в существующую или новую сессию. Возвращает SSE-стрим хода рассуждений + результат.
Request body:
{
"conversation_id": "conv_01HXYZ...",
"message": "Создай заказ на маргариту и колу на вынос для точки Арбат"
}conversation_idопционален. Если нет → создаётся новая сессия.messageобязателен, ≤ 2000 символов.
Response — text/event-stream:
event: conversation
data: {"conversation_id": "conv_01HXYZ...", "is_new": false}
event: message_started
data: {"message_id": "msg_01ABCD...", "role": "assistant"}
event: thinking
data: {"text": "Ищу товары: маргарита, кола"}
event: tool_call_started
data: {"tool_call_id": "call_1", "name": "find_products", "arguments": {"query": "маргарита", "store_id": "store_arbat"}}
event: tool_call_completed
data: {"tool_call_id": "call_1", "status": "ok", "duration_ms": 124, "summary": "Найдено: Пицца Маргарита (590 ₽)"}
event: tool_call_started
data: {"tool_call_id": "call_2", "name": "find_products", "arguments": {"query": "кола", "store_id": "store_arbat"}}
event: tool_call_completed
data: {"tool_call_id": "call_2", "status": "ok", "summary": "Найдено: Кока-кола (260 ₽)"}
event: tool_call_started
data: {"tool_call_id": "call_3", "name": "create_order", "arguments": {"store_id": "store_arbat", "channel": "takeaway", "items": [...]}}
event: tool_call_completed
data: {"tool_call_id": "call_3", "status": "ok", "summary": "Заказ #1234 создан, сумма 850 ₽"}
event: content_delta
data: {"text": "Заказ "}
event: content_delta
data: {"text": "#1234 "}
event: content_delta
data: {"text": "создан. Пицца Маргарита, Кока-кола, сумма 850 ₽."}
event: message_completed
data: {"message_id": "msg_01ABCD...", "finish_reason": "stop", "total_duration_ms": 12450, "eval_tokens": 187}
event: done
data: {}
Event types:
| Event | Когда отправляется | Payload |
|---|---|---|
conversation | В начале, если новая или возобновлена | { conversation_id, is_new } |
message_started | Перед первым токеном assistant-ответа | { message_id, role } |
thinking | Короткие пояснения агента (генерируется в content до tool_call) | { text } |
tool_call_started | Перед каждым HTTP-вызовом downstream | { tool_call_id, name, arguments } |
tool_call_completed | После результата tool | { tool_call_id, status: "ok"|"error", duration_ms, summary?, error? } |
content_delta | Дельта текстового ответа ассистента | { text } |
message_completed | Финальный токен (finish_reason=stop) | { message_id, finish_reason, total_duration_ms, eval_tokens } |
error | Любая ошибка во время стрима | { code, message } |
done | Конец стрима | {} |
Ошибки в начале (до стрима):
| HTTP | Code | Когда |
|---|---|---|
| 400 | MESSAGE_TOO_LONG | message > 2000 |
| 403 | AGENT_ACCESS_DENIED | Нет agent.use |
| 404 | CONVERSATION_NOT_FOUND | conversation_id не найден или чужой |
| 409 | CONVERSATION_LIMIT_REACHED | В сессии уже 20 ходов |
| 429 | RATE_LIMIT_EXCEEDED | Превышен per-user limit |
| 503 | LLM_HOST_UNAVAILABLE | LLM-провайдер недоступен |
Ошибки внутри стрима:
Эмитятся через event: error с продолжением стрима до event: done. Клиент должен отобразить error-блок в UI и оставить чат активным.
Сессии
GET /api/v1/admin/agent/conversations
Список моих сессий, отсортированных по updated_at DESC.
Query:
limit(default 50, max 100)cursor(опаковый, для пагинации)status(active/closed, default — все)
Response 200:
{
"data": [
{
"id": "conv_01HXYZ...",
"title": "Создай заказ на маргариту и колу",
"status": "active",
"messages_count": 8,
"created_at": "2026-05-13T10:00:00Z",
"updated_at": "2026-05-13T10:05:42Z"
}
],
"meta": { "next_cursor": null, "total": 1 }
}GET /api/v1/admin/agent/conversations/{id}
История одной сессии — все сообщения в порядке создания.
Response 200:
{
"id": "conv_01HXYZ...",
"title": "...",
"status": "active",
"messages": [
{
"id": "msg_01...",
"role": "user",
"content": "Создай заказ...",
"created_at": "..."
},
{
"id": "msg_02...",
"role": "assistant",
"content": "Заказ #1234 создан...",
"tool_calls": [{ "id": "call_1", "name": "find_products", ... }],
"duration_ms": 12450,
"created_at": "..."
},
{
"id": "msg_03...",
"role": "tool",
"tool_call_id": "call_1",
"content": "[{\"id\": \"prd_abc\", \"name\": \"...\"}]",
"created_at": "..."
}
]
}Ошибки:
| HTTP | Code |
|---|---|
| 404 | CONVERSATION_NOT_FOUND (не существует или чужая) |
DELETE /api/v1/admin/agent/conversations/{id}
Удалить сессию вместе со всеми сообщениями.
Response 204 No Content.
POST /api/v1/admin/agent/conversations/{id}/close
Закрыть сессию (status=closed). После этого /chat с этим id будет возвращать 409.
Response 204 No Content.
Health и Admin
GET /internal/agent/health
Без auth.
{
"status": "ok",
"llm_provider": { "reachable": true, "latency_ms": 12 },
"database": { "reachable": true }
}GET /internal/agent/admin/sessions/{user_id}
Service-token. Список сессий любого юзера для аудита.
Requires agent.config у вызывающего (проверяется через JWT в Authorization).
Стандартный формат ошибки
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Превышен лимит запросов. Подожди немного.",
"details": { "retry_after_sec": 38 }
}
}