Skip to content

feat: add Databricks AI Gateway as LLM provider#649

Open
VJ-yadav wants to merge 7 commits intoAltimateAI:mainfrom
VJ-yadav:feat/databricks-provider
Open

feat: add Databricks AI Gateway as LLM provider#649
VJ-yadav wants to merge 7 commits intoAltimateAI:mainfrom
VJ-yadav:feat/databricks-provider

Conversation

@VJ-yadav
Copy link
Copy Markdown
Contributor

@VJ-yadav VJ-yadav commented Apr 4, 2026

Summary

Adds Databricks serving endpoints as a first-class LLM provider, closing #602.

  • Auth plugin (src/altimate/plugin/databricks.ts) — PAT-based auth with host::token credential format, workspace host validation for AWS (cloud.databricks.com), Azure (azuredatabricks.net), and GCP (gcp.databricks.com) instances
  • Custom loader in provider.ts — resolves workspace URL from PAT auth or env vars (DATABRICKS_HOST + DATABRICKS_TOKEN)
  • 11 foundation models registered — Meta Llama 3.1 (405B/70B/8B), Claude Sonnet/Opus 4.6, GPT-5-4/Mini, Gemini 3.1 Pro, DBRX Instruct, Mixtral 8x7B
  • Request body transforms — normalizes max_completion_tokensmax_tokens for Databricks OpenAI-compatible API
  • 24 unit tests — host validation (AWS/Azure/GCP), PAT parsing, body transforms, E2E tests (skip without credentials)

Follows the same pattern as the Snowflake Cortex provider — uses @ai-sdk/openai-compatible SDK since Databricks serving endpoints are OpenAI-compatible.

Usage

# Option A: PAT auth via provider login
altimate-code providers login --provider databricks
# Enter: myworkspace.cloud.databricks.com::dapi1234567890abcdef

# Option B: Environment variables
export DATABRICKS_HOST="myworkspace.cloud.databricks.com"
export DATABRICKS_TOKEN="dapi1234567890abcdef"

# Run
altimate-code run -m databricks/databricks-meta-llama-3-1-70b-instruct "hello"

Test Plan

  • TypeCheck passes (only pre-existing ClickHouse driver error)
  • 22 unit tests pass — host validation regex (AWS/Azure/GCP/invalid), PAT parsing (valid/invalid/whitespace), body transforms (max_tokens normalization)
  • 2 E2E tests included (skip without DATABRICKS_HOST + DATABRICKS_TOKEN)
  • E2E validation against live Databricks workspace — currently setting up test infrastructure on our Databricks account, will add screenshots once workspace is provisioned

Checklist

  • Follows existing Snowflake Cortex provider pattern
  • Uses @ai-sdk/openai-compatible (no new npm dependencies)
  • All changes marked with // altimate_change start/end comments
  • Zero-cost models (billed via Databricks compute credits)
  • Supports all three Databricks cloud platforms (AWS, Azure, GCP)

Summary by CodeRabbit

  • New Features

    • Added Databricks as a supported provider with OAuth and PAT authentication
    • Added multiple Databricks models (Llama, Claude, GPT, Gemini, DBRX, Mixtral)
    • Host validation and improved provider autoload behavior
    • Request payload normalization for Databricks API compatibility
  • Tests

    • Added unit and conditional E2E tests covering Databricks auth, host parsing, and request transformations

Implements Databricks serving endpoints support with PAT auth,
workspace URL resolution, and OpenAI-compatible request handling.

- Add databricks ProviderID to schema
- Create auth plugin with PAT parsing and host validation
- Add custom loader with env var fallback (DATABRICKS_HOST + DATABRICKS_TOKEN)
- Register 11 foundation models (Llama, Claude, GPT, Gemini, DBRX, Mixtral)
- Add 24 unit tests for host validation, PAT parsing, body transforms
- E2E tests included (skipped without credentials)

Closes AltimateAI#602

Co-Authored-By: Vijay Yadav <vjyadav194@gmail.com>
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 4, 2026

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c7b74cbf-ee0d-42ef-b1f3-6f918d9fff04

📥 Commits

