Skip to content

MPS: resolve relayed --model against a curated target allowlist - #435

Open
masonc08 wants to merge 2 commits into
mainfrom
masonc08/mps-relayed-allowlist
Open

MPS: resolve relayed --model against a curated target allowlist#435
masonc08 wants to merge 2 commits into
mainfrom
masonc08/mps-relayed-allowlist

Conversation

@masonc08

@masonc08 masonc08 commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #427.

Problem

#427 forwards --model to Claude Code's own flag for a relayed provider — right for allow_all relays (the common Enterprise shape). But a relayed Team/Enterprise service that declares a curated model allowlist still breaks:

  • --model opus is forwarded verbatim; if Claude Code's opus alias resolves to an id that isn't byte-for-byte the declared target, the gateway 403s.
  • a bare launch uses Claude Code's subscription default (e.g. Sonnet 5), which the allowlist may forbid → 403 on the first prompt.

The gateway enforces the allowlist for Team/Enterprise (ExternalModelDirectClient.isModelAllowed), so the forwarded id must be one the service declares.

Change

For a relayed provider, resolve --model (and the bare-launch default) against the declared targets, then forward the resolved id via Claude Code's --model flag:

  • --model opus → the declared opus target,
  • no --model → the best allowed tier (so it doesn't dead-end on a forbidden default),
  • a family the service doesn't declare → a clear error,
  • an allow_all relay (no declared targets) → forward as-is (unchanged from MPS: forward --model to Claude Code for a relayed provider #427).

Mechanics: resolve_provider_models no longer exempts relayed — it maps declared targets like any Anthropic service (allow_all yields none). resolve_provider_launch_model gains always_select, since a relayed launch forwards via Claude Code's flag and has no pinned family alias to fall back on when opus is present.

Testing

  • Unit: relayed allowlist cases in test_cli (alias → declared target, auto-pick best tier, unavailable-family error); resolve_provider_models maps relayed targets (test_agents_init); always_select (test_databricks). 734 green, ruff clean.
  • Not e2e-verified: I don't have a curated-allowlist relay to test against — the real relays we've seen are allow_all. One assumption to confirm live: Claude Code's --model accepts a full canonical id (e.g. claude-opus-4-8), not only opus/sonnet/haiku aliases. If it doesn't, we'd forward the family alias for relayed instead.

This pull request and its description were written by Isaac.

A relayed (Claude Max/Team/Enterprise subscription) Model Provider Service is a
subscription relay: the AI Gateway passes the client's requested model through to
Anthropic and, for Team/Enterprise, validates it against the service's allowlist
(only personal Max skips that) -- it never selects a model server-side. Real
Enterprise relays are allow_all_targets with no declared Claude targets, so there
is nothing for ucode to resolve --model against.

So for a relayed provider, forward --model to Claude Code's own --model flag --
exactly what 'ucode claude --provider <mps> -- --model X' already does, now
automatic. Claude Code selects the model natively and the relay honors it.
Non-relayed providers (API-key / Bedrock) keep the env-pinning path unchanged.

Verified end-to-end against a relayed Enterprise MPS: '-- --model opus' launches
on Opus via the subscription.

Co-authored-by: Isaac <no-reply@databricks.com>
@masonc08
masonc08 force-pushed the masonc08/mps-relayed-allowlist branch from e9fe90f to 20eb50f Compare September 1, 2026 15:10
Follow-up to #427 (which forwards --model to Claude Code for a relayed provider).
That covers allow_all relays; a relayed Team/Enterprise service that declares a
curated model allowlist still needs its --model reconciled against those targets,
since the AI Gateway enforces them -- forwarding a bare alias or Claude Code's
subscription default can 403.

For a relayed provider, resolve --model (and the bare-launch default) against the
declared targets, then forward the resolved id via Claude Code's own --model flag:
--model opus -> the declared opus target; no --model -> the best allowed tier; an
allow_all relay declares nothing -> forward as-is (unchanged). Stops exempting
relayed in resolve_provider_models; adds resolve_provider_launch_model
always_select (relayed has no pinned family alias to fall back on).

Unit-tested; the curated-allowlist path is not e2e-verified (real relays we've
seen are allow_all). One assumption to confirm live: Claude Code's --model accepts
a full canonical id (e.g. claude-opus-4-8), not only opus/sonnet/haiku aliases.

Co-authored-by: Isaac <no-reply@databricks.com>
@masonc08
masonc08 force-pushed the masonc08/mps-relayed-allowlist branch from 20eb50f to d0e701f Compare September 1, 2026 15:16
Base automatically changed from masonc08/mps-relayed-honor-model to main September 1, 2026 23:47
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.

1 participant