Стриминг
Передайте "stream": true — и ответ придёт по частям в формате Server-Sent Events (SSE). Формат событий зависит от endpoint'а и совпадает с оригинальным API, поэтому официальные SDK разбирают его сами.
1Chat Completions
POST /v1/chat/completions отдаёт строки data: с фрагментами ответа и завершается data: [DONE].
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Привет"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":"stop"}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":3,"total_tokens":15}}
data: [DONE]Для моделей Claude и GPT Zukko сам добавляет в запрос stream_options: {"include_usage": true}. Поэтому последний фрагмент перед [DONE] содержит usage и пустой массив choices. Код, который без проверки читает chunk.choices[0], на нём упадёт:
for chunk in stream:
if chunk.choices:
print(chunk.choices[0].delta.content or "", end="", flush=True)
elif chunk.usage:
print(f"\n[токены: {chunk.usage.prompt_tokens} вход, {chunk.usage.completion_tokens} выход]")2Messages
POST /v1/messages отдаёт события Anthropic: message_start, content_block_start, content_block_delta, content_block_stop, message_delta и message_stop.
event: message_start
data: {"type":"message_start","message":{"id":"msg_...","role":"assistant","model":"claude-sonnet-5","content":[]}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Привет"}}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":3}}
event: message_stop
data: {"type":"message_stop"}Модели GLM через /v1/messages тоже стримят в этом формате: Zukko переводит их ответ в события Anthropic.
3Responses
POST /v1/responses отдаёт именованные события: response.created, response.output_item.added, response.output_text.delta, response.output_item.done, response.completed и другие. Полный список — на странице POST /v1/responses.
4Ошибки внутри потока
HTTP-статус 200 отправляется до того, как модель начала отвечать. Если ошибка случилась позже, она придёт событием внутри потока — строкой data: с полем error. Проверяйте события, а не только статус ответа.
Поток, в котором пришла только ошибка — без текста и без usage, — не оплачивается.
5Стоимость и прерывание
- У потокового ответа нет заголовков
X-Zukko-Cost-MicrosиX-Fetch-Balance-Cents: стоимость становится известна только в конце. Смотрите её в GET /v1/usage или в кабинете. - Если клиент закрыл соединение раньше времени, Zukko всё равно дочитывает ответ модели до конца и списывает всё сгенерированное. Прерывание потока не экономит деньги — чтобы ограничить расход, задайте
max_tokens. - Потоковые ответы тоже попадают в кэш и в
Idempotency-Key, если их размер не больше 2 МБ; потоковая и обычная версии одного запроса хранятся отдельно.