Retry

Agent routes can opt into automatic retry of transient LLM failures via the retry field on agent(). Retries apply to rate limits, server errors, network timeouts, and OpenAI overload responses — but not to non-transient errors like invalid API keys or model-not-found.

Configuring retry

Set retry on the agent() descriptor:

src/app/(public)/research/index.ts
import { agent } from "@dawn-ai/sdk"
 
export default agent({
  model: "gpt-5-mini",
  retry: { maxAttempts: 5, baseDelay: 500 },
  systemPrompt: "You are a helpful assistant.",
})
FieldDefaultNotes
maxAttempts3Total number of attempts (including the first call). 1 disables retry.
baseDelay1000 (ms)Base delay before the first retry. Backoff is exponential with jitter.

If retry is omitted, agents use the defaults (3 attempts, 1s base delay). To disable retry entirely, set maxAttempts: 1.

What's retried

The retry policy retries on errors whose message indicates a transient condition:

  • Rate limits: 429, rate limit
  • Server errors: 500, 502, 503
  • Network errors: ECONNRESET, ECONNREFUSED, ETIMEDOUT, timeout, network
  • OpenAI transient: overloaded, server_error

Anything else (invalid API key, model not found, schema validation errors, abort) fails immediately without retry.

Backoff

Delay before retry n (zero-indexed) is:

text
delay = min(baseDelay * 2^n + jitter, 10s)
jitter = random(0, 500ms)

So with the defaults (1s base, 3 attempts):

AttemptDelay before this attempt
1 (initial)0
2~1000–1500 ms
3~2000–2500 ms

The non-stream fallback honors the configured baseDelay. The cap at 10 seconds prevents pathological backoff for long retry chains.

Streaming behavior

For streaming routes, retry only applies if the failure happens before any token or event is yielded to the client. The current streaming path starts retries with a 1-second base delay regardless of the configured baseDelay. Once content has streamed, the partial response is committed — Dawn cannot retry a partially-emitted stream because the client has already seen content. In that case the error propagates through the stream.

If you need stronger retry guarantees in streaming mode, wrap the call at a higher level in your client or use /threads/:id/runs/wait for operations where partial output is not useful.

Abort signals

An Agent Protocol viewer disconnect does not abort the run; the run stays available for the thread to resume. An AG-UI disconnect, explicit Agent Protocol cancellation (POST /threads/:id/cancel), and server shutdown do abort the run. The resulting signal reaches agent execution and tools as ctx.signal, but provider and tool operations must cooperate with that signal for pending I/O to stop promptly.

Per-route, not global

Retry is configured per agent() descriptor. Different routes can have different policies:

ts
// Critical billing-related route — fail fast on transient errors
export default agent({
  model: "gpt-5-mini",
  retry: { maxAttempts: 1 },
  systemPrompt: "...",
})
ts
// Best-effort summarization route — patient retry
export default agent({
  model: "gpt-5-mini",
  retry: { maxAttempts: 5, baseDelay: 2000 },
  systemPrompt: "...",
})

There is no global retry config — each route states its own intent.