Skip to main content

Routing

client.routing controls how the gateway selects a model and provider for each request. Artemis Task decides every model: 'auto' request, by model capability; a request that names a model uses no router. See Artemis Task for how it decides.

The router​

There is no router to choose, per request or in a setting. The chat call's router option (RouterChoice) is optional: it takes only 'artemis' or 'v2', which change nothing, and any other value is rejected with a NuRouteError whose status is 400. When Artemis Task cannot decide a request, fallback-router:apollo decides it, and the request's routerVersion and routerFallback say so and why (see Which router decided). Your governance policy applies either way. More in Routing concepts.

Get the current config​

const config = await client.routing.getConfig();
console.log(config.strategy, config.speed, config.policy?.fallbackBehavior);

Update routing config​

updateConfig() replaces the whole config. A field you leave out goes back to its default: strategy to balanced, the weights to 40/30/30 and the policy to its defaults. speed and the model aliases are kept when you leave them out; send null for speed off. Aliases in the config you send are ignored: change them with the alias methods. If the stored config cannot be read at that moment, the call fails with 503 and nothing is saved. Changing the config needs an owner's or admin's session: sign the client in with auth.login() (see Authentication). With an API key, getConfig() works and updateConfig() and the alias changes fail with 403. Read the config, change what you need and send all of it back:

const config = await client.routing.getConfig();
await client.routing.updateConfig({
...config,
strategy: 'balanced', // 'balanced' | 'cheapest' | 'fastest' | 'highest_quality' | 'manual'
policy: { ...config.policy, fallbackBehavior: 'allow_commercial' },
});

See Fallback for what fallbackBehavior actually controls. It decides what happens when no provider passes your policy constraints, not whether the gateway retries on a provider error.

What the strategy means​

Artemis Task reads the strategy as a preset:

strategyArtemis Task preset
balancedBalanced
highest_qualityQuality-first
cheapestCost-first
fastestBalanced at speed Fastest on a capability version with a speed table, else Fastest
manualNone: your pinned provider serves it, recorded as routerFallback: 'manual_mode'

For a request that names a model, the strategy ranks that model's providers. The balanced weights rank the providers of a model you name, and the choice the fallback router makes inside its tier; Artemis Task does not read them. Cost, latency and quality controls sets out what the strategy, the weights, speed and the cost and latency caps in policy do, with what to change to make routing cheaper or faster.

Speed​

speed is Artemis Task's Speed setting: how much a quicker answer is worth, at the quality target the strategy's preset sets. 'off', 'faster', 'fastest', or null for off; any other value is rejected with a NuRouteError whose status is 400. No chat option or header sets it, and a project's speed overrides the organization's for the project's requests. fallback-router:apollo ignores it.

import type { RouterSpeed } from '@aicp/sdk'; // 'off' | 'faster' | 'fastest'

const speed: RouterSpeed = 'faster';
const config = await client.routing.getConfig();
await client.routing.updateConfig({ ...config, speed }); // null: off

// A project: null follows the organization (sent as router_speed: "")
const proj = client.project('proj_abc123');
const current = await proj.routing.getConfig();
await proj.routing.setConfig({ ...current, speed: 'fastest' });

Model aliases​

Aliases map a name of your choice to a model. They are stored per organization (and per project), but the request path does not resolve them today: a chat request has to name the real model, or auto.

// Create or update an alias
await client.routing.setAlias('smart', 'gpt-4o');
await client.routing.setAlias('fast', 'gpt-4o-mini');
await client.routing.setAlias('coding', 'claude-sonnet-4-6');

// List all aliases
const aliases = await client.routing.listAliases();
// [{ alias: 'smart', model: 'gpt-4o' }, ...]

// Delete an alias
await client.routing.deleteAlias('coding');

Routing history​

Inspect how recent requests were routed:

const { decisions, total } = await client.routing.listHistory({
limit: 20,
offset: 0,
provider: 'openai', // optional filter
strategy: 'balanced', // optional filter
status: 'success', // optional filter
});

const detail = await client.routing.getDecision(decisions[0].id);
console.log(detail.selectedProvider, detail.routerVersion, detail.candidates);

Which router decided​

client.chat.complete() returns the response body only, so read the router from the request log. The completion id is chatcmpl- followed by the request id, which client.requests.list() can search for:

const res = await client.chat.complete({ model: 'auto', messages });

const requestId = res.id.replace(/^chatcmpl-/, '');
const { requests } = await client.requests.list({ search: requestId, limit: 1 });
const detail = await client.requests.get(requests[0].id);

console.log(detail.routerVersion, detail.capabilityVersion, detail.routerFallback);
// 'v2' 'cap-6' null, or 'v1' null 'no_estimates' when fallback-router:apollo decided

RequestDetail (from client.requests.get()) and RoutingDecision (from client.routing.getDecision()) both extend RouterDecision:

FieldTypeMeaning
routerVersionRouterVersion | nullThe router that decided: 'v2' (Artemis Task) or 'v1' (fallback-router:apollo); null for a request that named a model
capabilityVersionstring | nullThe capability version Artemis Task decided with, e.g. 'cap-6'; null when the fallback router decided
routerFallbackstring | nullWhy the fallback router decided instead of Artemis Task; null otherwise

RequestDetail also breaks down the request's time: latencyMs (the provider call), routingDurationMs (routing), totalMs (end to end, as the gateway measured it; 0 for requests recorded before it was tracked) and overheadMs (the rest; null when totalMs is 0). There is no separate timeline call: requests.getTimeline() was removed, since the gateway has no such endpoint.

When the fallback router decides, the request is still served, and your governance policy applies to its choice too. The fallback reasons:

routerFallbackMeaning
no_estimatesArtemis Task had no estimates: router-model failed, was busy or ran out of time, or no capability version is active
unknown_capability_versionArtemis Task's estimates came from a capability version the deployment does not know
manual_modeRouting is manual (mode or strategy manual), or the request pins a provider
preset_unavailableThe capability version has no preset for the strategy (Fastest on cap-1)
no_servable_modelNone of Artemis Task's models could be served after your policy and enabled providers, or your cost and latency caps ruled them all out and your fallbackBehavior is not 'fail' (reasons then include 'policy_caps_exhausted'; under 'fail' the request is refused with 422 instead)
v2_disabledArtemis Task is switched off by the operator. Self-hosted NuRoute does not include Artemis Task yet, so its auto requests all report this
invalid_estimatesArtemis Task's estimates failed a sanity check
v2_errorArtemis Task hit an error while deciding

Candidates​

candidates lists what was weighed, each with provider, model, costUsd, latencyMs, score (0–100) and winner. On an Artemis Task decision, each Candidate adds Artemis Task's figures. Under Quality-first, Balanced and Cost-first there is one row per pool model that can be served, on the provider it would be served by; under Fastest, one row per model and provider.

FieldTypeMeaning
qualitynumberThe model's expected score on this prompt (0–1)
utilitynumber | nullThe expected score less the preset's price for extra cost; the highest wins. null under Fastest
inputTokensnumberThe prompt tokens it priced
outputTokensnumberThe answer length, in tokens, it expected
expectedLatencyMsnumberThe answer time it expected on this provider; Fastest picks by it

When the fallback router decided, candidates lists the models it weighed in its tier, score being each one's rank under the strategy (winner highest), and the fields above are absent.