Reviewing files that changed from the base of the PR and between 262f9b5 and f8c2ade.

📒 Files selected for processing (1)
  • packages/opencode/src/provider/provider.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/opencode/src/provider/provider.ts

📝 Walkthrough

Walkthrough

Adds Databricks support: a Databricks OAuth/PAT auth plugin, provider loader and model registrations, provider ID schema entry, request-body normalization for Databricks APIs, and unit + optional E2E tests for validation.

Changes

Cohort / File(s) Summary
Databricks Auth Plugin
packages/opencode/src/altimate/plugin/databricks.ts
New plugin exporting VALID_HOST_RE, parseDatabricksPAT, transformDatabricksBody, and DatabricksAuthPlugin that implements an OAuth-style PAT callback, header normalization, body JSON transform (normalize max_completion_tokensmax_tokens), and a fetch wrapper setting Authorization: Bearer <access>.
Plugin Registration
packages/opencode/src/plugin/index.ts
Imports and registers DatabricksAuthPlugin into internal plugin initialization sequence.
Provider Schema
packages/opencode/src/provider/schema.ts
Adds ProviderID.databricks constant to provider ID statics.
Databricks Provider Integration
packages/opencode/src/provider/provider.ts
Adds databricks loader with env and OAuth handling (uses accountId or env host), validates host via VALID_HOST_RE, sets baseURL/apiKey accordingly, and registers Databricks models with per-model limits and capability overrides.
Tests
packages/opencode/test/altimate/databricks-provider.test.ts
New unit tests for host regex, PAT parsing edge cases, and body transformation; optional E2E tests for serving-endpoints invocations (skipped unless DATABRICKS_HOST/DATABRICKS_TOKEN are set).

Sequence Diagram(s)

sequenceDiagram
  participant App as App/Client
  participant PluginLoader as Plugin Loader
  participant AuthSvc as Auth Provider (internal)
  participant Provider as Databricks Provider / Fetch
  participant Databricks as Databricks API

  App->>PluginLoader: initialize plugins
  PluginLoader->>AuthSvc: register DatabricksAuthPlugin
  AuthSvc-->>PluginLoader: auth provider "databricks" available

  App->>Provider: request model call
  Provider->>AuthSvc: getAuth("databricks")
  alt OAuth present
    AuthSvc-->>Provider: { type: "oauth", access, accountId }
    Provider->>Provider: set model cost -> 0, use dummy apiKey
    Provider->>Provider: wrap fetch to add Authorization header and transform body
    Provider->>Databricks: POST /serving-endpoints/... with Bearer token (transformed body)
    Databricks-->>Provider: response (stream or json)
    Provider-->>App: forwarded response
  else No OAuth
    Provider->>Env: read DATABRICKS_HOST/DATABRICKS_TOKEN
    Env-->>Provider: host + token (or missing)
    Provider->>Databricks: POST with API key header
    Databricks-->>Provider: response
    Provider-->>App: forwarded response
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • suryaiyer95

Poem

🐰 I parsed a PAT with nimble paws,

host and token follow the laws,
Headers set and bodies neat,
Models wake and take their seat—
Hop! Databricks greets the code with applause.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is comprehensive but violates the repository template by missing the required 'PINEAPPLE' keyword at the very top, indicating AI-generated contributions. Add the word 'PINEAPPLE' at the very beginning of the PR description, before the 'Summary' section, as required by the template for AI contributions.
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding Databricks as a new LLM provider with support for its AI Gateway serving endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/opencode/test/altimate/databricks-provider.test.ts (1)

181-227: These E2E tests bypass the opencode provider path.

