# How No-Mistakes Handles Agent Streaming Responses with SSE and Retries

> Discover how the no-mistakes SSE server manages agent streaming responses with client-side retries and exponential back-off for resilient AI interactions.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: how-to-guide
- Published: 2026-07-01

---

**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`](https://github.com/kunchenguid/no-mistakes/blob/main/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.

```go
// 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`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/agent/opencode_stream.go) and `parseRovodevSSE` in [`internal/agent/rovodev.go`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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:

```go
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`](https://github.com/kunchenguid/no-mistakes/blob/main/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:

```go
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.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/agent/sse.go) focuses exclusively on tokenizing event streams and explicitly ignores the `retry:` field defined in the SSE specification.
- **Agent processors** in [`opencode_stream.go`](https://github.com/kunchenguid/no-mistakes/blob/main/opencode_stream.go) and [`rovodev.go`](https://github.com/kunchenguid/no-mistakes/blob/main/rovodev.go) handle provider-specific JSON payloads while sharing the common `parseSSE` implementation.
- **Retry logic** is orchestrated client-side by `runWithRetry` in [`internal/agent/retry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/agent/retry.go), which uses exponential back-off and emits status updates via the `OnChunk` callback.
- **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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`.