Routes

A route is a name such as odnoga/smart that stands for an ordered list of models. Your code sends the name instead of a model; odnoga tries the models in order and moves to the next one when a provider fails. You change the models in odnoga — the code never changes, and nothing changes without you: every response names the route and version that served it.

Create a route

Workspace → Routing → Routes → New route.

  1. Give it a name: odnoga/ plus lowercase letters, digits, dots, dashes or underscores.
  2. Start from a suggestion built from your own catalogue and prices — Cheapest that works, Fast, Strongest, EU only; each takes one model per provider, so one provider outage never stops the route — or add models from the list. Model names are never typed.
  3. Drag the models into order (or use the arrows). What a request does shows exactly what the gateway will do — it is worked out by the same code the gateway runs.
  4. Create it, then send its name as the model:
POST https://api.odnoga.com/v1/chat/completions
{ "model": "odnoga/smart", "messages": [{ "role": "user", "content": "Hello" }] }

Every save is a new version with who made it and why. History shows every version and restores any of them as the newest one. Changes reach every request within 15 seconds.

Test before you save

In the route editor, Test before you save sends one sample request to each model of the list, one at a time, and shows what each did: time, tokens in and out, cost, and — when the sample offers tools — whether the model called the tool with valid JSON, answered without it, or broke the JSON. Start from a ready-made sample (short answer, a tool call, a JSON answer) or paste your own request. The fastest and cheapest answers are marked.

Is the answer as good? With two or more models, the first in the list is the reference — put the model you use today first. A judge model reads your request and both answers and scores each other model against the reference: 0–10, better / as good / slightly worse / worse, and one sentence why. It judges correctness, completeness and following your instructions (language, format), and for tool calls the right tool with the right values — not length or style. The judge is never one of the models being compared, and its call is billed like the others.

The calls are real: billed to the workspace like any call (labelled route-test, at most 1,024 output tokens each), and the editor shows the most the test can cost before you run it. Each call is pinned to its model, so a row never describes a fallback. Nothing about the route changes until you save. Workspace admins, from the Growth plan; 30 test runs per workspace per hour. AI tools use routes.test.

Recommendations (recommended with approval)

odnoga watches the catalogue for every named route and proposes, for its first model:

KindWhat it means
ReplacementThe model is being retired and the catalogue names its successor.
Newer versionSame vendor and model line, newer, no more expensive.
Cheaper — test firstSame kind of call, capabilities and price class, at least 20% less on the route's own traffic.

Each shows the saving simulated on the route's own last 30 days at your workspace's prices (or on 1,000 typical calls when the route has no traffic yet). A cheaper model can be approved only after Test against current on your sample in the last 24 hours: a judge model reads your request and both answers and scores the cheaper one against the current one from 0 to 10, with one sentence why — it needs 7 or more. Nothing changes until you approve: approving saves a new version with the recommended model first (undo from History), Not now hides it until the route changes. Included from the Extend plan. AI tools use routes.recommendations.

Within limits (autonomous)

Instead of a fixed list, a route can follow limits you set in the editor: the highest price per 1M tokens (in and out — at least one), the capabilities it must have (tools, JSON schema, images, reasoning, EU), optionally which vendors, what to prefer (cheapest, fastest — measured median response time on odnoga over the last 7 days — or newest) and how many models. The editor shows live what the limits mean today (A → B → C), spread across vendors so one outage does not stop the route.

odnoga re-checks every 15 minutes. When the best fit changes it saves an ordinary new version whose note says why (Autonomous: within your limits the best fit is now …) — so every change is in History and can be undone, and no model above your limits is ever chosen. If nothing fits any more, the last good list stays and the route card says Limits: needs attention. Answer quality (for example in Polish) is not measured by odnoga yet, so it is not a limit — use Test before you save. Switching the route back to a fixed list stops the limits. Extend plan and up; AI tools use routes.policy_preview and routes.save_within_limits.

Connect a route to a function

Different processes need different models. A function that sends the x-odnoga-app and x-odnoga-function headers appears in odnoga after its first call; on a route, Connect function picks it. From then on every call from that function is served by the route, whatever model its code sends — you switch a process's AI here, without a code change. The route card lists the functions it serves (Used by).

  • One route per function; connecting it to another route moves it.
  • A call that is part of a running prompt A/B test keeps the model being tested.
  • A route never takes a call of another kind: a chat route never serves an embeddings call.
  • Archiving a route sends its functions back to the model their code sends.

What every response says

HeaderMeaning
x-odnoga-routeThe route that served the call.
x-odnoga-route-versionIts version.
x-odnoga-route-chainThe models it was going to try, in order.
x-odnoga-route-connected<app>/<function> when the route served the call because the function is connected.
x-airouter-modelThe model that answered.
x-airouter-fallback1 when an earlier model failed and a later one answered.

The same is recorded on every request (Requests → the request → route).

Rules a route follows

  • 1 to 8 models, no duplicates, each serving today and allowed in this workspace.
  • One kind of call: chat models and embedding models never mix. Image and audio models are not routed yet.
  • Every model is checked against the workspace's Allowed models; one that is not allowed is left out, and the preview says so.

Automatic chain and per-model fallbacks

On the same page: the automatic chain is what {"model": "auto"} uses, and the fallback for any model without its own; fallbacks for a specific model say which models answer when that one fails. Both are edited with the same picker.

Plans

FreeGrowth and up
Automatic chain ("model": "auto") and per-model fallbacks✓✓
Named routes (odnoga/<name>), versions and undo✓
Connect a route to a function✓
routes.* changes from AI tools (MCP)✓
Test before you save✓
Recommendations with one-click approvalExtend and up
Routes within limits (autonomous)Extend and up

An organisation that leaves Growth keeps what it made: its named routes keep serving and their functions stay connected. They become read-only — archiving a route and disconnecting a function still work; creating, changing, rolling back, restoring and connecting answer Named routes is included from the Growth plan until the plan includes them again.

Errors

CodeWhen
400 route_not_foundNo route of that name in this workspace (or it is archived).
400 route_missing_capabilityNone of the route's models can do what the request needs (for example images).
400 model_not_allowedNone of the route's models is allowed in this workspace.

With AI tools (MCP)

Connected assistants use the routes.* tools: routes.guide explains everything above and the safe order of calls; routes.models lists the models a route may use; routes.preview shows what a request would do; routes.save refuses to overwrite a change someone else made meanwhile. See MCP.