Configuration reference¶
Two YAML files in frozen-v3/config/ define the gateway's
behavior. Both are mounted read-only into the gateway container.
models.yaml¶
Maps internal alias keys to real OpenRouter model IDs.
schema_version: 1
verified_on: "2026-08-18"
pricing_is_advisory: true
models:
nemotron_ultra:
openrouter_id: "nvidia/nemotron-3-ultra-550b-a55b:free"
role: "scout_critic_free"
cost_class: "free"
allow_sensitive: false
purposes: ["scout", "critic", "summarize_public", "classify_public", "review_public"]
deepseek_v4_flash:
openrouter_id: "deepseek/deepseek-v4-flash-0731"
role: "default_worker"
cost_class: "very_low"
allow_sensitive: true
purposes: ["coding", "debug", "tests", "tool_loop", "general"]
deepseek_v4_pro:
openrouter_id: "deepseek/deepseek-v4-pro-0813"
role: "senior_solver"
cost_class: "high_relative_to_stack"
allow_sensitive: true
purposes: ["high_reasoning", "hard_debug", "architecture", "high_risk", "escalation"]
glm_5:
openrouter_id: "z-ai/glm-5.2"
role: "emergency_fallback"
cost_class: "unknown"
allow_sensitive: true
purposes: ["emergency_fallback"]
| Field | Required | Notes |
|---|---|---|
schema_version |
yes | Must equal 1. The gateway refuses to start otherwise. |
verified_on |
recommended | Date the registry was last verified. |
pricing_is_advisory |
yes | true flags that the cost_class strings are not authoritative prices. |
models |
yes | Map of internal alias key → ModelConfig. |
Each ModelConfig has:
| Field | Required | Notes |
|---|---|---|
openrouter_id |
yes | The real OpenRouter ID. |
role |
yes | One of scout_critic_free, default_worker, senior_solver, emergency_fallback, or a custom string. |
cost_class |
yes | free, very_low, low, medium, high, high_relative_to_stack, unknown. |
allow_sensitive |
yes | Whether the model can receive sensitive content. The free model is false. |
purposes |
yes | Tags for routing and logging. |
routing-policy.yaml¶
The rule chain and thresholds. Loaded by
src/smart_gateway/settings.py::routing_policy.
schema_version: 1
freeze_id: "SGW-BLUEPRINT-2026-08-18-01"
default_route: deepseek_v4_flash
explicit_overrides:
auto: AUTO
pro: deepseek_v4_pro
flash: deepseek_v4_flash
free: nemotron_ultra
high_reasoning_markers:
- "/pro"
- "[route:pro]"
- "[reasoning:high]"
- "reasoning cao"
- "high reasoning"
- "deep reasoning"
- "think deeply"
hard_pro_rules:
task_kinds: ["SECURITY", "AUTH", "PAYMENT", "DESTRUCTIVE_MIGRATION"]
risk_levels: ["CRITICAL"]
same_error_count_gte: 2
flash_attempts_gte: 2
files_touched_gte: 20
tool_depth_gte: 16
blast_radius: ["CRITICAL"]
score:
weights:
reasoning_requirement: 20
ambiguity: 10
blast_radius: 15
dependency_depth: 10
tool_depth: 10
verification_difficulty: 10
runtime_failure: 15
business_risk: 10
flash_max: 45
pro_min: 65
gray_zone: [46, 64]
scout:
enabled: true
model: nemotron_ultra
use_only_in_gray_zone: true
max_calls_per_task: 1
require_non_sensitive: true
default_after_scout_failure: deepseek_v4_flash
free_direct:
enabled: true
task_kinds: ["SUMMARIZE", "CLASSIFY", "PUBLIC_REVIEW"]
require_non_sensitive: true
require_repo_free_opt_in_if_repo_context_present: true
escalation:
flash_local_retry_limit: 1
same_error_to_pro: 2
structural_failure_to_pro: true
verification_fail_to_pro_after_attempts: 2
de_escalation:
reclassify_each_subtask: true
never_inherit_previous_model_as_requirement: true
privacy:
sensitive_default: true
free_model_fail_closed: true
budget:
per_goal_soft_usd: 2.00
per_goal_hard_usd: 5.00
per_day_soft_usd: 10.00
per_day_hard_usd: 25.00
hard_cap_behavior: "STOP_AND_REQUIRE_HUMAN"
| Field | Required | Notes |
|---|---|---|
schema_version |
yes | Must equal 1. |
freeze_id |
yes | Must equal SGW-BLUEPRINT-2026-08-18-01. The gateway refuses to start otherwise. |
default_route |
yes | Internal alias key. Always deepseek_v4_flash in v1.0.0. |
explicit_overrides |
yes | Maps auto, pro, flash, free to internal alias keys or AUTO. |
high_reasoning_markers |
yes | Substring markers that force Pro. |
hard_pro_rules |
yes | The hard Pro thresholds. |
score |
yes | Weighted scoring weights and the Flash / Pro bands. |
scout |
yes | Scout configuration. |
free_direct |
yes | When the free model can run directly. |
escalation |
yes | Runtime escalation policy. |
de_escalation |
yes | How subtasks are reclassified. |
privacy |
yes | Privacy defaults. |
budget |
yes | Per-goal / per-day caps. |
What happens on startup¶
# src/smart_gateway/settings.py
def routing_policy() -> dict[str, Any]:
data = load_yaml(os.getenv("ROUTING_POLICY_PATH", ROOT / "frozen-v3" / "config" / "routing-policy.yaml"))
config = RoutingPolicyConfig.model_validate(data)
if config.schema_version != 1:
raise ValueError(...)
if config.freeze_id != "SGW-BLUEPRINT-2026-08-18-01":
raise ValueError("Immutable freeze_id violated")
return config.model_dump()
A bad YAML or a wrong freeze ID is a startup failure. There is no "ignore and start anyway" mode.
Overriding at runtime¶
ROUTING_POLICY_PATH and MODELS_CONFIG_PATH can be set to
point at a different file. This is useful for:
- testing a proposed change locally before freezing it,
- running a side-by-side evaluation in a non-production profile.
In production, the values are hardcoded in
docker-compose.production.yml:
environment:
- ROUTING_POLICY_PATH=/app/config/routing-policy.yaml
- MODELS_CONFIG_PATH=/app/config/models.yaml
Changing the configuration¶
The configuration is part of the architecture freeze. To change
it, follow the release process documented in
docs-internal/development/release-process.md (operator-only):
- Open a branch.
- Edit the YAML.
- Run local tests (
make check). - Deploy to staging.
- Run the post-release evidence suite.
- Freeze and release.
See also: docs-internal/development/routing-change-policy.md
(operator-only).
See also¶
- Reference → Environment variables.
- Reference → Model registry.
- The full
routing-policy.yamlrule table is summarized inline above and in Architecture → Routing pipeline; the file itself infrozen-v3/config/is the source of truth.