Fix multi-workspace host auth: append o=<workspace_id> to discovery calls - #260
Open
jcampabadal-db wants to merge 2 commits into
Open
Fix multi-workspace host auth: append o=<workspace_id> to discovery calls#260jcampabadal-db wants to merge 2 commits into
jcampabadal-db wants to merge 2 commits into
Conversation
…alls On a Databricks host that serves multiple workspaces, an account-audience OAuth token is rejected at the authz layer unless the request carries the workspace disambiguator. Without it, the AI Gateway v2 probe (`GET /api/ai-gateway/v2/endpoints`) and the model-discovery calls (`/api/2.1/unity-catalog/model-services`, `/ai-gateway/anthropic/v1/models`) 303-redirect to `/login`, and ucode reads the returned login HTML/empty body as "response was not valid JSON". `ucode configure` then aborts with "Unity AI Gateway probe failed" / "No coding agents are available", even though the workspace is fully gateway-enabled. Centralize the fix in the HTTP helpers: `_with_workspace_disambiguator` appends `o=<workspace_id>` (resolved from the matching ~/.databrickscfg profile) to any workspace URL that lacks it. Single-workspace hosts ignore the extra param, so the change is a no-op there. Verified end-to-end against a multi-workspace staging host: the probe and model discovery return HTTP 200 with the param and 303 to /login without it, and `ucode configure --agents claude` completes and validates. Co-authored-by: Isaac
jcampabadal-db
force-pushed
the
fix/multi-workspace-o-param
branch
from
August 3, 2026 21:31
d874dfe to
d4aa1ad
Compare
Author
|
The following monkey patch also fixes this error: ERROR Databricks Unity AI Gateway probe failed on this workspace (response was not valid JSON (Expecting value) |
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
On a Databricks host that serves multiple workspaces, the CLI issues an account-audience OAuth token. The workspace APIs reject that token at the authz layer unless the request carries the workspace disambiguator
o=<workspace_id>. Without it they respond303to/login, and ucode parses the returned sign-in HTML as JSON.ucode configuretherefore aborts before writing any agent config:Patching only the probe moves the failure one step later, to model discovery:
The affected requests all flow through
_http_get_json/_http_post_json:GET /api/ai-gateway/v2/endpoints— theensure_ai_gateway_v2probeGET /api/2.1/unity-catalog/model-services— model discoveryGET /ai-gateway/anthropic/v1/modelsGET /api/2.0/sql/warehouses, the UC catalog/schema/function listings, etc.The workspace is fully gateway-enabled and the token is valid — the request just can't be attributed to a workspace.
Observed against a multi-workspace staging host:
An
X-Databricks-Org-Id: <workspace_id>header works equivalently.Fix
Centralize it in the two HTTP helpers rather than at the ~30 individual call sites that each build
f"https://{hostname}/..."._workspace_id_for_hostname(hostname)reads~/.databrickscfg(honoringDATABRICKS_CONFIG_FILE), normalizes each profile'shostto a hostname, and returns theworkspace_idof the first match. Blank values and the literalnoneare skipped, so a workspace-scoped profile wins over an account-only profile on the same host — a common layout, since an account-leveldatabricks auth loginwritesworkspace_id = none._with_workspace_disambiguator(url)appends?o=<id>or&o=<id>as appropriate._http_get_jsonand_http_post_jsoneach call it on entry.It is a no-op wherever it isn't needed: a single-workspace host ignores the extra param, an account-only profile resolves to
None, a URL already carryingo=is untouched, and a malformed or missing config degrades to current behavior instead of raising. No authentication logic changes — same token, same headers, same audience.Verification
After the change, against the same host:
ucode claude -p "..."then runs headless againstsystem.ai.claude-opus-5through the gateway.Tests
8 focused tests in
tests/test_databricks.py(TestWorkspaceIdForHostname,TestWithWorkspaceDisambiguator): resolving past an account-only profile on the same host, a second distinct host, unknown host, missing config file, append with and without an existing query string, and the no-op wheno=is already present.Note for reviewers
ci.ymltriggers onpull_request, and GitHub withholds repo secrets from fork-based PRs, so the steps needingUCODE_TEST_WORKSPACE/DATABRICKS_BEARERwon't have credentials here. Unit tests and lint run normally; the e2e job may need aworkflow_dispatchre-run from a branch in this repo.