Speko Docs

Routing

The routing object, objectives, provider pinning, and automatic failover.

Every relay request carries a routing object that is a closed tagged union on mode. There are exactly two modes, and fields from one mode are rejected — never silently ignored — in the other.

Auto mode

Speko picks the provider, ranked for your objective and filtered by route health:

{
  "routing": {
    "mode": "auto",
    "objective": "latency",
    "allow_providers": ["deepgram", "cartesia"],
    "deny_providers": []
  }
}
objectivestring

One of balanced, quality, latency, cost. Defaults to balanced when omitted.

allow_providersstring[]

Optional. Restricts candidates to these provider IDs in preference order. Relay tries the first healthy, capable provider first and falls through the ordered list before returning an error. Entries must be non-blank.

deny_providersstring[]

Optional. Excludes these provider IDs from consideration.

Omitting the routing object entirely means {"mode": "auto", "objective": "balanced"}. A partially specified routing object is rejected rather than defaulted, and a present-but-empty list such as "allow_providers": [] counts as having named the field.

Explicit mode

You pin the exact provider and model; Speko does not substitute:

{
  "routing": { "mode": "explicit", "provider": "openai", "model": "gpt-5.2" }
}

Both provider and model are required. objective, allow_providers, and deny_providers are rejected in explicit mode — including as empty arrays.

The route in the response

Every successful response reports what actually served it, in the route object and mirrored in response headers:

{ "provider": "deepgram", "model": "flux-general-en", "region": "us-east-1", "attempt_id": "ratt_..." }

Automatic failover

In auto mode, if the chosen provider fails before the first byte of output, the relay transparently retries on the next-ranked provider:

  • Your Speko-Request-ID stays the same; a new Speko-Attempt-ID is minted.
  • Prices are frozen per attempt, so the new attempt is priced at its own provider's rates.
  • Nothing fails over after output has started — a mid-stream provider failure terminates the stream with a provider_error.
  • Explicit mode never falls back. If your pinned provider fails, you get the error.

Failover also preserves who supplies the credential. A request using one of your provider keys can retry only on another BYOK-configured provider; a managed request retries only on managed providers. Relay never changes the billing source during a request.

On LLM streams, the response.created event is deliberately not counted as output, so failover can still happen after you have seen it.

What auto mode considers

Candidates are ranked per objective, then filtered by your allow/deny lists, by canary route health, and by capability requirements (for example, tools, structured_output, or the requested reasoning_effort on LLM requests). If filters empty the candidate set:

  • 400 capability_unsupported — routable providers existed, but none can do what the request needs.
  • 503 provider_unavailable (retryable) — nothing is currently routable.

Speech rankings come from Speko's continuously measured quality/latency boards. LLM rankings are launch-pinned editorial orderings per objective — quality favors frontier models, latency favors fast inference providers, cost favors the cheapest capable entries.

On this page