Influence
Influence lets recent outcomes reorder routing. When a subscription seat runs out of credit, gets rate-limited, or a model keeps erroring, the breaker deprioritizes that target — moves it later in the chain, never removes it — so your parallel agents stop each paying a wasted first-hop round-trip into a target that just failed. Once the trouble should have passed, a single probe request checks whether it’s healthy again.
Influence is off by default. It reads the same per-attempt outcomes the insight recorder observes, but the two are independently gated — either works without the other.
Configure
Section titled “Configure”The top-level influence: block in routeplane.yaml:
influence: enabled: true # default false — routing order entirely unchanged cooldown_secs: 60 # base cooldown before a recovery probe; doubles per failed probe max_cooldown_secs: 900 # ceiling for the exponential backoff (15 minutes) trip_threshold: 3 # consecutive 5xx/timeouts on one model that trip its breaker window_secs: 300 # rolling window for that 5xx streak (5 minutes)| Key | Default | What it does |
|---|---|---|
enabled |
false |
Turn the breaker on. Off means routing order is entirely unchanged — no state, no hook. |
cooldown_secs |
60 |
Base cooldown before a tripped target gets its recovery probe. Doubles on each consecutive failed probe. |
max_cooldown_secs |
900 |
Ceiling for the exponential-backoff cooldown. |
trip_threshold |
3 |
Consecutive upstream 5xx/timeout failures on one model (within window_secs) that trip its breaker. A 402 always trips on the first. |
window_secs |
300 |
Rolling window for the 5xx streak — a failure more than this after the previous one restarts the count rather than accreting stale evidence. |
That’s the whole surface — deliberately minimal knobs.
The three signals
Section titled “The three signals”A seat is one (provider, account) subscription — the thing your parallel agents share.
| Signal | Scope | Trips | Recovers |
|---|---|---|---|
Out of credit (402) |
Whole seat | On the first 402 — credit exhaustion is unambiguous and affects every model on the seat |
Exponential cooldown → a single probe; any success on the seat clears it |
Rate limited (429) |
Whole seat | On any 429 |
Self-heals when the provider’s own Retry-After deadline passes — no probe, no backoff |
Model errors (5xx/timeout) |
One model on one seat | trip_threshold consecutive failures within window_secs |
Exponential cooldown → a single probe; a success on that model clears it |
In operator terms:
402is seat-wide because running out of credit affects everything on the subscription — there’s no point trying another model on the same dead seat.429honors the provider’s stated deadline. The provider told you exactly how long to back off, so Routeplane treats that as a grounded, self-healing deadline: the seat is deprioritized until theRetry-Afterpasses, then routes again on its own. No probe is spent, no backoff is invented, and — deliberately — no unrelated success clears it early: a success on model B doesn’t disprove a rate limit the provider declared on the seat. Repeated429s only ever extend the deadline (it moves forward, never back), and the wait is clamped between 1 second andmax_cooldown_secsso a missing or hostileRetry-Aftercan neither thrash nor strand the seat. The429and402states are independent — one never overwrites the other.5xx/timeouts are model-scoped and thresholded. A model-specific500must not sideline the healthy models on the same seat, and a single transient blip shouldn’t trip anything — so it takestrip_thresholdconsecutive failures inside the rolling window, on that specific model, to trip it.
What is not evidence: an upstream 4xx (the request’s fault), a local or internal error, an auth demand, and an abandoned stream (the client cancelled — that says nothing about upstream health, so it neither trips nor clears anything).
Deprioritize, never remove — and fail open
Section titled “Deprioritize, never remove — and fail open”The breaker only ever reorders your chain. Healthy targets route first; tripped targets move to the back — still present, still reachable if everything ahead of them fails. Within each group your configured order is preserved.
[!NOTE] If every target is tripped, the breaker steps aside entirely — the chain runs in your original configured order as if influence were off. The breaker can delay a target; it can never starve you.
Recovery: a single probe
Section titled “Recovery: a single probe”When a tripped target’s cooldown elapses, it becomes probe-ready — and exactly one live request is allowed to try it (the probe is claimed atomically, so a burst of parallel agents can’t stampede a recovering seat):
- The probe succeeds → the breaker clears, and the target routes normally again.
- The probe fails → the breaker re-trips with the cooldown doubled, up to
max_cooldown_secs. - The probe never resolves (hung request) → another probe is allowed only after the maximum cooldown, so a slow-but-live probe isn’t duplicated.
Rate limits are the exception: they don’t probe at all — the seat simply routes again once the provider’s deadline passes.
routeplane breakers reset
Section titled “routeplane breakers reset”routeplane breakers reset [--config PATH] [--socket PATH]Asks the running daemon to clear every tripped breaker — seat and model alike — so everything routes in your configured order immediately. This is the escape hatch for when you know the evidence is stale: you topped up a credit-exhausted subscription and don’t want to wait out its cooldown.
● routing-influence breakers reset cleared 2 breaker(s)The command talks to the daemon’s control socket (--config locates it via your config; --socket overrides directly). When influence is disabled it reports routing influence is disabled (no breakers to reset).
Design philosophy: only negative evidence
Section titled “Design philosophy: only negative evidence”Only negative evidence ever changes routing order. A failure deprioritizes; a success (or an expired deadline) restores — that’s the entire model. There is no latency scoring, no success-boosting, no learned weights, and no predictive quota modeling. Your configured order is the routing policy; the breaker just steps a target out of the front of the line while there’s concrete evidence it will fail, and puts it back the moment there isn’t.
Boundaries
Section titled “Boundaries”- The breaker learns across requests, not within one. The chain is fixed once a request starts: a seat that
402s on turn 1 of a multi-turn request isn’t reordered for turn 2 of the same request. And the very first concurrent burst — before any failure has been recorded — still hits a dead seat once; the breaker keeps the next wave from repeating it. - State is in-memory, per daemon. Restarting the daemon clears all breakers (equivalent to a
breakers reset).