Skip to content

Model registry

The model registry is the YAML file at frozen-v3/config/models.yaml. It is the single source of truth for "alias → real OpenRouter ID".

The four entries

Internal alias key OpenRouter ID Role Sensitive-allowed Cost class
nemotron_ultra nvidia/nemotron-3-ultra-550b-a55b:free scout_critic_free no free
deepseek_v4_flash deepseek/deepseek-v4-flash-0731 default_worker yes very_low
deepseek_v4_pro deepseek/deepseek-v4-pro-0813 senior_solver yes high_relative_to_stack
glm_5 z-ai/glm-5.2 emergency_fallback yes unknown

What each role means

scout_critic_free

Used for:

  • the gray-zone Scout call (advisory only),
  • direct execution on SUMMARIZE / CLASSIFY / PUBLIC_REVIEW tasks that are non-sensitive.

allow_sensitive: false is enforced by the privacy gate's free_model_fail_closed rule.

default_worker

The cheap, fast default. Always allowed on sensitive content. The policy never refuses to route a request to Flash for cost reasons at the Flash band.

senior_solver

The expensive, careful choice. Allowed on sensitive content. Forced by hard Pro rules or high complexity.

emergency_fallback

Used only when a Pro call fails end-to-end after retries. Not exposed as an alias.

Why the OpenRouter IDs are not in the alias

The alias layer (smart-router etc.) and the registry layer (internal alias key) decouple client intent from upstream identity. Clients should not hard-code the OpenRouter IDs. See User guide → Model aliases.

How to discover the real ID at runtime

The response body of /v1/chat/completions includes the real ID:

{
  "model": "deepseek/deepseek-v4-flash-0731",
  "choices": [...]
}

The structured routing log includes the internal alias key:

{
  "decision": {
    "action": "ROUTE",
    "model": "deepseek_v4_flash",
    "cause": "score_flash"
  }
}

The two fields are different namespaces. The first is upstream's identifier; the second is the gateway's policy identifier.

Changing the registry

To add a new model:

  1. Update frozen-v3/config/models.yaml. Add the new entry, set schema_version: 1, set a sensible role and cost_class.
  2. If the new model is intended to replace an existing alias, update routing-policy.yaml::explicit_overrides and the fallback list in src/smart_gateway/routing.py::senior_fallbacks.
  3. Update frozen-v3/07-model-health-registry-spec.md if the health thresholds need adjustment.
  4. Run the full release process — local tests, staging, E3 / E4 evidence, freeze, release.

See the release process at docs-internal/development/release-process.md (operator-only).

When you should not add a model

  • Don't add free models that are not on OpenRouter. OpenRouter is the only upstream in v1.0.0. LiteLLM is not in use.
  • Don't add vision models. Multimodal is rejected by the policy layer in v1.0.0.
  • Don't add non-English-only models unless you've verified the rest of the policy still works.

Cost classes

The cost_class strings are not dollar amounts. They are buckets that the policy and the operator dashboards interpret roughly:

Class Meaning
free No charge.
very_low Cheapest paid tier.
low Cheap.
medium Mid-range.
high Expensive.
high_relative_to_stack Most expensive in the current stack.
unknown Not priced. Treat as expensive until verified.

pricing_is_advisory: true is the registry's way of saying "these strings are not authoritative prices; consult OpenRouter directly for current rates."

See also