How No-Mistakes Handles Agent Streaming Responses with SSE and Retries
The no-mistakes CLI processes Server-Sent Events (SSE) from AI agents using a layered parser that ignores standard retry: fields, while implementing robust client-side retry logic with exponential back-off that re-issues HTTP requests on transient failures.
The no-mistakes repository implements a sophisticated streaming architecture for AI agent communication. While remote SSE servers deliver incremental text via HTTP streams, the client-side code in internal/agent/ manages parsing, assembly, and resilient retry mechanisms. This article examines how the Go codebase handles SSE streaming and implements retry logic for agent responses.
SSE Stream Architecture
Low-Level Event Parsing in sse.go
The foundation of the streaming system resides in internal/agent/sse.go, where the parseSSE function transforms raw HTTP response bodies into discrete events. This low-level reader processes the byte stream line-by-line, concatenating multi-line data: fields and respecting both \n\n and \r\n\r\n event separators. Notably, the parser ignores all other fields such as id: or the standard SSE retry: field, treating them as irrelevant to the application logic.
// Called by the agent-specific processors.
err := parseSSE(resp.Body, func(ev sseEvent) bool {
// `ev.Name` is the event type (often empty), `ev.Data` holds JSON payload.
// The caller decides whether to continue streaming.
return true
})
Agent-Specific Stream Processors
Building atop the low-level parser, agent-specific processors handle the JSON payloads within SSE data fields. The parseOpencodeSSE function in internal/agent/opencode_stream.go and parseRovodevSSE in internal/agent/rovodev.go both invoke parseSSE to tokenize the stream. These processors unmarshal the JSON, filter by session ID, assemble text parts, and invoke the caller-supplied onChunk callback for every incremental piece of output.
This architecture separates transport concerns from business logic, allowing each agent implementation to define its own payload interpretation while sharing the same robust SSE parsing core.
Client-Side Retry Orchestration
The Retry Classifier
Retry logic is implemented entirely client-side in internal/agent/retry.go through the runWithRetry function. This wrapper surrounds the runOnce execution with a retry classifier (retryClassifier) that inspects errors to determine if they are transient (e.g., HTTP 429, overloaded errors). When the classifier identifies a retryable failure, the orchestrator initiates the retry sequence rather than propagating the error immediately.
The classifier abstraction allows the system to handle API-specific error codes from different providers (OpenAI, Claude, etc.) while maintaining a clean separation between transport errors and application logic.
Exponential Back-Off and User Feedback
When a retry is triggered, runWithRetry implements an exponential back-off schedule calculated as 1× base, 4× base, 16× base, and so on. Crucially, the system maintains user transparency by emitting status messages through the same opts.OnChunk callback used for streaming content. Before re-issuing the HTTP request, the code sends a human-readable status line:
label, shouldRetry := opts.ClassifyRetry(err)
if shouldRetry {
opts.OnChunk(fmt.Sprintf("[retry] %s (attempt %d/%d)\n", label, attempt, max))
// exponential back-off then retry the request
}
This design ensures that the UI layer (implemented in internal/cli/axi_render.go) receives a continuous stream of updates, including both agent text and retry notifications, creating a seamless user experience during transient failures.
Implementation Examples
To run an agent with automatic retries, configure the RunOptions struct with the appropriate callback and classifier:
opts := RunOptions{
// Called for every text chunk and also for retry status messages.
OnChunk: func(chunk string) {
fmt.Print(chunk) // stream to terminal
},
// Retry classification (uses built-in classifier that knows API-specific errors).
ClassifyRetry: defaultRetryClassifier,
}
// The high-level entry point that handles retries for you.
err := runWithRetry(ctx, agentRequest, opts)
The SSE parser itself never participates in retry decisions. When runWithRetry re-issues a request after a transient error, it creates a fresh HTTP connection and passes the new response body to parseOpencodeSSE or the equivalent processor, which invokes parseSSE on the new stream. This guarantees that each retry attempt starts with a clean SSE event stream.
Summary
- The SSE parser in
internal/agent/sse.gofocuses exclusively on tokenizing event streams and explicitly ignores theretry:field defined in the SSE specification. - Agent processors in
opencode_stream.goandrovodev.gohandle provider-specific JSON payloads while sharing the commonparseSSEimplementation. - Retry logic is orchestrated client-side by
runWithRetryininternal/agent/retry.go, which uses exponential back-off and emits status updates via theOnChunkcallback. - User experience is maintained by treating retry notifications as stream chunks, allowing the CLI to display "[retry]" messages inline with agent responses.
Frequently Asked Questions
Does the no-mistakes SSE server respect the retry: field in SSE events?
No. The parseSSE function in internal/agent/sse.go explicitly ignores the retry: field along with other non-essential fields like id:. The retry logic is implemented entirely in the client-side runWithRetry function, which manages its own back-off schedule independent of any server-sent retry recommendations.
What happens to the SSE stream when a retry occurs?
When a transient error triggers a retry, runWithRetry closes the failed HTTP connection and re-issues the entire request. A fresh SSE stream is established, and parseSSE begins processing the new response from the first event. The previous stream is discarded, and the user sees a "[retry]" status message before the new content begins flowing.
How does the retry classifier determine which errors are transient?
The retryClassifier function inspects error types and HTTP status codes to identify transient failures such as rate limits (HTTP 429) or server overloads. According to the implementation in internal/agent/retry.go, provider-specific error patterns are matched against the error string to decide whether a retry is appropriate, ensuring that fatal errors fail fast while temporary glitches trigger recovery.
Can the retry behavior be customized for different AI agents?
Yes. The RunOptions struct accepts a ClassifyRetry function, allowing different retry strategies for various agent types. While the default classifier handles common OpenAI and Claude error patterns, you can inject custom logic to adjust sensitivity or handle provider-specific edge cases before passing the request to runWithRetry.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →