Show text as it is generated instead of freezing on a spinner. Stream tokens from the API, accumulate the final message, and understand the event types you receive.
Why: a long answer can take many seconds — streaming shows the first words almost immediately, so the interface feels fast even though total time is unchanged. When: stream anything a human reads live (chat, long generations); do not bother for short machine-to-machine calls. Where: perceived latency, not real latency, is what you are improving.
NON-STREAMING: [........ 6s wait ........] whole answer appears
STREAMING: first words in ~0.5s, then flowing to the end
Same total time. Wildly different experience.Why: the streaming helper yields text deltas you print as they come, so the user watches the answer form. When: use client.messages.stream(...) with a context manager so the connection is always closed. Where: text_stream gives you just the text; other events (below) carry tool calls and metadata.
import anthropic
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=1024,
messages=[{"role": "user", "content": "Write a haiku about streaming APIs."}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True) # flush so it appears immediately
print()Why: you often need the complete text and the token usage after streaming for logging or storage — the SDK assembles it for you. When: call get_final_message() once the stream is exhausted; do not hand-concatenate deltas yourself. Where: this is the same object a non-streaming call returns.
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=1024,
messages=[{"role": "user", "content": "Summarize REST in two sentences."}],
) as stream:
for _ in stream.text_stream:
pass # (in a real app you'd forward each delta to the client)
final = stream.get_final_message()
print(final.content[0].text)
print("tokens:", final.usage.output_tokens)Why: in a web app the model streams to your server and your server must stream to the browser — buffering the whole reply first throws away the entire benefit. When: pipe each delta straight out over Server-Sent Events (SSE) or a chunked response. Where: this pattern (yield-as-you-go) is the backbone of every chat UI.
# FastAPI example: relay model deltas to the client as they arrive.
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
@app.get("/chat")
def chat(q: str):
def gen():
with client.messages.stream(
model="claude-opus-4-8", max_tokens=1024,
messages=[{"role": "user", "content": q}],
) as stream:
for text in stream.text_stream:
yield f"data: {text}\n\n" # SSE frame — never buffer first
return StreamingResponse(gen(), media_type="text/event-stream")