Model Routes
Named, ordered provider+model failover lists an agent can generate through.
Overview
A model route is a project-scoped, ordered list of provider+model targets.
Target 0 is tried first; a retryable failure (a provider error, a timeout, a
rate limit — whichever classes retry_on lists) falls through to the next
target. Deterministic failures — a 400-class error, an auth failure, a content
policy rejection — never fail over: they fail the generation immediately.
This module is a verbatim mirror of the runtime: every field, method, status code and error shape is the runtime's own, re-rooted under the project in the path. Errors raised by the route machinery arrive in the runtime's envelope.
See the OpenAPI spec for the full endpoint and schema reference, or browse it rendered under API Reference → Model Routes.
Data Model
ModelRoute
| Field | Type | Description |
|---|---|---|
id | string | Public model route ID. |
project_id | string | The owning project. |
name | string | Human-readable name, unique per project. |
targets | array of ModelRouteTarget | Ordered failover targets; position is priority. |
retry_on | array of string | Failure classes that are failover-eligible: provider_error, timeout, rate_limited. |
failure_threshold | integer | Consecutive retryable failures after which a target is skipped for cooldown_seconds. |
cooldown_seconds | integer | How long a tripped target is skipped before being probed again. |
created_at | string (date-time) | |
updated_at | string (date-time) |
ModelRouteTarget
| Field | Type | Description |
|---|---|---|
ai_provider_id | string | An AI provider in the route's project. |
model | string | Model name to call on that provider. |
timeout_seconds | integer | Per-attempt deadline; omitted means none. A timeout classifies as timeout. |
max_retries | integer | Retries on this target before falling through to the next one. Defaults to 0. |
Key Concepts
Ordered failover with a bounded budget
Targets are tried in array order, and the total attempt budget — the sum of
1 + max_retries over all targets — may not exceed 10;
POST /v1/projects/{project_id}/model-routes
rejects a route over the cap with a 400 naming the computed total. Every
target must reference an AI provider in the same project, and a duplicate
name in the project is a 409.
Circuit breaking
After failure_threshold consecutive retryable failures a target is skipped
for cooldown_seconds before being probed again. Breaker state is keyed by
(provider, model), so every route pointing at the same backend shares it.
Deleting a referenced route
DELETE /v1/projects/{project_id}/model-routes/{route_id}
answers 409 while an agent still references the route — a routed agent has no
pinned provider to fall back on, so repoint or delete the agent first.
Examples
Create a route with a fallback
- CLI
- SDK
- curl
naturali create-model-route \
--project-id proj_V1StGXR8Z5jdHi6B \
--name primary-with-fallback \
--targets '[
{ "ai_provider_id": "aip_V1StGXR8Z5jdHi6B", "model": "gpt-4o-mini", "max_retries": 1 },
{ "ai_provider_id": "aip_9fJk2LmNpQrStUvW", "model": "claude-haiku-4-5" }
]'
const { data: route } = await naturali.modelRoutes.createModelRoute({
path: { project_id: 'proj_V1StGXR8Z5jdHi6B' },
body: {
name: 'primary-with-fallback',
targets: [
{
ai_provider_id: 'aip_V1StGXR8Z5jdHi6B',
model: 'gpt-4o-mini',
max_retries: 1,
},
{ ai_provider_id: 'aip_9fJk2LmNpQrStUvW', model: 'claude-haiku-4-5' },
],
},
});
curl -X POST https://api.naturali.ai/v1/projects/proj_V1StGXR8Z5jdHi6B/model-routes \
-H "Authorization: Bearer $NATURALI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "primary-with-fallback",
"targets": [
{ "ai_provider_id": "aip_V1StGXR8Z5jdHi6B", "model": "gpt-4o-mini", "max_retries": 1 },
{ "ai_provider_id": "aip_9fJk2LmNpQrStUvW", "model": "claude-haiku-4-5" }
]
}'
List a project's routes
- CLI
- SDK
- curl
naturali list-model-routes --project-id proj_V1StGXR8Z5jdHi6B
const { data: routes } = await naturali.modelRoutes.listModelRoutes({
path: { project_id: 'proj_V1StGXR8Z5jdHi6B' },
});
curl https://api.naturali.ai/v1/projects/proj_V1StGXR8Z5jdHi6B/model-routes \
-H "Authorization: Bearer $NATURALI_TOKEN"