Streaming and Partial-Result UX
Stream model output and tool progress so users see the agent think and act - the UX baseline every serious terminal agent has set.
The route
4 steps to Done
- 01
Design the event protocol
Streaming without structure is just faster confusion.
Preview prompt + verify gate ▾ Hide ▴
Design a typed streaming event protocol for the agent. Event types to include: run_started {run_id}, text_delta {content}, tool_started {call_id, tool, args_summary}, tool_progress {call_id, note} (optional heartbeats), tool_finished {call_id, ok, result_summary}, turn_completed {turn}, run_completed {status, usage}, run_error {message}, run_cancelled {partial: bool}. Each event carries a sequence number and timestamp. Document the protocol in a schema file with versioning (v1). Decide the transport (SSE for one-way UI updates is the default choice) and justify it in one paragraph.
- ✓ All lifecycle events covered
- ✓ Sequence numbers and timestamps included
- ✓ Transport choice justified
- 02
Implement server-side streaming
Wire the loop's inner moments to the event stream.
Preview prompt + verify gate ▾ Hide ▴
Implement streaming in the backend loop. Requirements: use the model API's streaming mode and forward text deltas as text_delta events as they arrive; emit tool_started before each tool executes with a compact args summary (never full file contents); emit tool_finished with ok/failed and a one-line result summary; for tools that run over 5 seconds, emit tool_progress heartbeats; emit run_completed with token usage at the end. Expose the stream over an SSE endpoint keyed by run ID. Verify with curl that events arrive progressively and in sequence order during a live run.
- ✓ Text deltas forwarded, not buffered
- ✓ Tool events bracket each execution
- ✓ Heartbeats cover long tool runs
- 03
Build the streaming client rendering
Users should watch the agent work the way they watch a colleague type.
Preview prompt + verify gate ▾ Hide ▴
Implement client rendering of the stream. Requirements: model text renders progressively token by token; tool activity renders as compact status lines (spinner while running, check or cross on completion, expandable to see the result summary); text and tool lines interleave in true chronological order using the sequence numbers; auto-scroll follows output unless the user scrolls up (then a 'jump to latest' affordance appears); a subtle elapsed-time indicator shows the run is alive. Test with a run that mixes long text, three tool calls, and one tool failure - the timeline must read coherently.
- ✓ Sequence order drives rendering
- ✓ Tool lines show running/success/failure states
- ✓ Auto-scroll yields to user scroll
- 04
Implement safe interruption
Cancel is a feature, not an emergency stop.
Preview prompt + verify gate ▾ Hide ▴
Add interruption. Requirements: a cancel control sends a stop request with the run ID; the server sets a cancellation flag checked between turns and between tool executions; in-flight generation is aborted at the API level where supported; tools that mutate state must complete or roll back - never abandon a half-applied edit (finish the current write, skip the rest); the server emits run_cancelled {partial: true} with a final summary of completed vs skipped work; the client renders the partial state clearly ('Cancelled - 2 of 4 steps completed'). Test by cancelling during generation and during a tool run, then verify files and run state are consistent.
- ✓ Flag checked at safe boundaries
- ✓ Mutating tools complete or roll back
- ✓ Partial summary rendered to the user
Research-backed