Routing preferences
By default the proxy picks an operator the same way the chat app does — favoring a fast, cheap, available operator for the model you asked for. Most tools never need to touch anything beyond the model id.
If you want finer control — from your own code, or a tool that exposes it —
add an optional top-level provider object to the request body
(OpenRouter-style). It's a proxy-only hint: the proxy reads it to pick an
operator, then strips it before the request ever leaves your machine, so it
never reaches the operator or the model. Any field that's missing or
malformed is just ignored.
{
"model": "qwen3-coder",
"messages": [/* … */],
"provider": {
"only": ["1234", "5678:2"], // allowlist of operator refs
"ignore": ["9999:1"], // denylist (deny wins over allow)
"order": ["5678:2", "1234"], // explicit preference order
"allow_fallbacks": false, // false ⇒ pin to exactly `order`/`only`
"max_price": { "input": 2.0, "output": 6.0 }, // USD per 1M tokens, ceilings
"require_tools": true, // only route to operators with built-in tools
"sort": "latency", // price | throughput | latency
"relay": "off" // per-request transport-privacy override
}
}
A ref is either "<operatorId>" (any node run by that operator) or
"<operatorId>:<nodeId>" (one exact node). You can find operator/node ids
from GET /v1/zs/operators, or from the chat app's model picker.
Fields
| Field | What it does |
|---|---|
only | Restrict routing to these operator refs. |
ignore | Exclude these operator refs — wins over only if both match the same ref. |
order | Try these operators in this order before falling back to the rest. |
allow_fallbacks | false pins the request to exactly only/order — no fallback to anything else if they're all unavailable. |
max_price | USD-per-1M-token ceilings (input/output); operators above either are excluded. |
require_tools | Only route to operators that advertise the built-in tools the request needs. |
sort | Re-weight ordering among the remaining candidates — see below. |
relay | Override transport privacy for this one request — see below. |
If you have an active multi-turn session (a previous_response_id
continuation), that pin always wins over provider — it has to, since the
conversation lives in that specific operator's account. If your provider
preferences would exclude it, that's a conflict, not a silent re-route (see
the table below).
When preferences can't be satisfied
| Situation | What you get back |
|---|---|
only/order with allow_fallbacks: false matched no available operator | 503 no_pinned_operator |
A previous_response_id continuation is excluded by only/ignore/order | 400 pin_conflicts_with_continuation |
max_price excluded every operator | 400 price_ceiling_exceeded |
require_tools and no operator advertises the requested tools | 503 no_tool_capacity |
sort — what to optimize for
By default the proxy bands candidates by a combined expected-response-time
score (network latency + time-to-first-token + decode speed) and picks the
cheapest within the fastest band. sort changes that:
| Value | Optimizes for |
|---|---|
latency | Time to first token only (ignores decode speed). |
throughput | Decode speed only (ignores time to first token). |
price | Cheapest available operator, full stop. |
| (absent) | The combined default. |
relay — transport privacy, per request
The proxy normally routes every request through another operator acting as
a relay, so the operator actually running your model never sees your IP —
see Privacy & security. relay overrides that for one
request:
| Value | Effect |
|---|---|
"off" | Send directly to the target — lower latency, but it sees your IP. Only honored if zs.allow_privacy_override is enabled (the default). |
"required" | Force a relay hop, failing with 503 no_relay_available rather than send directly. |
"auto" / absent | Use the configured default (zs.privacy). |
You can also set this per request with the X-Zs-Relay header instead of
the request body; the body wins if both are present.
What's next
- Configuration — the config-file defaults these fields override per request.
- Connecting AI tools — the rest of the request surface.