Функции могут передавать вывод потоком вместо одного финального ответа. Платформа оформляет каждый фрагмент как сообщение Server-Sent Events (SSE), поэтому браузеры, CLI-инструменты и оркестраторы показывают прогресс — токены LLM, статус задачи, долгие вычисления, — пока обработчик ещё работает.
Потоковая передача — это обычный HTTP: без перехода на WebSocket и специальных клиентских библиотек. Читать поток может всё, что умеет читать HTTP-ответ построчно: fetch с reader, curl -N, EventSource.
Пишем потоковый обработчик#
В Node.js экспортируйте асинхронный генератор (или верните его из обработчика): каждый yield становится одним SSE-фреймом. Обработчики на Python передают поток так же — yield из генератора или асинхронного генератора, и каждое значение уходит фреймом data:. Обработчики на Go возвращают канал для чтения, и среда выполнения пересылает каждое полученное значение SSE-фреймом, так же как генераторы Node.js и Python.
// Return an async generator and the platform streams each chunk // to the client as Server-Sent Events over /invoke/stream. exports.handler = async function* (event, context) { yield { type: 'status', message: 'starting' }; for (const token of ['Hello', ' from', ' a', ' stream']) { // Objects are framed as `data: {...}` SSE events automatically; // yield a string to write a raw SSE frame yourself. yield { token }; } yield { type: 'done' }; };
Если отдать объект, среда выполнения сериализует его в JSON внутри фрейма data:; если отдать строку, вы сами записываете сырой SSE-фрейм. Если обработчик вернул одно значение вместо генератора, поток завершается одним фреймом event: done с результатом — вызывающая сторона обрабатывает оба варианта одинаково.
Вызываем потоковый эндпоинт#
Любую функцию можно вызвать в потоковом режиме через POST /functions/{functionId}/invoke/stream. Ответ начинается сразу и остаётся открытым, пока обработчик не завершится:
# -N disables buffering so events render as they arrive curl -N -X POST "https://api.inquir.org/functions/{functionId}/invoke/stream" \ -H "Authorization: Bearer $INQUIR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"event": {"prompt": "stream me"}}' # data: {"type":"status","message":"starting"} # data: {"token":"Hello"} # … # event: log — console output is interleaved as log events # event: done — emitted when the handler returns a value instead of a generator
Потоковая передача через API-шлюз#
Маршруты шлюза тоже передают поток: маршрут, привязанный к потоковому обработчику, пересылает SSE-фреймы на публичный URL по мере их появления. Так выглядит собственный эндпоинт с потоковой выдачей токенов LLM:
- Соединение остаётся открытым в пределах таймаута функции — потоковая передача не продлевает лимит, она лишь доставляет вывод раньше.
- Для потоковых путей отключена буферизация прокси, поэтому фреймы доходят до клиента без задержек на накопление.
- Авторизация на маршруте (API-ключ или Bearer) действует для потоковых маршрутов так же, как для обычных.
- Поток передают только маршруты с целью lambda. Маршрут, нацеленный на графовый пайплайн, отклоняет потоковый запрос с кодом
400. - SSE-соединение поддерживается heartbeat-комментарием
: pingпримерно раз в 25 секунд, чтобы простаивающие прокси не обрывали медленный поток.
Особенности поведения#
- Вывод
console.logвплетается в поток фреймамиevent: log— живые логи приходят вместе с данными без второго соединения. - Если обработчик упал посреди потока, поток завершится фреймом
event: errorс сообщением — проверяйте его, прежде чем считать закрытый поток успешным. - Потоковая передача работает и из тёплых, и из холодных контейнеров; при холодном старте просто позже приходит первый фрейм.