Skip to content

Route models by harness namespace, not a curated allow-list#2

Merged
clawhavenapp merged 1 commit into
mainfrom
harness-model-namespaces
Jul 13, 2026
Merged

Route models by harness namespace, not a curated allow-list#2
clawhavenapp merged 1 commit into
mainfrom
harness-model-namespaces

Conversation

@czpython

@czpython czpython commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Why

Adding any new model — a new Claude or Codex release — currently means editing hardcoded models tuples on each harness and cutting a druks release. Codex CLI never does this: it passes the model string through and routes by provider, so a new model works the day it ships. This does the same.

What

  • Routing is by name namespace, not a list. Each harness declares model_prefixes; Harness.has_model(model) matches on them (or the family token). get_harness_for_model uses it, so claude-opus-5 / gpt-6 route with no code change.
  • models demotes from allow-list → picker suggestions (advisory). The HarnessResponse.allowedModels the settings UI renders is unchanged, so the dropdowns keep working.
  • Write-boundary validation stays, as namespace checks (client data, trust boundary): a harness row's model must be in its own namespace (no gpt-5.5 on the claude row), and an agent override must be runnable by some installed harness (else it 500s the settings read). Neither is a curated list — a new in-namespace model passes.
  • Deletions: the unused ExtensionsSettingsResponse.allowed_models union + its registry function, and the dead frontend ALLOWED_*_MODELS constants (zero consumers).
  • get_harness_for_model now raises the typed HarnessError (was ValueError).

Not in this PR

The settings model pickers are still suggestion dropdowns — the new-model-without-release path is via the settings API / config (like codex's config.toml), not free-text in the UI yet. A free-text combobox is an easy follow-up if wanted.

Verification

  • ruff check backend clean; frontend tsc -b + eslint clean.
  • New test_harness_model_routing.py covers namespace routing, the family token, and the unroutable-model raise.
  • DB-backed settings tests (incl. the two adjusted coherence tests) gate via CI per the shared-DB convention.

The one line that'd ever need touching for a brand-new provider namespace: CodexHarness.model_prefixes / ClaudeHarness.model_prefixes.

A model routes to the harness whose name namespace owns it
(Harness.has_model), so a provider's new model runs the day it ships —
no druks release to extend a hardcoded tuple. The per-harness `models`
tuple demotes from an allow-list to picker suggestions.

Write-boundary validation keeps two coherence checks as namespace
checks: a harness row's model must be in its own namespace, and an
agent override must be runnable by some installed harness (else it'd
500 the settings read). Drops the unused ExtensionsSettingsResponse
model union and the dead frontend ALLOWED_*_MODELS constants.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants