Справочник API: сессии, сообщения и чат
Создание и управление сессиями, чтение сообщений и временных вложений, а также получение ответов на вопросы по базе знаний или ответов агента через SSE.
Сессии — это «приватный для пользователя» ресурс; handler внутренне принудительно проверяет принадлежность; на уровне маршрутизации требуется Viewer+. API-ключ: для сессий/чата нужна возможность chat (или full-access); для поиска по сообщениям — message_history; для извлечения знаний — retrieve.
Сессии (/api/v1/sessions)
POST /api/v1/sessions
Назначение: создание сессии. Handler: internal/handler/session/handler.go
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
title | string | Нет | Заголовок |
kind | string | Нет | Пустое значение (по умолчанию) — обычная сессия; assistant — сессия-ассистент aihelpme.ru; другие значения возвращают 400 |
description | string | Нет | Описание |
project_dir | string | Нет | Только для настольной версии: привязывает сессию к одобренному пользователем локальному каталогу проекта (абсолютный путь должен точно совпадать со списком одобренных), иначе возвращается 400 |
Ответ: 201 {"success":true,"data":{Session}} (id,kind,title,description,tenant_id,user_id,is_pinned,last_request_state,created_at,...)
curl -X POST $BASE/api/v1/sessions -H "X-API-Key: $API_KEY" \
-H 'Content-Type: application/json' -d '{"title":"Новый диалог"}'GET /api/v1/sessions
Назначение: список сессий. Handler: internal/handler/session/handler.go
| Параметр запроса | Тип | Обязательно | Описание |
|---|---|---|---|
page / page_size | int | Нет | Постраничная навигация |
keyword | string | Нет | Нечёткий поиск по заголовку |
kind | string | Нет | По умолчанию или при пустом значении возвращаются только обычные сессии, применимо ко всем источникам; assistant — только собственные сессии-ассистенты вызывающего (администратор тоже не видит чужие), сортировка updated_at DESC; другие значения возвращают 400 |
source | string | Нет | Фильтр по источнику (web/embed/api/feishu/wechat/slack/...) |
agent_id | string | Нет | Фильтр по агенту (IM-сессии) |
Ответ: 200 {"success":true,"data":[SessionListItem],"total","page","page_size"}
curl "$BASE/api/v1/sessions?page=1" -H "Authorization: Bearer $TOKEN"GET /api/v1/sessions/:id
Назначение: сведения о сессии.
Ответ: 200 {"success":true,"data":{Session}}
curl $BASE/api/v1/sessions/s-1 -H "Authorization: Bearer $TOKEN"PUT /api/v1/sessions/:id
Назначение: обновление сессии (заголовок/описание/закрепление). Тело запроса: title, description, is_pinned (все необязательны).
Ответ: 200 {"success":true,"data":{Session}}
curl -X PUT $BASE/api/v1/sessions/s-1 -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"title":"Новое название"}'DELETE /api/v1/sessions/:id
Назначение: удаление сессии.
Ответ: 200 {"success":true,"message":"Session deleted successfully"}
curl -X DELETE $BASE/api/v1/sessions/s-1 -H "Authorization: Bearer $TOKEN"DELETE /api/v1/sessions/batch
Назначение: массовое удаление сессий. delete_all:true сохраняет сессии-ассистенты; при удалении по указанным ID действуют прежние правила принадлежности. Тело запроса: {"ids":["s-1"],"delete_all":false} (одно из двух: ids или delete_all:true).
Ответ: 200 {"success":true,"message":"Sessions deleted successfully"}
curl -X DELETE $BASE/api/v1/sessions/batch -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"ids":["s-1","s-2"]}'DELETE /api/v1/sessions/:id/messages
Назначение: очистка сообщений сессии.
Ответ: 200 {"success":true,"message":"Session messages cleared successfully"}
curl -X DELETE $BASE/api/v1/sessions/s-1/messages -H "Authorization: Bearer $TOKEN"POST /api/v1/sessions/:session_id/generate_title
Назначение: генерация заголовка сессии по контекстным сообщениям. Handler: internal/handler/session/title.go
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
messages | []Message | Да (binding:"required") | Сообщения, используемые как контекст |
Ответ: 200 {"success":true,"data":"Сгенерированный заголовок"}
curl -X POST $BASE/api/v1/sessions/s-1/generate_title -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"messages":[{"role":"user","content":"Расскажи о продукте"}]}'POST /api/v1/sessions/:session_id/stop
Назначение: остановка генерируемого ответа. Handler: internal/handler/session/stream.go
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
message_id | string | Да (binding:"required") | ID сообщения ассистента |
Ответ: 200 {"success":true,"message":"Generation stopped"}
curl -X POST $BASE/api/v1/sessions/s-1/stop -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"message_id":"m-1"}'При остановке дополнительные сообщения, ещё не доставленные агенту (см. ниже Добавление сообщений в выполняющийся ответ), также отбрасываются, и новый цикл автоматически не запускается.
POST /api/v1/sessions/:session_id/fork
Назначение: ответвление новой сессии от некоторого исторического сообщения; исходная сессия остаётся без изменений. Ответвить сессию может только её владелец. Handler: internal/handler/session/fork.go
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
message_id | string | Да | Точка ветвления. Сообщение пользователя: копируется история до него, клиент обычно подставляет этот вопрос в поле ввода; сообщение ассистента: копируется история до этого ответа включительно |
title | string | Нет | Заголовок новой сессии, по умолчанию «исходный заголовок (ветка)» |
Скопированные сообщения сохраняют исходную временную шкалу и сгенерированные файлы; новая сессия записывает parent_session_id и forked_from_message_id. Если исходная сессия привязана к песочнице, система создаёт снимок песочницы, и при первом использовании песочницы новая сессия запускается из состояния рабочей области того цикла, что соответствует точке ветвления. Если перенести рабочую область невозможно, ветвление всё равно завершается успешно, но возвращается degraded: true и причина:
reason | Значение |
|---|---|
NO_CHECKPOINT | До точки ветвления нет контрольной точки рабочей области |
SANDBOX_REPLACED | Контрольная точка принадлежит старой песочнице, которую сессия уже сменила |
SANDBOX_GONE | У исходной сессии сейчас нет песочницы, доступной для снимка |
SNAPSHOT_UNSUPPORTED | Бэкенд песочницы не поддерживает снимки или снимок не удался |
Ответ: 200 {"success":true,"data":{"session_id":"ID новой сессии","degraded":false}}. Если исходная сессия генерирует ответ или точка ветвления — незавершённый ответ, возвращается 409 (code: FORK_SOURCE_BUSY); если сессия или сообщение не существует — 404; если точка ветвления не является сообщением пользователя или ассистента — 400.
curl -X POST $BASE/api/v1/sessions/s-1/fork -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"message_id":"m-3"}'POST /api/v1/sessions/:session_id/rewind
Назначение: откат текущей сессии на месте до некоторого сообщения. Откатить сессию может только её владелец. Handler: internal/handler/session/rewind.go
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
message_id | string | Да | Точка отката. Сообщение пользователя: удаляется оно само и все последующие; сообщение ассистента: этот ответ сохраняется, последующие удаляются |
Сгенерированные файлы удалённых сообщений, подсказки-вопросы и индекс истории чата также очищаются. Если сессия привязана к песочнице, система одновременно сбрасывает /workspace к контрольной точке последнего цикла в сохраняемой истории; при неудачном сбросе рабочей области вся операция завершается неудачей, и сообщения не удаляются.
Ответ: 200 {"success":true,"data":{"deleted_messages":N,"workspace_reset":true,"reason":""}}. Когда workspace_reset равно false, reason объясняет причину отката только диалога: NO_SANDBOX (сессия не привязана к песочнице) или NO_CHECKPOINT (в сохраняемой истории нет контрольной точки).
| Код статуса | code | Значение |
|---|---|---|
| 409 | REWIND_SOURCE_BUSY | Сессия генерирует ответ или точка отката — незавершённый ответ |
| 409 | REWIND_NO_CHECKPOINT | Песочница ещё есть, но в сохраняемой истории не найдена доступная контрольная точка; отказ, чтобы файлы не опережали диалог |
| 409 | REWIND_SANDBOX_REPLACED | Контрольная точка принадлежит уже сменённой старой песочнице |
| 404 | — | Сессия или сообщение не существует |
| 500 | — | Сброс рабочей области не удался, можно повторить |
curl -X POST $BASE/api/v1/sessions/s-1/rewind -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"message_id":"m-3"}'Добавление сообщений в выполняющийся ответ (steer)
Во время генерации ответа в режиме интеллектуального рассуждения повторный вызов agent-chat для той же сессии возвращает 409. В этом случае можно поставить новое сообщение в очередь текущего цикла через следующие эндпоинты. Вызывать может только владелец сессии; у быстрых ответов нет цикла выполнения, в который можно внедряться, поэтому добавление не поддерживается. Handler: internal/handler/session/steer.go
| Метод | Путь | Назначение |
|---|---|---|
| POST | /api/v1/sessions/:session_id/steer | Добавить сообщение |
| GET | /api/v1/sessions/:id/steer | Вывести очередь сообщений, ещё не доставленных в текущем цикле, для восстановления очереди после перезагрузки страницы; возвращает assistant_message_id и items[] (steer_id, content, delivery, mentioned_items); если выполняющегося цикла нет, items пуст |
| DELETE | /api/v1/sessions/:id/steer/:steer_id | Отозвать сообщение из очереди |
| POST | /api/v1/sessions/:session_id/steer/:steer_id/inject | Изменить сообщение after на inject |
Тело запроса POST:
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
query | string | Да | Содержимое сообщения, не более 10 000 символов |
delivery | string | Нет | after (по умолчанию): после завершения текущего цикла отправляется как вопрос следующего цикла; inject: доставляется агенту на границе следующей итерации текущего цикла (в том числе прямо перед выдачей финального ответа), и агент корректируется и продолжает |
mentioned_items | []object | Нет | Элементы @упоминания, формат как в запросе чата |
steer_id | string | Нет | Сгенерированный клиентом UUID для дедупликации при повторных попытках; один и тот же ID с разным содержимым возвращает 409 |
expected_assistant_message_id | string | Нет | ID выполняющегося сообщения ассистента, который видит клиент; если цикл переключился, возвращается 409, и клиент должен повторить |
channel | string | Нет | Источник (канал) |
status в ответе:
status | Значение |
|---|---|
queued | Поставлено в очередь; возвращаются steer_id, delivery и assistant_message_id |
new_run | Сейчас нет выполняющегося цикла; клиент должен отправить обычным вызовом agent-chat |
already_injected | Сообщение уже доставлено агенту (может возникнуть при повторной попытке, отзыве или изменении на inject); отозвать нельзя |
deleted / gone | Только DELETE: отозвано (removed показывает, действительно ли удалено сообщение) / сейчас нет выполняющегося цикла |
В каждом цикле одновременно может стоять в очереди не более 10 недоставленных сообщений; при превышении возвращается 400. После нормального завершения текущего цикла первое недоставленное сообщение сервер сразу запускает как вопрос следующего цикла, а остальные переходят в этот цикл с прежним способом доставки; у этого цикла нет соответствующего соединения agent-chat, поэтому получить его можно, вызвав continue-stream с assistant_message_id, возвращённым GET /steer. Когда пользователь останавливает генерацию, все недоставленные сообщения отбрасываются. Доставленные сообщения записываются в историю сессии, и клиент уведомляется событием user_message_injected. Если не удаётся узнать состояние выполнения, возвращается 503; можно повторить.
curl -X POST $BASE/api/v1/sessions/s-1/steer -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"query":"Только данные за 2024 год","delivery":"inject"}'POST /api/v1/sessions/:session_id/pin и DELETE /api/v1/sessions/:id/pin
Назначение: закрепить / снять закрепление сессии. Без тела запроса. Handler: internal/handler/session/handler.go
Ответ: 200 {"success":true,"is_pinned":true|false}
curl -X POST $BASE/api/v1/sessions/s-1/pin -H "Authorization: Bearer $TOKEN"
curl -X DELETE $BASE/api/v1/sessions/s-1/pin -H "Authorization: Bearer $TOKEN"GET /api/v1/sessions/continue-stream/:session_id
Назначение: возобновление активного потока после разрыва (воспроизведение исторических событий + опрос приращений каждые 100 мс). Handler: internal/handler/session/stream.go
| Параметр запроса | Тип | Обязательно | Описание |
|---|---|---|---|
message_id | string | Да | ID сообщения ассистента, которое нужно продолжить |
Ответ: 200 SSE (text/event-stream, формат событий см. в обзоре «Протокол потоковых интерфейсов»). При воспроизведении сохранённых событий последовательные незавершённые приращения answer/thinking/reflection с одним ID события объединяются в один кадр, и текст, получаемый клиентом, который накапливает содержимое по ID события, не меняется; часть push-доставки в реальном времени не объединяется.
curl -N "$BASE/api/v1/sessions/continue-stream/s-1?message_id=m-1" -H "Authorization: Bearer $TOKEN"Графический рабочий стол песочницы
Эти маршруты регистрируются в internal/router/routes_chat.go и пока не включены в Swagger. Поддерживаются только шаблонами рабочего стола Cube/E2B; требования к развёртыванию и проксированию см. в Развёртывание песочницы.
POST /api/v1/sessions/:session_id/sandbox/desktop-ticket
Выдаёт одноразовый WebSocket-билет, действующий две минуты. Требуется действующий сессионный Bearer access token владельца сессии; использовать только API-ключ нельзя. JWT передаётся только в заголовке аутентификации этого POST-запроса.
curl -X POST "$BASE/api/v1/sessions/$SESSION_ID/sandbox/desktop-ticket" \
-H "Authorization: Bearer $TOKEN"Ответ: 200 {"success":true,"data":{"ticket":"<opaque-ticket>","expires_in":120}}.
GET /api/v1/sessions/:id/sandbox/desktop
При WebSocket-рукопожатии используется ?ticket=<opaque-ticket>, обычное JWT-промежуточное ПО не задействуется. Билет привязан к пользователю, пространству, сессии и исходному access token и становится недействительным после однократного использования; использованные, просроченные и неизвестные билеты отклоняются единообразно. Логи прокси не должны записывать query-параметр ticket.
На одну сессию одновременно допускается только одно ретранслирующее соединение. В состояниях «песочница не привязана», «приостановлена», «рабочий стол не поддерживается» или «запуск не удался» WebSocket upgrade может сначала завершиться, а затем соединение разрывается с close reason вроде SANDBOX_NOT_BOUND, SANDBOX_PAUSED, DESKTOP_UNSUPPORTED, DESKTOP_START_FAILED; клиент должен читать причину закрытия.
POST /api/v1/sessions/:session_id/sandbox/desktop/activity
Владелец сессии сообщает об активности клавиатуры и мыши; ответ 200 {"success":true}. Используется для продления только когда серверный RFB-парсер работает в режиме деградации; при нормальном парсере игнорируется, и продлевать время жизни песочницы опросом не следует.
Вложения сессии (временные документы)
Handler: internal/handler/session/temporary_document.go
POST /api/v1/sessions/:session_id/attachments
Назначение: загрузка и сохранение вложения сессии. После сохранения оно сразу ставится в очередь фонового разбора — завершение загрузки не означает, что разбор закончен. Быстрый ответ ждёт незавершённый разбор после установки потока ответа; интеллектуальное рассуждение читает текст по мере надобности через read_file, дожидаясь неготовых документов только в момент чтения. Отдельно загруженные изображения при включённой загрузке изображений сначала ждут готовности. Поля multipart: file (обязательно), agent_id (необязательно; определяет движок разбора/ASR-модель), parser_engine (необязательно; при использовании общего агента игнорируется — определяется правилами разбора агента).
Ответ: 202 {"success":true,"data":{TemporaryDocument}} (id,session_id,file_name,file_type,file_size,status(uploaded/processing/ready/failed),resource_ref,...)
curl -X POST $BASE/api/v1/sessions/s-1/attachments -H "Authorization: Bearer $TOKEN" -F 'file=@notes.pdf'uploaded — допустимое для отправки состояние сохранённого вложения; клиент не должен ждать ready, чтобы разрешить вопрос. Вложения, на которые ссылаются действующие сообщения сессии (включая ветвления), не удаляет фоновая очистка со стандартным TTL 24 часа; фоновой очистке поддаются только неиспользованные просроченные файлы.
GET /api/v1/sessions/:id/attachments
Назначение: список вложений.
Ответ: 200 {"success":true,"data":[TemporaryDocument]}
curl $BASE/api/v1/sessions/s-1/attachments -H "Authorization: Bearer $TOKEN"GET /api/v1/sessions/:id/attachments/:attachment_id
Назначение: сведения о вложении (включая статус разбора).
Ответ: 200 {"success":true,"data":{TemporaryDocument}}
curl $BASE/api/v1/sessions/s-1/attachments/a-1 -H "Authorization: Bearer $TOKEN"GET /api/v1/sessions/:id/attachments/:attachment_id/preview
Назначение: предпросмотр исходного файла вложения.
Ответ: 200 поток файла (Content-Disposition: inline|attachment, Cache-Control: private).
curl $BASE/api/v1/sessions/s-1/attachments/a-1/preview -H "Authorization: Bearer $TOKEN" -o preview.pdfDELETE /api/v1/sessions/:id/attachments/:attachment_id
Назначение: удаление вложения.
Ответ: 204 No Content
curl -X DELETE $BASE/api/v1/sessions/s-1/attachments/a-1 -H "Authorization: Bearer $TOKEN"Подсказки к ответу (Suggestions)
Handler: internal/handler/message_suggestion.go
GET /api/v1/sessions/:id/messages/:message_id/suggestions
Назначение: чтение подсказок-вопросов к сообщению ассистента.
Ответ: 200 {"success":true,"data":{MessageSuggestionSet}} (status(generating/ready/suppressed/failed),questions:[{id,text,category,source,knowledge_base_ids}],allow_regenerate,...)
curl $BASE/api/v1/sessions/s-1/messages/m-1/suggestions -H "Authorization: Bearer $TOKEN"POST /api/v1/sessions/:session_id/messages/:message_id/suggestions
Назначение: гарантировать генерацию подсказок (идемпотентный запуск). Тело запроса: {"regenerate":true} (необязательно; принудительная повторная генерация).
Ответ: 200 (готово) или 202 (в процессе генерации) {"success":true,"data":{MessageSuggestionSet|null}}
curl -X POST $BASE/api/v1/sessions/s-1/messages/m-1/suggestions -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{}'POST /api/v1/sessions/:session_id/suggestion-events
Назначение: отправка событий взаимодействия с подсказками (телеметрия).
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
suggestion_set_id | string | Да (binding:"required") | ID набора подсказок |
question_id | string | Нет | Обязательно при click/regenerate |
event_type | string | Да (binding:"required") | impression/click/dismiss/regenerate |
Ответ: 204 No Content
curl -X POST $BASE/api/v1/sessions/s-1/suggestion-events -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"suggestion_set_id":"ss-1","event_type":"impression"}'Чат и извлечение
Handler: internal/handler/session/qa.go. API-ключ: для чата нужен chat/full; для knowledge-search — retrieve/full.
POST /api/v1/knowledge-chat/:session_id
Назначение: вопросно-ответная система по базе знаний (поток SSE).
Тело запроса (общее для KnowledgeQA/AgentQA):
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
query | string | Обычно обязателен | Вопрос пользователя; при непустых встроенных images[].data или attachment_uploads[].data текст можно не вводить — система сгенерирует вопрос по умолчанию. При переданных только attachment_ids или URL изображения текст опустить нельзя; недопустимые символы или запрос без содержимого возвращают 400 |
knowledge_base_ids | []string | Нет | Базы знаний для извлечения |
knowledge_ids | []string | Нет | Ограничить файлами знаний |
agent_enabled | bool | Нет | Включён ли режим агента |
agent_id | string | Нет | ID пользовательского агента |
agent_source_tenant_id | uint64 | Нет | Исходное пространство общего агента; используется для различения одноимённых общих агентов из разных пространств |
reasoning_effort | string | Нет | Интенсивность рассуждений в этом цикле: off, auto, minimal, low, medium, high, xhigh, max (none/false считаются off, true/on — auto); при пропуске используется конфигурация агента. Действует только на этот цикл и не изменяет агента; если модель не поддерживает выбранный уровень, он автоматически подбирается к ближайшему. Недопустимое значение возвращает 400 |
web_search_enabled | bool | Нет | Поиск в интернете; действует, только если у самого агента включён поиск в интернете |
local_browser_enabled | bool | Нет | Разрешить в этом цикле использовать подключённый локальный браузер; допустимо только для agent-chat агента интеллектуального рассуждения, иначе возвращается 400. См. Локальный браузер |
summary_model_id | string | Нет | Модель суммаризации; при использовании общего агента игнорируется, всегда применяется модель из конфигурации агента |
mcp_service_ids | []string | Нет | MCP-сервисы, упомянутые через @ |
skill_names | []string | Нет | Навыки, упомянутые через @ |
tag_ids | []string | Нет | Фильтр по тегам |
mentioned_items | []object | Нет | Элементы @упоминания (type/kb_id/kb_name/service_id/skill_name) |
disable_title | bool | Нет | Отключить автоматический заголовок |
images | []object | Нет | Изображения (data base64 / url / caption) |
attachment_uploads | []object | Нет | Встроенные вложения (data base64, file_name, file_size) |
attachment_ids | []string | Нет | ID уже загруженных вложений сессии |
channel | string | Нет | Источник (канал) |
suggestion_attribution | object | Нет | Атрибуция клика по подсказке |
question_origin | object | Нет | Откуда взялся выбранный пользователем подсказанный вопрос: knowledge_base_id, необязательный knowledge_id. Используется только в режиме интеллектуального рассуждения; агент сначала выполняет поиск по этому источнику. Если источник не входит в область поиска этого цикла, он игнорируется и область не расширяется |
page_context | object | Нет | Текущая страница: knowledge_base_id, необязательный knowledge_id, wiki_slug, wiki_issue_ids (максимум 20 элементов) либо agent_id. База знаний должна входить в область поиска этого цикла; агент проверяет её самостоятельно — она должна быть видима текущему пространству (встроенные агенты поддерживаются). Недопустимые части отбрасываются, права поиска не расширяются |
assistant_access | string | Нет | Уровень прав ассистента aihelpme.ru: read_only, confirm, auto_write; по умолчанию confirm, ограничивается допустимым уровнем пространства |
Выбранный reasoning_effort записывается в last_request_state.reasoning_effort сессии; при повторном открытии сессии фронтенд восстанавливает его по этому значению.
Ответ: поток 200 SSE, event: message + data: StreamResponse (см. обзор), завершается событием complete. Если ответ обрезан из-за ограничения модели на один вывод, событие answer несёт data.truncated: true, а сгенерированное до обрезки содержимое сохраняется как обычно.
curl -N -X POST $BASE/api/v1/knowledge-chat/s-1 -H "X-API-Key: $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"query":"Какова политика возврата?","knowledge_base_ids":["kb-1"]}'POST /api/v1/agent-chat/:session_id
Назначение: вопросно-ответная система агента (поток SSE, включая события thinking/tool_call/tool_result/tool_approval_required/mcp_oauth_required и др.). Тело запроса такое же, как выше.
- Ошибка выполнения инструмента возвращается событием
tool_result(data.success: false,data.error— причина), и агент продолжает обработку; событиеerrorозначает провал всего цикла выполнения. - Когда агент в середине процесса принимает добавленное сообщение, отправляется
user_message_injected; во время выполнения команды вывод карточки инструмента обновляется событиемcommand_output. - Если в той же сессии уже генерируется ответ интеллектуального рассуждения, возвращается 409; в этом случае для добавления сообщения следует использовать интерфейс steer.
curl -N -X POST $BASE/api/v1/agent-chat/s-1 -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"query":"Проанализируй данные за прошлый квартал","agent_id":"agent-1"}'POST /api/v1/knowledge-search
Назначение: извлечение знаний без сессии (не потоковое), предпочтительный интерфейс для внешних систем, получающих результаты поиска. Использует тот же конвейер извлечения, что и ответы на вопросы внутри продукта (recall → rerank → merge → truncate), а порядок совпадает с ответами на странице. Как выбирать между этим и hybrid-search см. в Как выбрать интерфейс поиска. Handler: SearchKnowledge в internal/handler/session/qa.go.
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
query | string | Да (binding:"required") | Запрос |
knowledge_base_id | string | Нет | Одна база знаний (совместимость со старыми версиями) |
knowledge_base_ids | []string | Нет | Несколько баз знаний |
knowledge_ids | []string | Нет | Указать файлы; объединяется с knowledge_base_id(s) в единый набор (см. пояснение ниже) |
tag_ids | []string | Нет | Фильтр по тегам |
mentioned_items | []object | Нет | Упоминания тегов с областью базы знаний |
vector_threshold / keyword_threshold | float | Нет | Пороги извлечения; при пропуске используется конфигурация поиска пространства (по умолчанию 0.15 / 0.3) |
match_count | int | Нет | Число возвращаемых записей, максимум 200; при пропуске используется rerank_top_k из конфигурации пространства (по умолчанию 10). Глубина извлечения автоматически увеличивается до значения не меньше этого |
disable_keywords_match / disable_vector_match | bool | Нет | Отключить одну из ветвей извлечения; если обе равны true, возвращается 400 |
rerank | object | Нет | Переопределение настроек rerank; {"enabled":false} отключает rerank. Поля см. в объекте rerank. При одновременном указании rerank.top_k он имеет приоритет над match_count |
Пропущенные поля берут значения из конфигурации поиска пространства (GET /tenants/kv/retrieval-config); при отсутствии новых полей поведение прежнее.
Область поиска — объединение knowledge_base_id(s) и knowledge_ids, что совпадает со смыслом @упоминаний в продукте: каждая база знаний ищется целиком, входящие в неё файлы из knowledge_ids уже покрыты и отдельно не ограничиваются; файлы из других баз знаний добавляются к поиску дополнительно. Если нужно искать только в указанных файлах, передавайте только knowledge_ids и не указывайте вместе с ними их базы знаний — иначе будет просканирована вся база знаний.
Ответ: 200 {"success":true,"data":[SearchResult],"meta":{"rerank":{...}}}. SearchResult содержит id,content,knowledge_id,knowledge_title,score,chunk_type,knowledge_base_id,...; у результатов после rerank в metadata есть model_score и base_score. Когда data пуст, причину определяют по meta.rerank.outcome; см. Диагностика meta.rerank.
curl -X POST $BASE/api/v1/knowledge-search -H "X-API-Key: $API_KEY" \
-H 'Content-Type: application/json' -d '{"query":"Требования к развёртыванию","knowledge_base_ids":["kb-1"]}'
# Только векторное извлечение, 5 записей, rerank отключён
curl -X POST $BASE/api/v1/knowledge-search -H "X-API-Key: $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"query":"Требования к развёртыванию","knowledge_base_ids":["kb-1"],"disable_keywords_match":true,"match_count":5,"rerank":{"enabled":false}}'
# Искать только в указанных файлах (без knowledge_base_ids)
curl -X POST $BASE/api/v1/knowledge-search -H "X-API-Key: $API_KEY" \
-H 'Content-Type: application/json' -d '{"query":"Требования к развёртыванию","knowledge_ids":["k-1","k-2"]}'Сообщения (/api/v1/messages)
Handler: internal/handler/message.go
POST /api/v1/messages/search
Назначение: поиск по истории чата. Права: Viewer+; API-ключ message_history/full.
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
query | string | Да (binding:"required") | Запрос |
mode | string | Нет | keyword/vector/hybrid (по умолчанию hybrid) |
limit | int | Нет | По умолчанию 20 |
session_ids | []string | Нет | Ограничить сессиями |
Ответ: 200 {"success":true,"data":{"total":N,"results":[{session_id,message_id,role,content,created_at,score}]}}
curl -X POST $BASE/api/v1/messages/search -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"query":"Коммерческое предложение"}'GET /api/v1/messages/chat-history-stats
Назначение: статистика индекса истории чата. Права: Viewer+; API-ключ message_history/full.
Ответ: 200 {"success":true,"data":{indexed_message_count,knowledge_base_size,last_indexed_at,...}}
curl $BASE/api/v1/messages/chat-history-stats -H "Authorization: Bearer $TOKEN"GET /api/v1/messages/:session_id/load
Назначение: загрузка сообщений сессии (пагинация по временному курсору назад). Права: Viewer+; API-ключ chat/full.
| Параметр запроса | Тип | Обязательно | Описание |
|---|---|---|---|
limit | int | Нет | По умолчанию 20 |
before_time | string | Нет | Метка времени RFC3339/RFC3339Nano |
Ответ: 200 {"success":true,"data":[Message]} (id,session_id,role,content,is_completed,images,attachments,agent_steps,...)
curl "$BASE/api/v1/messages/s-1/load?limit=20" -H "X-API-Key: $API_KEY"DELETE /api/v1/messages/:session_id/:id
Назначение: удаление одного сообщения. Права: Viewer+ (handler проверяет принадлежность сессии); API-ключ chat/full.
Ответ: 200 {"success":true,"message":"Message deleted successfully"}
curl -X DELETE $BASE/api/v1/messages/s-1/m-1 -H "Authorization: Bearer $TOKEN"Сгенерированные файлы сессии
Следующие интерфейсы требуют Viewer+, API-ключ chat или full-access, и проверяют принадлежность сессии. Для несуществующих или недоступных сессий возвращается 404.
| Метод | Путь | Ответ |
|---|---|---|
| GET | /api/v1/sessions/:id/artifacts | 200 {success:true,data:[Artifact]}, сводка файлов сессии |
| GET | /api/v1/sessions/:id/messages/:message_id/artifacts | То же, только файлы этого сообщения |
| GET | /api/v1/sessions/:id/messages/:message_id/artifacts/:index/download | 200 поток файла, Content-Disposition: attachment |
| DELETE | /api/v1/sessions/:id/messages/:message_id/artifacts/:index | 200 {success:true,data:{file_name,deleted}}, удаление этого файла |
Поля Artifact: index, handle (необязательная ссылка resource://), file_name, file_type, file_size, source_path, mod_time, created_at. Ответ не возвращает URL нижележащего объектного хранилища. Индекс загрузки начинается с 0, и нужно использовать индекс из списка соответствующего сообщения; нельзя брать сводный индекс сессии и подставлять его напрямую в адрес загрузки сообщения. Недопустимый индекс возвращает 400; выход за границы или отсутствие файла — 404.
curl "$BASE/api/v1/sessions/session-1/messages/message-1/artifacts" \
-H "Authorization: Bearer $TOKEN"
curl "$BASE/api/v1/sessions/session-1/messages/message-1/artifacts/0/download" \
-H "Authorization: Bearer $TOKEN" -o result.pdfУдаление сгенерированных файлов
Удаление освобождает байты в объектном хранилище и необратимо. В отличие от загрузки, удаление доступно только владельцу сессии: доступ только для чтения, полученный через общий агент, позволяет скачивать файлы, но не удалять их — чужие сессии всегда обрабатываются как 404 (без различия «не существует» и «нет прав», как и в остальных интерфейсах сессий). Удалённые файлы возвращают 404, повторное удаление также 404.
Байты действительно освобождаются только когда у файла не осталось других держателей: если тот же файл сохранён в базу знаний, повторно использован в последующих ответах или его сессия ответвлена в копию, он сохранится. Неудачное освобождение не влияет на результат удаления (интерфейс всё равно возвращает 200), и файл исчезает из всех списков.
После удаления файл больше не появляется в интерфейсах списков и в библиотеке артефактов, но его позиция в сообщении сохраняется: index — это и есть адрес загрузки, и если последующие файлы сдвинутся, существующие ссылки на загрузку будут указывать на неправильный файл. По той же причине одноимённый файл в песочнице не будет заново собран в следующем цикле — его mtime не изменился из-за удаления пользователем.
| Параметр | Описание |
|---|---|
all_versions | Удалить вместе со всеми историческими версиями с тем же source_path в этой сессии. Логическое значение, по умолчанию false |
curl -X DELETE "$BASE/api/v1/sessions/session-1/messages/message-1/artifacts/0" \
-H "Authorization: Bearer $TOKEN"Список артефактов по всем сессиям
GET /api/v1/artifacts выводит все сгенерированные файлы из веб-диалогов текущего пользователя для страницы «Артефакты» в боковой панели главной страницы. Область та же, что у source=web в списке сессий: собственные сессии и исторические веб-сессии уровня пространства без владельца; IM-каналы, веб-виджеты (embed) и сессии API-ключей не включаются вовсе, даже если у IM-сессии нет владельца в базе. Файлы с одинаковым source_path в одной сессии считаются версиями одного файла, возвращается только последняя версия, а version_count даёт число версий. Файлы удалённых сессий или сообщений не возвращаются. Требования к правам те же, что в таблице выше.
| Параметр | Описание |
|---|---|
keyword | Фильтр по имени файла, без учёта регистра |
file_types | Расширения через запятую, например .pdf,.pptx (точку можно опустить) |
page / page_size | Пагинация; page_size максимум 100, по умолчанию 20 |
Ответ {success, data:[LibraryArtifact], total, page, page_size}, в порядке убывания времени генерации. Поля LibraryArtifact: session_id, session_title, message_id, index, handle (необязательно), file_name, file_type, file_size, source_path, created_at, version_count. При загрузке используйте из них session_id, message_id, index для вызова интерфейса загрузки из таблицы выше.
curl "$BASE/api/v1/artifacts?file_types=.pptx,.pdf&keyword=отчёт&page=1&page_size=30" \
-H "Authorization: Bearer $TOKEN"DELETE /api/v1/artifacts удаляет один файл из библиотеки артефактов, определяя его query-параметрами session_id, message_id, index; семантика та же, что у удаления внутри сессии выше. Различие лишь в том, что при опущенном all_versions он считается true (при явной передаче правила разбора у обоих интерфейсов одинаковы): строка библиотеки артефактов означает один файл (version_count даёт число версий), а не одну конкретную генерацию, поэтому удаление только последней версии оставит эту строку в списке с предыдущей версией. Передав all_versions=false, можно удалить только текущую версию.
curl -X DELETE "$BASE/api/v1/artifacts?session_id=session-1&message_id=message-1&index=0" \
-H "Authorization: Bearer $TOKEN"Ссылки на изображения и файлы в ответах
GET /api/v1/sessions/:id/messages/:message_id/files?file_path=... — это прокси с аутентификацией на уровне сообщения. В file_path передаётся дескриптор ресурса, на который ссылается сообщение, или поддерживаемая ссылка на хранилище; клиент должен URL-кодировать значение. Бэкенд проверяет право доступа к сообщению, привязку ресурса к сообщению и текущее право доступа к базе знаний/общему агенту; произвольный путь к файлу нельзя открыть по ID сессии. После отзыва авторизации ссылки из старых сообщений также отклоняются. Применимо к общим агентам и общим библиотекам организации для изображений в ответах и артефактов сообщений; подробнее см. Доступ к файлам.
Использование за цикл
Сообщения возвращают сохраняемый usage, а событие завершения агента несёт turn_usage; они включают агрегированный результат вызовов моделей по каждому назначению в этом цикле. Вызовы инструментов не все сами по себе порождают токены; использование определяется тем, что вернул провайдер или что уже собрал бэкенд. Поля см. в Наблюдаемость.
Событие завершения в режиме агента несёт в data.model_id ID модели, реально отработавшей в этом цикле (именно она породила текущее использование); по нему через интерфейс моделей можно получить сведения о модели и пересчитать использование по цене. model_id в записи сообщения — модель, привязанная при запросе; если указанная в запросе модель недействительна и происходит откат к модели агента, эти значения различаются. Событие завершения быстрого ответа пока не несёт этого поля.
Справочник по реализации
Регистрация маршрутов: RegisterSessionRoutes, RegisterChatRoutes, RegisterMessageRoutes в internal/router/routes_chat.go (вызываются из internal/router/router.go). Handler: internal/handler/session/ (handler.go, qa.go, stream.go, title.go, temporary_document.go, fork.go, rewind.go, steer.go, artifact_*.go), internal/handler/message.go, internal/handler/message_suggestion.go.
