Syllabus Lesson 117 of 239 · Calling a Real LLM
Calling a Real LLM

Fold a Token Stream

When you stream a response, the model sends the answer as a series of small events instead of one big payload, so you can show text as it is typed. The SDK gives you a clean iterator of text chunks, but underneath it is folding a stream of typed events: a message_start, then many content_block_delta events each carrying a tiny text_delta, with content_block_stop and message_stop markers around them. To rebuild the full answer you keep only the text deltas and concatenate them.

The friendly real version looks like this (illustrative only -> we do not call the network):

with client.messages.stream(model="claude-sonnet-4-6", max_tokens=1024,
                            messages=[{"role": "user", "content": "Hi"}]) as stream:
    for text in stream.text_stream:   # already just the text chunks
        print(text, end="", flush=True)
    final = stream.get_final_message()

That text_stream is a convenience. Under it, the raw events look like the list below, and folding them is exactly the skill this lesson drills. We model the stream as a list of event dicts so it runs offline:

[
  {"type": "message_start"},
  {"type": "content_block_delta", "delta": {"type": "text_delta", "text": "He"}},
  {"type": "content_block_delta", "delta": {"type": "text_delta", "text": "llo"}},
  {"type": "content_block_stop"},
  {"type": "message_stop"}
]

You are building collect_stream(events). Walk the list and concatenate, in order, the text from every event that is a content_block_delta whose inner delta has type == "text_delta". Skip every other event -> the lifecycle markers (message_start, content_block_stop, message_stop) carry no text, and a non-text delta (such as an input_json_delta for a streamed tool call) is not part of the visible answer. An empty list returns "".

Build it so two different event lists rebuild two different strings, the lifecycle and non-text events are skipped, and an empty stream returns "".

Your turn

Write collect_stream(events) where events is a list of streaming event dicts. Concatenate, in order, the text of every {"type": "content_block_delta", "delta": {"type": "text_delta", "text": ...}} event. Skip all other events (lifecycle markers like message_start/content_block_stop, and non-text deltas). Return "" for an empty stream.

Spotted a problem in this lesson? Report it

Code · runs in your browser
Output