Skip to content

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.

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.

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)
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);
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)

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.

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 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.

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.

Set up the router on MLX, then check it:

msty-nexusctl routes prepare --backend mlx
msty-nexusctl routes status

See 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.json
msty-nexusctl routes validate everyday

followUps 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