Looks fine at first. Under load it turns rate limits into request storms.
I wrote a small CLI to catch it:
npx pitstop-check ./src
It scans TS/JS and flags things like: - 429 handled without Retry-After
- blanket retry of all 429s (no CAP vs WAIT distinction)
- unbounded retry loops (no max elapsed)
Example (ran against OpenClaw): [WARN] src/agents/venice-models.ts:24 — 429 handled without Retry-After
[WARN] src/agents/venice-models.ts:24 — All 429s treated as retryable — CAP vs WAIT not distinguished
The retry primitive supports Retry-After. The callers just don’t wire it up.So when the API returns Retry-After: 600, the client retries on its own schedule instead of backing off.
What’s going on is basically collapsing different failure modes into one:
WAIT — respect Retry-After
CAP — limit retries / concurrency
STOP — don’t retry
Most code just does: retry()
The tool is heuristic (will flag some test files), but it’s been useful for quickly spotting this in real repos.
SirBrenton•1h ago