Skip to content

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.

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.

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:

  • 402 is seat-wide because running out of credit affects everything on the subscription — there’s no point trying another model on the same dead seat.
  • 429 honors 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 the Retry-After passes, 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. Repeated 429s only ever extend the deadline (it moves forward, never back), and the wait is clamped between 1 second and max_cooldown_secs so a missing or hostile Retry-After can neither thrash nor strand the seat. The 429 and 402 states are independent — one never overwrites the other.
  • 5xx/timeouts are model-scoped and thresholded. A model-specific 500 must not sideline the healthy models on the same seat, and a single transient blip shouldn’t trip anything — so it takes trip_threshold consecutive 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.

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.

Terminal window
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).

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.

  • 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).