Skip to content

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

  1. Open a branch.
  2. Edit the YAML.
  3. Run local tests (make check).
  4. Deploy to staging.
  5. Run the post-release evidence suite.
  6. Freeze and release.

See also: docs-internal/development/routing-change-policy.md (operator-only).

See also