Responses
Вызов POST /v1/responses — чем он отличается от Chat Completions, члены запроса, типизированные элементы ответа и завершающее событие потока.
Быстро
Тот же ключ и тот же base URL, что у остальных операций шлюза. Разговор едет в input, а системный промпт — в instructions.
curl https://api.kumorouter.com/v1/responses \
-H "Authorization: Bearer $KUMO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<model>",
"instructions": "Отвечай одним предложением.",
"input": [
{
"type": "message",
"role": "user",
"content": [{ "type": "input_text", "text": "Объясни токены." }]
}
]
}'Чем он отличается
Это отдельный протокол, а не другое написание Chat Completions. Пять различий видны сразу.
- Разговор — это
input: один упорядоченный список типизированных элементов. Ход, вызов инструмента и результат вызова — три вида элемента, а не члены одного сообщения. - Системный промпт — это
instructions, член запроса. Он становится ведущим системным ходом разговора, впереди всех элементовinput. - Ответ — это
output: список элементов, а неchoices. - Ответ заявляет
status— стадию жизненного цикла,completedилиincomplete, — а не причину остановки. Два словаря не переводятся друг в друга. - Потолок вывода необязателен: запрос без
max_output_tokensотвечается по опубликованному умолчанию этой поверхности в 32768 токенов. Явный ноль отвергается: это просьба не выводить ничего.
Часть членов протокола эта поверхность принимает и не пересылает, и каждый говорит об этом сам: parallel_tool_calls, reasoning, prompt_cache_key, client_metadata и text.verbosity. Они не отвергаются и не исполняются молча — они не делают ничего. include — наполовину из них: значения, под которые эта поверхность публикует ответ, пересылаются, остальные не делают ничего.
store принимается только со значением false, и его отсутствие значит false. Платформа не хранит ни промптов, ни ответов, ни чанков, поэтому хранить и потом отдавать здесь нечего, а true отвергается, а не принимается с молчаливым невыполнением. По той же причине previous_response_id проверяется на принадлежность вашей организации, но не служит серверным контекстом: продолжать не из чего, контекст присылает клиент.
Члены запроса
modelОбязателен. Модель, которой отвечать: каноническое имя или псевдоним из опубликованного каталога.inputОбязателен. Разговор по порядку, типизированными элементами; от одного до 512.instructionsСистемный промпт. Становится ведущим системным ходом разговора.max_output_tokensПотолок вывода. Без него действует умолчание поверхности в 32768 токенов; явный ноль отвергается.streamОтвечать ли потоком собственными именованными событиями этого протокола.textКак оформлен текст ответа. Здесь же и требование структурированного вывода — в `text.format`.toolsИнструменты этого хода. Объявляются плоско: `type`, `name`, `parameters`.tool_choiceЧто запрос требует от своего списка инструментов: строка `auto`, `none` или `required` либо объект, называющий один объявленный инструмент.storeПринимается только `false`.previous_response_idОтвет вашей же организации, за которым идёт этот запрос. Проверяется на принадлежность и серверным контекстом не служит.parallel_tool_callsПринимается и не пересылается.reasoningПринимается и не пересылается.includeПересылается для значений, под которые эта поверхность публикует ответ, — сегодня это ровно `reasoning.encrypted_content`: именно эта просьба заставляет поставщика подписать зашифрованную запись на элементах `reasoning` в вашем ответе. Отправьте эти элементы обратно во `input` на следующем ходу — и модель продолжит с отчёта, который подписала сама; без записи не продолжит. Любое другое значение принимается и не делает ничего: `include` просит поставщика ДОБАВИТЬ элементы в ответ, а элемент, которого эта поверхность не публикует, она отвергает как нарушение контракта поставщика — то есть пересылка такого значения превратила бы работающий запрос в неработающий. Сам член не отвергается никогда: клиенты, которые его шлют, шлют его на каждом запросе.prompt_cache_keyПринимается и не пересылается.client_metadataПринимается и не пересылается: платформа не описывает поставщику ваши сессии.Виды элементов входа
messageХод разговора: `role` (`system`, `user`, `developer`, `assistant`) и `content` частями `input_text` или `output_text`. Ход `developer` несётся как системный: это одна роль под двумя именами.function_callВызов, который модель сделала раньше: `call_id`, `name` и `arguments` текстом JSON, плюс `namespace`, в котором инструмент был объявлен, если запрос объявлял инструменты группами.function_call_outputРезультат работы инструмента: `call_id` и `output` текстом.custom_tool_callВызов инструмента, объявленного как `custom`: `call_id`, `name`, необязательный `namespace` и `input` — ответ модели на языке самого инструмента, а не JSON. Пустой `input` — законный ответ и посылается пустой строкой.custom_tool_call_outputРезультат его работы: `call_id` и `output`. Результат отвечает вызову своего вида: `custom_tool_call_output` отвечает `custom_tool_call`, а `function_call_output` — `function_call`.reasoningСобственный отчёт модели о прошлом ходе, переигранный: `id`, обязательный `summary` частями `summary_text`, необязательный `content` частями `reasoning_text`, `encrypted_content` и `status`. Платформа ничего из этого не читает — всё уезжает поставщику, который это и произвёл.web_search_callПоиск, который поставщик уже выполнил, переигранный: `id`, `status` и необязательный `action`. Отвечать на него некому.additional_toolsОбъявления инструментов, сгруппированные в пространства имён, — туда их кладут новейшие клиенты этого протокола вместо `tools`. Допускается первым элементом входа и только один.Второй ход
Платформа не хранит ответов, поэтому ваш клиент несёт свою историю сам — а история у него та, которую дал ему ответ. Каждый элемент, которым эта поверхность отвечает, принимается обратно во `input`, в тех же членах, в которых он был опубликован: переиграть ответ дословно — законный запрос. Единственное исключение — часть содержимого refusal: отказ завершает обмен, которому принадлежит, и обратно ходом эта поверхность его не принимает.
Ответ
idЛичность запроса в Kumo — та же, которую называет `previous_response_id`.objectВсегда `response`.created_atМомент ответа, целыми секундами эпохи Unix.modelИмя, которое назвал запрос, возвращённое ровно тем же.status`completed` или `incomplete`.outputЧто произвела модель, по порядку: элементы `message`, `function_call`, `custom_tool_call`, `web_search_call` и `reasoning`.usage`input_tokens`, `output_tokens`, `total_tokens`. Отсутствует, если поставщик не сообщил расхода вовсе.Части элемента message бывают двух видов: output_text — текст ответа, refusal — собственный отказ модели отвечать.
Элемент reasoning — собственный отчёт модели о том, как она пришла к ответу; рассуждающая модель ставит его первым, перед сообщением, которое он объясняет. Он несёт id, обязательный summary частями summary_text — присутствующий и пустой, если модель ничего не резюмировала, — необязательный content частями reasoning_text, encrypted_content, если вы попросили его через include, и status. Платформа ничего из этого не читает и ничего не хранит. Отправьте его обратно во `input` на следующем ходу, в тех же членах, в которых он опубликован: именно этого протокол просит от клиента, который несёт свой контекст сам, и именно это позволяет рассуждающей модели продолжить с того места, где она остановилась.
{
"id": "resp-4d19a0b7c2",
"object": "response",
"created_at": 1756900000,
"model": "<model>",
"status": "completed",
"output": [
{
"type": "message",
"role": "assistant",
"content": [{ "type": "output_text", "text": "Токены — куски текста, которыми модель меряет ввод и вывод." }]
}
],
"usage": { "input_tokens": 14, "output_tokens": 21, "total_tokens": 35 }
}Поток
"stream": true даёт text/event-stream в именованных событиях этого протокола: сначала response.created, затем элементы вывода и их дельты, затем ровно одно завершающее событие — response.completed с готовым телом и расходом либо response.failed с конвертом ошибки этого протокола.
Все события и правило завершающего кадра →