Intermediate16 min
LangGraph Streaming v2
The StreamPart TypedDict protocol, all 7 stream modes, subgraph streaming, and the production FastAPI/SSE pattern — with the correct API, not the broken dot-notation examples most tutorials ship.
Quick Reference
- →StreamPart is a TypedDict: part['type'], part['data'], part['ns'] — no dot notation
- →7 stream modes: values, updates, messages, custom, checkpoints, tasks, debug
- →version='v2' → every chunk is a self-describing StreamPart; v1 returns raw tuples
- →updates is the default for non-chat APIs; messages is for token-by-token chat UIs
- →stream_mode=['messages', 'updates'] combines modes in one loop
- →GraphOutput from invoke v2: .value and .interrupts — no .tasks field
- →get_stream_writer() fails silently on Python < 3.11 async — use writer parameter instead
Should You Stream at All?
Streaming adds complexity — only use it when the user is watching
Streaming keeps a long-lived HTTP connection open, complicates error handling, and requires reconnection logic on the client. If the caller is a batch pipeline, a scheduled job, or any non-interactive consumer, use invoke() — it's simpler, easier to test, and handles errors without SSE boilerplate.
| Scenario | Use | Reason |
|---|---|---|
| Chat UI where user reads tokens as they arrive | stream_mode='messages' | Token delay is user-visible; streaming hides it |
| Dashboard showing which agent step is running | stream_mode='updates' | Per-node progress without full state bandwidth |
| Batch processing 1,000 documents overnight | invoke() | No human watching; streaming overhead wasted |
| Long tool call with progress percentage | stream_mode='custom' | Built-in modes only emit at super-step boundary |
| Debugging why a node emits unexpected state | stream_mode='debug' | Internal events only; never in production |
| Crash-recovery replay of prior run state | stream_mode='checkpoints' | Replay checkpoint events; requires checkpointer |