MPS: launch on a servable default model, and honor --model under --provider - #380
Merged
Conversation
masonc08
force-pushed
the
masonc08/mps-default-launch-model
branch
from
August 25, 2026 01:32
d4ff231 to
f98b473
Compare
lilly-luo
reviewed
Aug 29, 2026
lilly-luo
approved these changes
Aug 29, 2026
lilly-luo
reviewed
Aug 29, 2026
…--model pick one `ucode claude --provider <mps>` always started on Claude Code's built-in "family default" (opus). When the Model Provider Service declares no opus target the gateway 403s that default, so a bare launch failed for any service that only offers sonnet/haiku. `--model` couldn't rescue it either: `--model` + `--provider` was rejected outright. Now, under a provider: - with no --model, pick the most capable tier the service actually declares (opus > sonnet > haiku) and pin it via ANTHROPIC_MODEL, so the session starts on a servable model instead of dead-ending on opus. When the service does offer opus, pin nothing -- Claude Code's own default already works, and this avoids the duplicate /model picker row ANTHROPIC_MODEL causes. - --model is honored (guard removed): a family alias (opus/sonnet/haiku) resolves to that tier's declared target (clear error if the service doesn't offer it), any other value is trusted as a raw target id. Routed via route_root_model, not custom_model, so it doesn't clobber the per-family pins. - a relayed (subscription) service selects the model server-side, so --model is ignored with a warning. Known gap, deferred: for an opus-less Bedrock service the region-prefixed slug can be rejected by ANTHROPIC_MODEL's client-side check. That case was already broken (bare launch 403s), and opus-having Bedrock services are unaffected; the follow-up is to pin the servable target into the opus family slot instead. Co-authored-by: Isaac <no-reply@databricks.com>
The behavior is clear from the code and print_warning text; the deferred opus-less-Bedrock gap is tracked in the PR description. Co-authored-by: Isaac <no-reply@databricks.com>
masonc08
force-pushed
the
masonc08/mps-default-launch-model
branch
from
August 31, 2026 12:35
bf09ca6 to
1372700
Compare
masonc08
added a commit
that referenced
this pull request
Sep 1, 2026
## Problem `ucode claude --provider <mps> --model <m>` is ignored for a **relayed** (Claude subscription) Model Provider Service. A customer on a **Claude Enterprise** relay needs to launch on a specific model (e.g. `claude-opus-4-8[1m]`) without Claude Code's `/model` picker (limited list) or editing `settings.json` (blocked under MDM). ## What we learned - In the AI Gateway relayed Anthropic path (`ai-gateway/src/v3/client/ExternalModelDirectClient.scala`), the client's model is **passed through** to Anthropic; Team/Enterprise validates it against the allowlist, personal Max skips that — the gateway **never selects a model server-side**. - Real Enterprise relays are **`allow_all_targets`** with no declared Claude targets. So there's nothing for ucode to resolve `--model` against — an approach that pins the gateway env from declared targets can't help them. - The proven lever is **Claude Code's own `--model`**: `ucode claude --provider <mps> -- --model opus` already launches on Opus via the subscription (verified e2e against a relayed Enterprise MPS on staging). ## Change For a **relayed** provider, forward `--model` to Claude Code's own `--model` launch arg — exactly what the `-- --model X` passthrough does, now automatic. Claude Code selects the model natively and the relay honors it; no declared targets required, and it sidesteps the `ANTHROPIC_MODEL` client-side check (we use Claude Code's native flag). A `--model` that already rode in after `--` wins. Non-relayed providers (API-key / Bedrock) keep the env-pinning path from #380 unchanged. The change is `cli.py`-only: drop the relayed "--model is ignored" warning, guard the env-pinning resolve with `not relayed`, and inject `--model` into the launch args for a relayed provider (surfaced in the launch summary via the existing `forwarded_model`). ## Testing - Unit: `test_cli.py` relayed cases (forwarded-to-Claude-Code, and no-`--model` forwards nothing); the provider suites, `test_agents_init`, `test_databricks`, `test_agent_claude` green (729). `ruff` clean. - e2e: `ucode claude --provider <relayed_enterprise_mps> --model opus` launches on Opus (matches the proven `-- --model opus` passthrough). This pull request and its description were written by Isaac. Co-authored-by: Isaac <no-reply@databricks.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
ucode claude --provider <mps>always started on Claude Code's built-in "family default" (opus). When a Model Provider Service declares no opus target, the gateway 403s that default — so a bare launch failed for any service that only offers sonnet/haiku (e.g. an API-key Anthropic MPS scoped to sonnet+haiku).--modelcouldn't rescue it either:--model+--providerwas rejected outright with "Use either --model or --provider, not both."Stacked on #376 (which pins the declared per-family targets); this makes the launch model land on one of them.
Change
Under a provider:
--model, choose the most capable tier the service actually declares (opus > sonnet > haiku) and pin it viaANTHROPIC_MODEL, so the session starts on a servable model instead of dead-ending on opus. When the service does offer opus, pin nothing — Claude Code's own default already works, and this avoids the duplicate/modelpicker rowANTHROPIC_MODELproduces.--model(guard removed). A family alias (opus/sonnet/haiku) resolves to that tier's declared target (clear error if the service doesn't offer it); any other value is trusted as a raw target id. Routed viaroute_root_model, notcustom_model, so it doesn't clobber the per-family pins from Pin declared Anthropic MPS targets by family, like Bedrock #376.--modelis ignored with a warning.The launch banner now also prints the chosen
Model:under a provider.Known gap (deferred)
For an opus-less Bedrock service the region-prefixed slug can be rejected by
ANTHROPIC_MODEL's client-side check. That case was already broken (bare launch 403s on opus), and opus-having Bedrock services are unaffected (they returnNoneand behave as today). The follow-up fix is to pin the servable target into the opus family slot instead — that channel is passed through unchecked.Testing
resolve_provider_launch_model(7 cases: opus-present no-op, sonnet/haiku fallback, alias→target, unavailable-tier error, raw-id passthrough); CLI provider-launch (alias pin, auto-default, opus-present no-op, unavailable-tier error, relayed-ignored).test_databricks.py(248),test_cli.py(218),test_agent_claude.py+test_agents_init.py(188).ruffclean.--model haikustarts on haiku;--model opuserrors clearly.This pull request and its description were written by Isaac.