Skip to content

copilot: run ug copilot on a Unity Catalog model location - #1256

Draft
xi-db wants to merge 14 commits into
mainfrom
xi-db/stack/copilot-model-location
Draft

xi-db wants to merge 14 commits into
mainfrom
xi-db/stack/copilot-model-location

Conversation

@xi-db

@xi-db xi-db commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

🥞 Stacked PR

Use this link to review incremental changes.


What did you change, and why?

Change: ug copilot --model-location <catalog>.<schema> runs Copilot on the Unity Catalog model services of one schema, with them in /model. Claude Code and Codex already support model locations; Copilot only had system.ai and, in #1220, provider services.

  • Discovery, as for Claude Code.
    • The models come from the gateway's Anthropic model listing with the Databricks-Model-Service-Parent-Schema header, the same listing Claude Code's picker uses.
    • The listing names services by gateway alias (anthropic-aigw-<hash>-<catalog.schema.name>); Copilot registers and sends the full name, which the gateway routes as a model service.
    • The header only scopes the listing. Inference routes by the model id, so the registry carries no header.
  • Wire per service.
    • Services named like Claude or GPT models (…claude-sonnet-4-6, …gpt-5-6-luna) use the same wire as the system.ai catalog. GPT 5+ goes on Responses on /ai-gateway/mlflow/v1, because GPT 5+ rejects the temperature Copilot sends on the Anthropic wire.
    • Everything else (names that don't say which model backs them) goes on the Anthropic wire, as Claude Code sends every service. The gateway translates for other models.
    • claude-opus-4-1 is skipped, as in the system.ai catalog.
    • Claude limits are capped at 200K where Copilot's catalog limits exceed it, as for provider services, since a model service may not serve the 1M window.
  • Selection. --model-location, the saved "Custom Model Location" in ug configure and the managed unity_catalog_location now apply to Copilot like Claude Code and Codex (MODEL_LOCATION_TOOLS). --provider and --model-location stay mutually exclusive. The managed Databricks model list is ignored under a location.

How do you know it works?

Testing:

  • Unit:
    • location catalog: alias stripping, the name-based wire with the Anthropic fallback, claude-opus-4-1 skipped, the listing called with the schema, an empty schema;
    • a launch through the real proxy with a stubbed Copilot process: registry ids and wires, no header, 200K limits, start model;
    • ug copilot --model-location reaching the launch.
    • just lint is clean.
  • Integration (new tests/integration/test_ug_copilot_model_location.py, non-blocking Copilot lane): from fresh state, ug copilot --workspace … --model-location <model-discovery schema> --model <its Claude-compatible service> -p … completes a file task, with the answering model checked from Copilot's own session events.
  • Live (ug from this branch, a Databricks workspace):
    • --model-location system.ai started on system.ai.claude-sonnet-5-5 and answered.
    • --model system.ai.gpt-5-6-luna answered on dbx-responses. The same model on the Anthropic wire failed with "Unsupported parameter: 'temperature'", which is why GPT-named services use Responses.

Limits: a GPT 5+ model behind a service whose name doesn't say GPT goes on the Anthropic wire and can hit the same temperature rejection. Telling those apart needs each service's backing model, a possible follow-up.

Stacked on #1220.

This pull request and its description were written by Isaac.

@xi-db xi-db added the ug-review Run the automated UG review label Oct 22, 2026
@xi-db
xi-db force-pushed the xi-db/stack/copilot-model-location branch 5 times, most recently from 76d745b to 856a99d Compare October 23, 2026 10:00
xi-db and others added 14 commits October 23, 2026 10:24
ug copilot --provider <catalog>.<schema>.<name> registers the service's models in
the session registry: Claude models of Anthropic and Bedrock services on the
Anthropic endpoint, chat models of OpenAI and Azure OpenAI services on the
gateway's native OpenAI route (Responses for GPT 5+ and o-series, Chat
Completions otherwise). Every registry provider sends the
Databricks-Model-Provider-Service header, so the proxy needs no routing change.

Provider ids are classified whole (gpt-5.5, us.anthropic.claude-sonnet-4-6),
not as system.ai names, and dated or versioned Claude ids map to Copilot's
catalog id. A service that allows every model lists them through the gateway;
an empty listing (which is what a caller without permission gets) asks for
--model. Subscription-relay services are refused for Copilot. ug configure
offers matching services, and a managed model_provider_service applies.

Co-authored-by: Isaac <no-reply@databricks.com>
Provider ids write versions with dots (gpt-5.6), which the version sort read as
unversioned, so a provider session started on its oldest GPT.

Co-authored-by: Isaac <no-reply@databricks.com>
…rors

- Region-less Bedrock and Mantle Claude ids (anthropic.claude-*) map to
  Copilot's catalog id, limits and family order again.
