You can wait for a model's answer to arrive whole, or read it as it is generated. The second route is streaming over server-sent events (SSE). Below: where it pays off and where it only adds code.
How streaming works
On a plain request the server holds the connection until the answer is finished, then sends it as one block. With streaming it sends events as soon as the next tokens are ready. The client opens an HTTP connection with Accept: text/event-stream and reads a stream of data: {...} lines, each separated by a blank line.
Anthropic and OpenAI use different formats. Anthropic sends named events (message_start, content_block_delta, message_stop and others), and each one carries its own type. OpenAI's stream is simpler: the same data: lines with a text delta, ending in data: [DONE]. Both formats work through codexkey, and streaming is switched on with the same stream: true flag you would use in the original SDKs.
Where streaming genuinely helps
Chat. There is a real gap between "a spinner for five seconds" and "text appears after three hundred milliseconds", even when the total time is identical. People start reading sooner, and the service feels responsive.
Long answers. When the model writes a couple of thousand tokens, the reader works through the beginning while the end is still being written. Staring at a frozen screen for the whole wait is irritating.
Cancellation. The user sees the answer heading the wrong way, hits stop, the connection closes, and the tokens that were never generated cost nothing.
When you can skip it
Short answers: a classification, one extracted field, a plain yes or no. Nobody reads those in pieces, and streaming only makes the code harder to follow.
Server-side processing with no interface, where the result goes into a database or another system. That path needs a complete, validated answer. A partial text would have to be buffered whole anyway, and the point of streaming is gone.
A batch of dozens or hundreds of requests is also simpler without it: less state, easier retries, easier token accounting.
Assembling partial chunks
The main trap: a network chunk is not a meaningful unit of text. It can cut a word or a JSON object in half, especially when you are also streaming tool use whose function arguments arrive only in part.
What works: accumulate text deltas in a buffer and leave the JSON alone until a block-completion event arrives. A Python example with the Anthropic SDK:
import anthropic
client = anthropic.Anthropic(
api_key="your-codexkey-key",
base_url="https://api.codexkey.online/v1",
)
with client.messages.stream(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Write a short poem about autumn"}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
final = stream.get_final_message()
The SDK stitches the deltas into full text and returns the finished message with exact token counts at the end. If you read raw SSE without an SDK, repeat that logic by hand: append lines to a buffer and parse JSON only at an event boundary.
What to do when the connection drops
A long stream can break: the app goes to the background, a mobile network hiccups, a proxy closes the connection on a timeout. LLM APIs have no built-in way to resume from the point of failure, unlike file uploads with resumable transfer.
The practice is simple. Treat the break as an ordinary network error, keep what has already arrived, and decide separately what to do with it: show it marked as interrupted, or send the request again. On a retry it makes sense to cut max_tokens down to the part you still need, so you do not pay twice for no reason.
When drops happen specifically on long generations, the cause is often not the client but an intermediate proxy or load balancer with a short timeout. Raise the timeout on the client and check that nothing between your app and codexkey is cutting long-lived connections on its own.
Summary
Turn SSE on where a person waits and reads: chat, long answers, the option to stop a generation. In server-side processing with no interface it only adds complexity. Collect deltas in a buffer, parse JSON at event boundaries, and meet a dropped connection as a plain network error without losing the text that already arrived.