Skip to content

Streaming Events

When you request a streaming response, ai& streams the model’s SSE events unchanged and then appends a single trailer event carrying cost, request ID, and final usage.

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{"content":"Hel"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{"content":"lo"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":7,"completion_tokens":2,"total_tokens":9}}
data: [DONE]
event: aiand.metadata
data: {"request_id":"req-...","cost_usd":0.000018,"model":"..."}

The aiand.metadata event is emitted after [DONE]. Robust clients should keep the connection open until the stream closes naturally.

event: message_start
data: {"type":"message_start",...}
event: content_block_delta
data: {"type":"content_block_delta",...}
event: message_delta
data: {"type":"message_delta","usage":{"output_tokens":2}}
event: message_stop
data: {"type":"message_stop"}
event: aiand.metadata
data: {"request_id":"req-...","cost_usd":0.000018,"model":"..."}
FieldDescription
request_idSame as X-Request-ID header.
cost_usdFinal cost in USD.
modelModel that actually served the request.
usage(optional) Echo of the final usage block, for shapes that don’t emit it natively.

ai& never modifies the response body emitted by the model. Cost, request id, and final usage are delivered as a named SSE event after the terminal message, so the byte stream above the trailer is identical to what the source API would produce — the official OpenAI and Anthropic SDKs work without modification.