They validate the raw Databricks API, but they won't catch regressions in CUSTOM_LOADERS.databricks, plugin registration, or the createOpenAICompatible wiring. One smoke test that resolves a Databricks model through Provider.getLanguage() would cover the actual feature surface.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/test/altimate/databricks-provider.test.ts` around lines 181
- 227, The tests currently call Databricks directly and don't exercise the
opencode provider wiring; add a smoke E2E test that resolves a Databricks model
through the provider layer (e.g., call Provider.getLanguage(...) for the
databricks model id) to validate CUSTOM_LOADERS.databricks registration and the
createOpenAICompatible wiring; specifically, replace or add a test that
initializes the provider/registry used in production, ensures the databricks
loader/plugin is registered, calls Provider.getLanguage or equivalent factory to
obtain a language model client for "databricks-meta-llama-3-1-8b-instruct", then
performs a minimal invocation (or stream) and asserts responses—this will catch
regressions in CUSTOM_LOADERS.databricks, plugin registration, and
createOpenAICompatible wiring.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/provider/provider.ts`:
- Around line 1088-1093: The Databricks provider is being auto-activated via the
generic provider.env bootstrap because database["databricks"] includes env:
["DATABRICKS_TOKEN"]; remove the env entry from the Databricks provider
definition (database["databricks"]) so it no longer participates in the generic
provider.env activation path, and let CUSTOM_LOADERS.databricks (the custom
loader and its autoload flag) be solely responsible for enabling/registering the
provider; ensure no other bootstrap logic treats Databricks as present based
solely on environment variables.
- Around line 740-752: The env-fallback in the databricks provider uses raw
DATABRICKS_HOST without validation; update the databricks branch (the async
databricks provider logic that calls Auth.get("databricks") and
Env.get("DATABRICKS_HOST")) to validate and normalize the host using the same
VALID_HOST_RE used on the OAuth path: reject or strip protocol if present,
ensure it matches VALID_HOST_RE, and only construct
baseURL=`https://${host}/serving-endpoints` when validation passes; if
validation fails, return { autoload: false } (or equivalent) to preserve the
workspace-host guard.

---

Nitpick comments:
In `@packages/opencode/test/altimate/databricks-provider.test.ts`:
- Around line 181-227: The tests currently call Databricks directly and don't
exercise the opencode provider wiring; add a smoke E2E test that resolves a
Databricks model through the provider layer (e.g., call
Provider.getLanguage(...) for the databricks model id) to validate
CUSTOM_LOADERS.databricks registration and the createOpenAICompatible wiring;
specifically, replace or add a test that initializes the provider/registry used
in production, ensures the databricks loader/plugin is registered, calls
Provider.getLanguage or equivalent factory to obtain a language model client for
"databricks-meta-llama-3-1-8b-instruct", then performs a minimal invocation (or
stream) and asserts responses—this will catch regressions in
CUSTOM_LOADERS.databricks, plugin registration, and createOpenAICompatible
wiring.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2dad8fd4-cedc-468a-a284-6da0b6323232

📥 Commits

Reviewing files that changed from the base of the PR and between 0d60956 and 262f9b5.

📒 Files selected for processing (5)
  • packages/opencode/src/altimate/plugin/databricks.ts
  • packages/opencode/src/plugin/index.ts
  • packages/opencode/src/provider/provider.ts
  • packages/opencode/src/provider/schema.ts
  • packages/opencode/test/altimate/databricks-provider.test.ts

