Skip to content

MPS: launch on a servable default model, and honor --model under --provider - #380

Open
masonc08 wants to merge 11 commits into
mainfrom
masonc08/mps-default-launch-model
Open

MPS: launch on a servable default model, and honor --model under --provider#380
masonc08 wants to merge 11 commits into
mainfrom
masonc08/mps-default-launch-model

Conversation

@masonc08

Copy link
Copy Markdown
Collaborator

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). --model couldn't rescue it either: --model + --provider was 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:

  • Auto-pick the best servable tier. With no --model, choose 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 produces.
  • Honor --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 via route_root_model, not custom_model, so it doesn't clobber the per-family pins from Pin declared Anthropic MPS targets by family, like Bedrock #376.
  • Relayed services: model selection is server-side, so --model is 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 return None and 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

  • Unit: 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).
  • Suites green: test_databricks.py (248), test_cli.py (218), test_agent_claude.py + test_agents_init.py (188). ruff clean.
  • End-to-end against an API-key Anthropic MPS (canonical target names): recommended sanity check — bare launch starts on sonnet with no 403; --model haiku starts on haiku; --model opus errors clearly.

This pull request and its description were written by Isaac.

`ucode claude --provider <mps>` sends whatever model string Claude Code's alias
resolves to, and the gateway's direct-MPS path exact-matches that against the
service's declared targets (then forwards it verbatim). For a Bedrock service
ucode already pins ANTHROPIC_DEFAULT_*_MODEL to the service's target slugs, but
for an API-key Anthropic service it pinned nothing and trusted Claude Code's
canonical names to match — which they may not: a custom/dated target name, or an
enterprise managed-settings pin like `system.ai.claude-haiku-4-5`, yields a 403
"not in the allowed models list".

resolve_provider_models now derives the family->target map for a non-relayed
Anthropic service too (map_claude_family_models already handles canonical ids),
so the client sends exactly the ids the MPS declares. Bedrock is unchanged;
relayed Claude Max/Enterprise stays exempt (model selection is off server-side).

Co-authored-by: Isaac <no-reply@databricks.com>
@masonc08
masonc08 requested a review from rohita5l August 24, 2026 22:39
…--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>
@masonc08
masonc08 force-pushed the masonc08/mps-default-launch-model branch from d4ff231 to f98b473 Compare August 25, 2026 01:32
Base automatically changed from masonc08/pin-anthropic-mps-targets to main August 28, 2026 15:06
Comment thread src/ucode/cli.py
Comment on lines +1878 to +1889
# Claude Code starts on its built-in "family default" (opus), which the gateway 403s when
# the service declares no opus target. Pick the launch model explicitly and pin it via
# ANTHROPIC_MODEL (route_root_model): the user's --model when given, else the most capable
# tier the service actually offers. A relayed service selects the model server-side, so
# there's nothing to pin — and --model can't be honored, so say so rather than ignore it.
#
# KNOWN GAP (deferred): ANTHROPIC_MODEL is checked client-side, so this covers services
# whose targets are canonical Anthropic names (an API-key Anthropic service); a Bedrock
# service's region-prefixed slug can be rejected there. Only an opus-less Bedrock service
# hits this — an opus-having one returns None above and is unaffected — and that case was
# already broken (bare launch 403s on opus). The follow-up fix is to pin the servable
# target into the opus family slot instead (that channel is passed through unchecked).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can u rm all this

Comment thread src/ucode/databricks.py
# Claude Code starts every session on its opus tier, which the gateway 403s when a Model Provider
# Service declares no opus target. When opus is missing, fall back to the most capable tier the
# service does offer. opus > sonnet > haiku.
_CLAUDE_LAUNCH_TIER_PREFERENCE = ("opus", "sonnet", "haiku")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no fable?

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