feat(model): retry what fails fast, and only that #662

Merged
coilyco-ops merged 1 commit from feat/retry-what-fails-fast-claude into main 2026-08-13 18:09:39 +00:00
Member

closes #650

not a ton. maybe like. 3 ~ 5 ish total tries. there should be a harness notice when this is happening

Four attempts, 250ms doubling — under two seconds of waiting against a 180 second turn.

The bound is arithmetic, not taste

defaultRequestTimeout caps the turn at 180s and Echo's p99 turn already sits at 180.32s (#577). A ladder built for slow failures does not fit: five attempts at thirty seconds each outlives the turn, so the retry would convert a failure the member could be told about into a timeout they wait out.

A connection refused or a 503 returns in milliseconds. Four of those cost less than the notice they replace.

Availability only

Retried: transport errors (no server reached, no status to read), and 429, 502, 503, 504.

Not retried: everything else in 4xx. A 400 is the request being wrong, and that case is live — the upstream prompt-trimming defect returns 400, so a naive retry would make it four times slower to report the same failure. Also not retried: a cancelled or expired turn, because that budget is already gone.

The status is now a typed modelHTTPError rather than a formatted string, so classification reads a number instead of parsing a sentence.

What I did not do

The harness notice. The mechanism logs model.retry with attempt, total and backoff, so the telemetry half exists. The member-facing wording is Content Creator's and I am not writing it.

Worth knowing before this merges

Agent Proxy already retries, twice, at 600 seconds each (#578). That is why a turn Echo abandoned at 180s leaves a request running for twenty minutes. This ladder does not change that and rides on top of it — the two multiply. Recorded in the doc rather than left for someone to rediscover.

A test asserts the whole ladder stays under a tenth of the turn ceiling, so this cannot quietly grow into the thing it was designed not to be.

ward exec gate green.

closes #650 > not a ton. maybe like. 3 ~ 5 ish total tries. there should be a harness notice when this is happening Four attempts, 250ms doubling — **under two seconds of waiting** against a 180 second turn. ## The bound is arithmetic, not taste `defaultRequestTimeout` caps the turn at 180s and **Echo's p99 turn already sits at 180.32s** (#577). A ladder built for slow failures does not fit: five attempts at thirty seconds each outlives the turn, so the retry would convert a failure the member could be *told* about into a timeout they *wait out*. A connection refused or a 503 returns in milliseconds. Four of those cost less than the notice they replace. ## Availability only Retried: transport errors (no server reached, no status to read), and **429, 502, 503, 504**. Not retried: **everything else in 4xx**. A 400 is the request being wrong, and that case is live — the upstream prompt-trimming defect returns 400, so a naive retry would make it four times slower to report the same failure. Also not retried: a cancelled or expired turn, because that budget is already gone. The status is now a typed `modelHTTPError` rather than a formatted string, so classification reads a number instead of parsing a sentence. ## What I did not do **The harness notice.** The mechanism logs `model.retry` with attempt, total and backoff, so the telemetry half exists. The member-facing wording is Content Creator's and I am not writing it. ## Worth knowing before this merges **Agent Proxy already retries, twice, at 600 seconds each** (#578). That is why a turn Echo abandoned at 180s leaves a request running for twenty minutes. This ladder does not change that and rides on top of it — the two multiply. Recorded in the doc rather than left for someone to rediscover. A test asserts the whole ladder stays under a tenth of the turn ceiling, so this cannot quietly grow into the thing it was designed not to be. `ward exec gate` green.
feat(model): retry what fails fast, and only that
All checks were successful
ci / image-build (pull_request) Successful in 23s
ci / test (pull_request) Successful in 37s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
bc0cc79d82
Kai asked for three to five tries with backoff on genuine availability
problems. Four attempts, 250ms doubling, so under two seconds of waiting
against a 180 second turn.

The bound is not taste. defaultRequestTimeout caps the turn at 180 seconds and
Echo's p99 turn already sits at that number, so a ladder built for slow
failures does not fit and would convert a failure the member could be told
about into a timeout they wait out.

Availability only. A transport error reached no server. 429, 502, 503 and 504
are the server saying not now. Everything else in 4xx is the request being
wrong, and the 400 from the upstream prompt-trimming defect is exactly that:
retrying it produces the same 400 four times and delays the notice by the whole
ladder. A cancelled or expired turn is not retried either, because the budget
is already spent.

The status is now a typed error rather than a formatted string, so the
classification reads a number instead of parsing a sentence.

Agent Proxy retries independently at 600 seconds twice, which is why a turn
abandoned at 180 seconds leaves a request running for twenty minutes. This
ladder does not change that and rides on top of it. Recorded in the doc.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo!662
No description provided.