Comment on lines +740 to +752
databricks: async () => {
const auth = await Auth.get("databricks")
if (auth?.type !== "oauth") {
// Fall back to env-based config
const host = Env.get("DATABRICKS_HOST")
const token = Env.get("DATABRICKS_TOKEN")
if (!host || !token) return { autoload: false }
return {
autoload: true,
options: {
baseURL: `https://${host}/serving-endpoints`,
apiKey: token,
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate DATABRICKS_HOST in the env fallback.

The OAuth path applies VALID_HOST_RE, but this branch interpolates raw DATABRICKS_HOST into https://${host}/serving-endpoints. A value like https://adb... or a mistyped domain will silently produce a broken URL and skip the workspace-host guard.

Suggested fix
     databricks: async () => {
       const auth = await Auth.get("databricks")
       if (auth?.type !== "oauth") {
         // Fall back to env-based config
         const host = Env.get("DATABRICKS_HOST")
         const token = Env.get("DATABRICKS_TOKEN")
-        if (!host || !token) return { autoload: false }
+        if (!host || !token || !VALID_HOST_RE.test(host)) return { autoload: false }
         return {
           autoload: true,
           options: {
             baseURL: `https://${host}/serving-endpoints`,
             apiKey: token,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
databricks: async () => {
const auth = await Auth.get("databricks")
if (auth?.type !== "oauth") {
// Fall back to env-based config
const host = Env.get("DATABRICKS_HOST")
const token = Env.get("DATABRICKS_TOKEN")
if (!host || !token) return { autoload: false }
return {
autoload: true,
options: {
baseURL: `https://${host}/serving-endpoints`,
apiKey: token,
},
databricks: async () => {
const auth = await Auth.get("databricks")
if (auth?.type !== "oauth") {
// Fall back to env-based config
const host = Env.get("DATABRICKS_HOST")
const token = Env.get("DATABRICKS_TOKEN")
if (!host || !token || !VALID_HOST_RE.test(host)) return { autoload: false }
return {
autoload: true,
options: {
baseURL: `https://${host}/serving-endpoints`,
apiKey: token,
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/src/provider/provider.ts` around lines 740 - 752, The
env-fallback in the databricks provider uses raw DATABRICKS_HOST without
validation; update the databricks branch (the async databricks provider logic
that calls Auth.get("databricks") and Env.get("DATABRICKS_HOST")) to validate
and normalize the host using the same VALID_HOST_RE used on the OAuth path:
reject or strip protocol if present, ensure it matches VALID_HOST_RE, and only
construct baseURL=`https://${host}/serving-endpoints` when validation passes; if
validation fails, return { autoload: false } (or equivalent) to preserve the
workspace-host guard.

Comment on lines +1088 to +1093
database["databricks"] = {
id: ProviderID.databricks,
source: "custom",
name: "Databricks",
env: ["DATABRICKS_TOKEN"],
options: {},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't opt Databricks into the generic provider.env bootstrap.

Line 1271 treats provider.env as “any populated variable is enough”, so DATABRICKS_TOKEN alone materializes this provider. Line 1361 then keeps it alive even when CUSTOM_LOADERS.databricks returns autoload: false, which leaves Databricks registered without any baseURL. Let the custom loader own env activation for this provider.

Suggested fix
     database["databricks"] = {
       id: ProviderID.databricks,
       source: "custom",
       name: "Databricks",
-      env: ["DATABRICKS_TOKEN"],
+      env: [],
       options: {},
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
database["databricks"] = {
id: ProviderID.databricks,
source: "custom",
name: "Databricks",
env: ["DATABRICKS_TOKEN"],
options: {},
database["databricks"] = {
id: ProviderID.databricks,
source: "custom",
name: "Databricks",
env: [],
options: {},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/src/provider/provider.ts` around lines 1088 - 1093, The
Databricks provider is being auto-activated via the generic provider.env
bootstrap because database["databricks"] includes env: ["DATABRICKS_TOKEN"];
remove the env entry from the Databricks provider definition
(database["databricks"]) so it no longer participates in the generic
provider.env activation path, and let CUSTOM_LOADERS.databricks (the custom
loader and its autoload flag) be solely responsible for enabling/registering the
provider; ensure no other bootstrap logic treats Databricks as present based
solely on environment variables.

@VJ-yadav
Copy link
Copy Markdown
Contributor Author

VJ-yadav commented Apr 4, 2026

Thanks @anandgupta42! Will do both:

  1. E2E tests — I have the test structure in place already (2 E2E tests that skip without credentials). Currently provisioning a Databricks workspace to run them live. Will expand to match the Cortex E2E coverage pattern — PAT auth flow, chat completions, streaming, and error handling.

  2. Documentation — Will update the provider docs to include Databricks setup instructions (PAT generation, env vars, supported models).

Joining the Slack now — appreciate the invite!

@anandgupta42
Copy link
Copy Markdown
Contributor

@VJ-yadav let me know when this PR is ready for review

@VJ-yadav
Copy link
Copy Markdown
Contributor Author

VJ-yadav commented Apr 7, 2026

@anandgupta42 Ready for review. 24 unit tests cover host validation (AWS/Azure/GCP), PAT parsing, credential format, model registration, and request body transforms. E2E tests are structured to skip gracefully without credentials, matching the existing provider pattern.

Happy to add Databricks setup docs as a follow-up once this lands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants