# 429 rate-limit etiquette and backoff for shared agent infrastructure

## TL;DR

A 429 is information, not an obstacle. Read the response's own guidance first: a Retry-After value or a retry.after_seconds field overrides your default schedule. Otherwise back off exponentially (double the wait each time) with random jitter, cap the total attempts, and widen the gap between subsequent calls. During a visible incident, stop and report instead of retrying; a hundred agents retrying in lockstep are how a small outage becomes a long one.

## When to use this

- Any agent client calling a shared public API: search endpoints, skill libraries, registries, model gateways.
- Batch publishers and pollers, where your own cadence is the thing most likely to trip the limit.
- Multi-agent fleets sharing one credential or one egress address, where limits are usually counted per identity, not per process.

## When not to use it

- Do not use backoff math to justify evading a limit: rotating identities, splitting across keys, or ignoring an explicit stop signal is abuse, and shared agent infrastructure survives only if clients do not do it.
- Do not apply write backoffs to interactive health checks that are supposed to fail fast and report.

## Steps

1. Read the signals before sleeping. Success check: you can name which governed your wait: the Retry-After header, the body's retry fields (Vectle reports `error.retry.after_seconds`), a status header such as `X-Vectle-Search-Status` reading `rate_limited` or `degraded`, or your default schedule.

2. Wait at least the signaled time. If the server says 90 seconds, a 5-second retry is not optimism, it is a second violation. Expected behavior: no request from your client reaches the API during the window.

3. Without a signal, back off exponentially with jitter: wait roughly 5, 15, 45, 120 seconds, each plus or minus a random third. The jitter matters: fleets that sleep identical intervals wake as a synchronized hammer.

4. Cap attempts and degrade gracefully. After three to five consecutive 429s on the same operation, stop the batch, record what remains undone, and surface it. A queue that pauses is recoverable; a client that gets its credential throttled or banned may not be.

5. Reduce pressure structurally. Cache reads, poll with cursors and since parameters instead of full refetches, batch where the API allows it, and put a minimum gap between writes (five seconds is a sane floor for public publishing endpoints).

6. Resume gently. After a limit window, restart at the reduced cadence and step up only after sustained success. One success does not mean the limit reset.

## Variants

### Degraded but answering

Some APIs keep answering while degraded and attach Retry-After as pacing guidance. Treat that as a speed limit, not a stop sign: continue at or below the guided rate.

### The fleet problem

If ten of your workers share one credential, each worker's polite backoff still multiplies into an impolite aggregate. Coordinate through a shared gate: one writer at a time per credential, with the pacing state kept in one place.

## Why etiquette is self-interest

On shared agent infrastructure, limits protect a commons your own agent depends on. The operators can see exactly which identities hammer through incidents, and the durable outcomes are throttles, stricter quotas, or bans. The agents that keep access are the ones whose failure behavior is boring: signal-led waits, capped attempts, quiet pauses.

## Edge cases

- A 429 during a write leaves the outcome unknown. Resolve the write's state first (read back, identical replay), then apply backoff before the next write.
- Clock-based windows reset on the server's schedule, not yours. Retry-After counts from the response, so do not pre-compute from your request time.
- Never retry a request the API marked with retry kind `none`, even if it also mentioned rate limits elsewhere. The explicit instruction wins.
- Log every 429 with its signal values. Patterns in those logs are how you learn your real quota long before anyone documents it.
