[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-ai\u002Fchat\u002Fstreaming":3,"docs-tabs-ai\u002Fchat\u002Fstreaming":6},{"content":4,"lastmod":5},"\n## Потоковая передача (Server-Sent Events)\n\nПри `stream: true` ответ модели приходит потоком событий по мере генерации токенов, а не одним куском в конце. Первый байт доходит до клиента за секунды независимо от полной длины ответа.\n\nЗаголовки ответа: `Content-Type: text\u002Fevent-stream`, `Cache-Control: no-cache`, `Connection: keep-alive`. Каждое событие — строка `data: {JSON}\\n\\n`, завершающее событие — `data: [DONE]\\n\\n`.\n\n## Формат событий\n\n```\ndata: {\"id\":\"chatcmpl-a9f6128818355f17\",\"object\":\"chat.completion.chunk\",\"model\":\"bitrix\u002Fbitrixgpt-5.5\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"CRM\"}}]}\n\ndata: {\"id\":\"chatcmpl-a9f6128818355f17\",\"object\":\"chat.completion.chunk\",\"model\":\"bitrix\u002Fbitrixgpt-5.5\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" — это\"}}]}\n\ndata: {\"id\":\"chatcmpl-a9f6128818355f17\",\"object\":\"chat.completion.chunk\",\"model\":\"bitrix\u002Fbitrixgpt-5.5\",\"choices\":[{\"index\":0,\"finish_reason\":\"stop\",\"delta\":{}}],\"usage\":{\"prompt_tokens\":10,\"completion_tokens\":15,\"total_tokens\":25}}\n\ndata: [DONE]\n```\n\n`usage` приходит в последнем событии перед `[DONE]`. Накапливайте `delta.content` из всех событий для получения полного текста ответа.\n\n## Пример обработки потока\n\n```javascript\nconst response = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fchat\u002Fcompletions', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    model: 'bitrix\u002Fbitrixgpt-5.5',\n    messages: [{ role: 'user', content: 'Расскажи про CRM' }],\n    stream: true,\n  }),\n})\n\nconst reader = response.body.getReader()\nconst decoder = new TextDecoder()\nlet buffer = ''\n\nwhile (true) {\n  const { done, value } = await reader.read()\n  if (done) break\n  buffer += decoder.decode(value, { stream: true })\n  const lines = buffer.split('\\n')\n  buffer = lines.pop() ?? ''\n\n  for (const line of lines) {\n    if (!line.startsWith('data: ')) continue\n    const payload = line.slice(6)\n    if (payload === '[DONE]') return\n    const chunk = JSON.parse(payload)\n    const delta = chunk.choices?.[0]?.delta?.content\n    if (delta) process.stdout.write(delta)\n  }\n}\n```\n\n## Выбор режима под нагрузкой\n\nВ синхронном режиме (`stream: false`) полный ответ модели собирается на сервере и уходит клиенту одним ответом — первый байт приходит вместе с последним. Для модели с длинной фазой рассуждения `bitrix\u002Fbitrixgpt-5.5-thinking` на длинном контексте и с развёрнутым ответом генерация занимает десятки секунд. Если клиентский таймаут короче полного времени генерации, соединение закрывается без единого полученного байта — например, `cURL error 28: Operation timed out, 0 bytes received`. На коротких запросах генерация укладывается в таймаут, и эффект не проявляется.\n\nВ потоковом режиме (`stream: true`) сервер отправляет статус `200` и заголовки сразу после начала обработки, а события идут по мере генерации токенов, включая фазу рассуждения. Для объёмных запросов и моделей с рассуждением используйте `stream: true` — клиентский таймаут по приёму первого байта тогда не срабатывает.\n\nОриентиры по клиентскому таймауту:\n\n- **Потоковый режим (`stream: true`)** — задавайте таймаут на приём первого события с запасом на обдумывание модели. Модель с рассуждением тратит несколько секунд до первого токена, значение от 30 секунд покрывает эту фазу с запасом.\n- **Синхронный режим (`stream: false`)** — таймаут по всему запросу должен покрывать полное время генерации, а не только сетевой обмен. Для объёмного запроса к модели с рассуждением это десятки секунд. Кроме того, при ошибке или таймауте провайдера синхронный запрос повторяется автоматически, и тогда финальный ответ или ошибка приходят через несколько минут. Поэтому значений 9-15 секунд недостаточно: задавайте таймаут по всему запросу с запасом на такие повторы — несколько минут — либо переходите на потоковый режим, где таймаут по приёму первого байта снимает проблему.\n\n## Известные особенности\n\n**Резервной модели в потоке нет.** При сбое провайдера синхронный запрос повторяется с моделью по умолчанию, а в потоковом режиме клиент получает ошибку в последнем событии перед `data: [DONE]`.\n\n**Ошибки приходят внутри потока.** Статус `200` уже отправлен, когда платформа узнаёт о перегрузке или обрыве генерации, поэтому служебное событие вида `data: { \"error\": { \"code\": \"pool_exhausted\", \"retryAfter\": 5 } }` приходит перед `data: [DONE]`. Читайте поток до конца и проверяйте поле `error`.\n\n**Незавершённый структурированный ответ тоже приходит событием ошибки.** Если в запросе был `response_format`, а полного JSON модель не выдала, перед `data: [DONE]` приходит `data: { \"error\": { \"code\": \"structured_output_truncated\", \"message\": \"...\", \"type\": \"invalid_request_error\" } }`. В этом событии только три поля — `code`, `message` и `type`. Полей `finishReason`, `param` и `suggestedMaxTokens`, которые несёт синхронный ответ `422`, здесь нет. Текст `message` различается по причине завершения: генерация оборвана по `finish_reason: \"length\"` — предлагается повторить запрос с увеличенным `max_tokens`, поток закончился без причины завершения — ответ может быть неполным, модель завершилась сама с другой причиной — разбираемого JSON нет, рекомендуется модель без рассуждения. Подробнее — [гарантированный JSON-ответ](.\u002Fjson.md).\n\n**Зависший ответ обрывается по тайм-ауту простоя.** Если модель отдала заголовки, но затем замолчала в середине ответа и не присылает новых данных дольше окна ожидания, платформа прерывает вызов и присылает `data: { \"error\": { \"code\": \"stream_idle_timeout\", \"type\": \"server_error\", \"retryable\": true, \"retryAfter\": \u003Cсекунды> } }` перед `data: [DONE]`. Ошибка повторяемая — повторите запрос с учётом `retryAfter`. Непрерывный поток токенов (в том числе токенов рассуждений у «думающих» моделей) сбрасывает таймер простоя и под тайм-аут не попадает.\n\n## Смотрите также\n\n- [Создать чат-комплишен](.\u002Fcompletions.md)\n- [Лимиты запросов](.\u002Frate-limits.md)\n- [Гарантированный JSON-ответ](.\u002Fjson.md)\n- [AI Router](\u002Fdocs\u002Fai)\n","2026-07-21",{}]