Use a Smart Route from apps
An app uses a Smart Route like any model: it sends the route’s address, @route/<slug>, as the model name. Nothing else changes. The route works with these endpoints:
- OpenAI Chat Completions:
POST /v1/chat/completions - OpenAI Responses:
POST /v1/responses - Anthropic Messages:
POST /v1/messages - OpenAI Images:
POST /v1/images/generations
Other endpoints, such as embeddings, don’t take a route. Use a model, an alias or a preset there.
The key is a Nexus API key from Connections. The address below is the local one; use the private network or remote address for other devices. See the Gateway reference.
Examples
Section titled “Examples”curl -i http://127.0.0.1:3939/v1/chat/completions \ -H "Authorization: Bearer $NEXUS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "@route/everyday", "messages": [{"role": "user", "content": "Summarize: the review moved to Monday at 10am."}] }'-i prints the response headers, so you can see where the request went.
Python (OpenAI SDK)
Section titled “Python (OpenAI SDK)”from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:3939/v1", api_key="YOUR_NEXUS_API_KEY")
response = client.chat.completions.with_raw_response.create( model="@route/everyday", messages=[{"role": "user", "content": "Fix the off-by-one error in this loop: ..."}],)print(response.headers.get("X-Msty-Nexus-Route-Lane"))print(response.parse().choices[0].message.content)JavaScript (OpenAI SDK)
Section titled “JavaScript (OpenAI SDK)”import OpenAI from "openai";
const client = new OpenAI({ baseURL: "http://127.0.0.1:3939/v1", apiKey: process.env.NEXUS_API_KEY });
const { data, response } = await client.chat.completions .create({ model: "@route/everyday", messages: [{ role: "user", content: "Translate to French: good morning" }] }) .withResponse();
console.log(response.headers.get("x-msty-nexus-route-lane"), data.choices[0].message.content);Anthropic SDK
Section titled “Anthropic SDK”from anthropic import Anthropic
client = Anthropic(base_url="http://127.0.0.1:3939", api_key="YOUR_NEXUS_API_KEY")
message = client.messages.create( model="@route/everyday", max_tokens=512, messages=[{"role": "user", "content": "Explain this stack trace: ..."}],)print(message.content[0].text)Keep a conversation together
Section titled “Keep a conversation together”If your app knows its own conversation IDs, send one per conversation. Follow-ups then stay on the same model, even when the prompt’s start changes:
-H "X-Msty-Nexus-Session-Id: chat-8f2c1a"Without it, Nexus recognizes a conversation from the start of the prompt. See Conversations.
See why a request went where it did
Section titled “See why a request went where it did”Every response through a route carries these headers. They never contain prompt text.
| Header | What it says |
|---|---|
X-Msty-Nexus-Route-Pack |
The route’s slug. |
X-Msty-Nexus-Route-Lane |
The routing choice that was picked. |
X-Msty-Nexus-Resolved-Model |
The model that answered. |
X-Msty-Nexus-Route-Fallback |
true when the fallback answered. |
X-Msty-Nexus-Route-Fallback-Reason |
Why it fell back. |
X-Msty-Nexus-Route-Reason |
Why this message went there: first_message, follow_up, task_changed, rule, guard and so on. See the full list. |
X-Msty-Nexus-Route-Rule |
The ID of the rule that decided, when one did. |
X-Msty-Nexus-Route-Guard |
The ID of the guard that moved the request, when one did. |
X-Msty-Nexus-Route-Affinity |
How the conversation was treated: pinned, switched, classified or no_key. |
X-Msty-Nexus-Pool, X-Msty-Nexus-Pool-Target |
The Smart Balancer pool and the machine, when the target was a pool. |
X-Msty-Nexus-Data-Protection |
applied when Data Protection checked the request. -Redactions and -Categories say how many values were removed and of which types. |
X-Msty-Nexus-Request-Id |
The request’s ID, to find it in Activity and Request history. |
Errors
Section titled “Errors”Errors use the gateway’s usual shape. Branch on error.code:
| Code | What it means | What to do |
|---|---|---|
MODEL_NOT_FOUND |
No route has that slug, or the route is turned off. | Check the slug, and that the route is Enabled. |
MODEL_ENDPOINT_NOT_SUPPORTED |
The endpoint doesn’t take a route, such as embeddings, or the picked target can’t serve it. | Use a supported endpoint, or a target that supports it. |
SMART_ROUTE_LOCKED_BY_ENTITLEMENT |
The route is over your plan’s limit, or uses rules, guards or a budget without Pro. | Upgrade, turn another route off, or remove the paid features. |
DATA_PROTECTION_BLOCKED |
Data Protection found something the policy blocks. | Show the person why. Remove the detail, or change the policy. |
SMART_ROUTE_PRIVATE_TARGET_UNAVAILABLE |
The sensitive data route is down and set to block. | Start it, or set it to use the fallback. |
A target that’s down doesn’t cause an error by itself: the request goes to the fallback, and X-Msty-Nexus-Route-Fallback says so.
From the command line
Section titled “From the command line”msty-nexusctl routes manages routes from a terminal or a script. Add --output json for structured output. See the CLI reference.
| Command | What it does |
|---|---|
routes list |
Lists the routes. |
routes get <slug> |
Prints one route as JSON. |
routes set <slug> --input <file|-> |
Creates or replaces a route from JSON. |
routes validate <slug> |
Checks that its targets exist and can serve. |
routes preview <slug> --input <file|-> |
Shows where a request would go, without calling a model. |
routes dry-run <slug> --input <file|-> |
Replays kept requests against draft choices. |
routes enable <slug> / routes disable <slug> |
Turns the route on or off. |
routes delete <slug> |
Deletes the route. |
routes status |
Shows whether the router is ready. |
routes prepare [--backend mlx|llamacpp|ollama] |
Sets up the router model. |
routes export [--route <slug>]… [--since 24h|7d] |
Writes a support bundle, with no message text, keys or tokens. |
Examples
Section titled “Examples”Set up the router on MLX, then check it:
msty-nexusctl routes prepare --backend mlxmsty-nexusctl routes statusSee where a prompt would go:
echo '{"text": "Fix the null check in this function"}' | msty-nexusctl routes preview everyday --input -The result names the choice (routeId), the target (targetModelId), whether it fell back, and the rule that decided, if any.
Create a route from a file:
{ "slug": "everyday", "name": "Everyday", "enabled": true, "fallbackModelId": "mlx/Jundot/gemma-4-26B-A4B-it-oQ6e-mtp", "followUps": "switch", "routes": [ { "id": "coding", "name": "Coding", "description": "Write, explain, debug, or review software code, configuration, commands, or tests.", "targetModelId": "mlx/Jundot/Qwen3.8-27B-oQ6e-mtp" } ], "rules": [ { "id": "long-prompts", "name": "Long prompts to the fallback", "when": [{ "fact": "request.promptTokens", "op": "gte", "value": 24000 }], "then": { "target": "fallback" } } ]}msty-nexusctl routes set everyday --input everyday.jsonmsty-nexusctl routes validate everydayfollowUps is switch, keep or each. A rule’s then.target is a model ID, @preset/<slug>, @pool/<slug>, fallback or router. Rule facts and operators use the codes the Console shows in plain words, such as request.promptTokens and gte.
Write a support bundle for the last 7 days:
msty-nexusctl routes export --route everyday --since 7d