- An allow-all service starts only on --model or the managed default: the
  gateway lists a fixed catalog for it, not what the provider account serves.
  A --model in Copilot's dbx-<wire>/<id> form is accepted as the id.
- A failed allow-all listing reports its cause instead of being treated as an
  empty list.
- o-series models sort newest first; provider Claude limits are capped only
  where they exceed 200K.

Co-authored-by: Isaac <no-reply@databricks.com>
A provider target lists its native_api_types. A target that declares none of
the chat APIs (Anthropic Messages, Chat Completions, Responses), such as an
embedding deployment, is skipped. The API types only exclude: the gateway
serves some models on APIs they don't declare (gpt-5.2-chat declares only Chat
Completions and answers on Responses). This replaces the name pattern; the
gateway listing for allow-all services is left unfiltered, as for Codex.

Co-authored-by: Isaac <no-reply@databricks.com>
list_provider_service_models picks the Anthropic or Codex listing for a
provider type and returns (ids, reason), reporting an empty listing as empty
rather than a failure. Copilot no longer imports the private Codex catalog
helper or matches another module's error text to tell the two apart.

Co-authored-by: Isaac <no-reply@databricks.com>
…dex and Claude

Without --model or a managed default, an allow-all service now starts on
Copilot's default pick from the gateway's listing instead of refusing to
launch, matching ug codex and ug claude. ug still asks for --model when the
listing is empty or fails.

Co-authored-by: Isaac <no-reply@databricks.com>
The launch targets that workspace and sets it up first when it isn't
configured yet. Before, the flag was passed through to Copilot itself.

Co-authored-by: Isaac <no-reply@databricks.com>
- One rule for what an agent can use a Model Provider Service for, shared by
  service_usable_for_tool and resolve_provider_service. A subscription relay
  is refused for every agent but Claude Code, not only Copilot.
- ANTHROPIC_API_PROVIDER_TYPES names the provider types the gateway serves
  on its Anthropic route, for both the listing and Copilot's classifier.
- Copilot classifies provider ids with the same name rules as system.ai
  models, and derives its chat API set from its wire routes.
- The Codex listing reuses catalog_slugs; the provider-service catalog is
  built once; Copilot's provider OpenAI base URL moves into copilot.py.

Co-authored-by: Isaac <no-reply@databricks.com>
bare_model_name() in databricks.py replaces Copilot's split/removeprefix
chain with one regex, with examples of each id shape it handles. The wire
names Copilot writes to its registry are constants.

Co-authored-by: Isaac <no-reply@databricks.com>
classify_model() holds every rule that maps a model id to Copilot's wire, for
Databricks model services and Model Provider Service targets alike, and
replaces classify_provider_model. build_catalog() builds every catalog from
(model, api_types) pairs and replaces build_provider_catalog. launch picks
its catalog through _session_catalog(). A system.ai o-series model now uses
Responses, like o-series provider targets.

Co-authored-by: Isaac <no-reply@databricks.com>
The API types the gateway lists in supported_api_types and native_api_types
(anthropic/v1/messages, openai/v1/responses, ...) are shared constants, used
by Copilot's wire table and by Databricks endpoint discovery.

Co-authored-by: Isaac <no-reply@databricks.com>
Our new code used "provider" for a Model Provider Service, a Copilot
registry provider and the upstream vendor. Name each one: LAUNCH_PROVIDER_KEY
is LAUNCH_PROVIDER_SERVICE_KEY, provider_catalog is provider_service_catalog,
_without_provider_prefix is _without_registry_prefix, and comments, docstrings
and messages spell out which one they mean.

Co-authored-by: Isaac <no-reply@databricks.com>
Copilot sends reasoning_effort on Chat Completions. Only models that aren't GPT
5+ or o-series use that wire, and OpenAI and Azure reject the field for them
("Unrecognized request argument supplied: reasoning_effort"), so gpt-4o-mini
and gpt-4.1-mini failed through a Model Provider Service. The session proxy
now removes it from Chat Completions bodies; other requests pass unchanged.

Co-authored-by: Isaac <no-reply@databricks.com>
ug copilot --model-location <catalog>.<schema> registers the schema's model
services in the session registry, from the gateway's Anthropic model listing
as for Claude Code. Services are sent by full name; the gateway routes them
as model services. Services named like Claude or GPT models use their usual
wire (GPT 5+ on Responses, since GPT 5+ rejects the temperature Copilot sends
on the Anthropic wire); the rest use the Anthropic wire, which the gateway
translates for other models. The saved Custom Model Location and the managed
unity_catalog_location apply to Copilot like Claude Code and Codex.

Co-authored-by: Isaac <no-reply@databricks.com>
@xi-db
xi-db force-pushed the xi-db/stack/copilot-model-location branch from 856a99d to a04cb29 Compare October 23, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ug-review Run the automated UG review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant