Repository navigation
feat(appkit): add DatabricksAdapter.fromAiGateway for gateway chat completions - #605
Merged
Merged
Conversation
…mpletions Route agents through the Databricks AI Gateway Chat Completions endpoint (/ai-gateway/mlflow/v1/chat/completions), naming the model in the request body (e.g. system.ai.claude-opus-5-5) instead of in the URL. Reuses the existing Chat Completions tool loop and SSE parsing unchanged. Additive and non-breaking: the serving-endpoint path (fromModelServing, fromServingEndpoint, bare-string model) never sets a body model, so its request is byte-identical to before. Co-authored-by: Isaac <no-reply@databricks.com> Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Contributor
📦 Bundle size reportCompared against
|
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 1.2 MB (+3.4 KB) | 426 KB (+1.0 KB) |
| Type declarations | 446 KB (+2.4 KB) | 162 KB (+674 B) |
| Source maps | 2.3 MB (+7.2 KB) | 799 KB (+2.0 KB) |
| Other | 11 KB | 3.7 KB |
| Total | 4.0 MB (+13 KB) | 1.4 MB (+3.7 KB) |
Per-entry composition (own code — deps external (as shipped))
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
. |
96 KB | 2.5 KB | 98 KB | external | 314 KB |
./beta |
93 KB (+170 B) | 480 B (+23 B) | 94 KB (+193 B) | external | 281 KB (+540 B) |
./testing |
38 KB | 30 KB | 69 KB | external | 201 KB |
./tsdown |
520 B | 0 B | 520 B | external | 813 B |
./type-generator |
23 KB | 0 B | 23 KB | external | 65 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
. |
index.js |
initial | 92 KB |
. |
utils.js |
initial | 4.0 KB |
. |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./beta |
beta.js |
initial | 77 KB |
./beta |
stream-manager.js |
initial | 5.8 KB |
./beta |
databricks.js |
initial | 3.3 KB |
./beta |
wide-event-emitter.js |
initial | 3.2 KB |
./beta |
configuration.js |
initial | 2.3 KB |
./beta |
service-context.js |
initial | 1.3 KB |
./beta |
client.js |
initial | 434 B |
./beta |
client-options.js |
initial | 219 B |
./beta |
supervisor-api.js |
lazy | 192 B |
./beta |
databricks.js |
lazy | 165 B |
./beta |
index.js |
lazy | 123 B |
./testing |
manifest.js |
initial | 26 KB |
./testing |
index.js |
initial | 10.0 KB |
./testing |
wide-event-emitter.js |
initial | 2.9 KB |
./testing |
index.js |
lazy | 26 KB |
./testing |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./testing |
utils.js |
lazy | 1.2 KB |
./tsdown |
index.js |
initial | 520 B |
./type-generator |
index.js |
initial | 23 KB |
@databricks/appkit-ui
npm tarball (packed): 350 KB — gzipped download (dist + bin; excludes release-only docs/NOTICE).
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 395 KB | 132 KB |
| Type declarations | 229 KB | 84 KB |
| Source maps | 766 KB | 253 KB |
| CSS | 16 KB | 3.2 KB |
| Total | 1.4 MB | 472 KB |
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
./js |
5.3 KB | 49 KB | 55 KB | 208 KB | 14 KB |
./js/beta |
20 B | 0 B | 20 B | 0 B | 0 B |
./react |
432 KB | 49 KB | 481 KB | 1.3 MB | 177 KB |
./react/beta |
1.0 KB | 0 B | 1.0 KB | 0 B | 1.9 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
./js |
index.js |
initial | 5.2 KB |
./js |
chunk |
initial | 120 B |
./js |
apache-arrow |
lazy | 49 KB |
./js/beta |
beta.js |
initial | 20 B |
./react |
index.js |
initial | 430 KB |
./react |
tslib |
initial | 2.1 KB |
./react |
apache-arrow |
lazy | 49 KB |
./react/beta |
beta.js |
initial | 1.0 KB |
Contributor
🤖 AppKit PR bot🔬 Run evalsStart an eval for this PR from the evals-monitor app: Go to Evals Monitor → 📦 Try this PR's app templateScaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh run download 36422423929 -R databricks/appkit -n appkit-template-0.78.0-pr.0f7fbf2-feat-agents-ai-gateway-605 -D appkit-pr-605 \
&& unzip -o "appkit-pr-605/appkit-template-0.78.0-pr.0f7fbf2-feat-agents-ai-gateway-605.zip" -d "appkit-pr-605" \
&& databricks apps init --template "appkit-pr-605"The template pins |
Add adapterFromModelString(), the single decision point both string-model resolution sites (agents plugin + standalone runAgent) now share: a `system.*` UC model name (e.g. system.ai.claude-opus-5-5) resolves to the AI Gateway; any other string (serving-endpoint names like databricks-claude-sonnet-4-5, or custom endpoints) resolves to Model Serving. Non-breaking: serving-endpoint names are [a-zA-Z0-9_-] (no dots), so the `system.` prefix never matches an existing endpoint name. To force a `system.*` name onto a serving endpoint, pass a pre-built adapter as the agent's model. Co-authored-by: Isaac <no-reply@databricks.com> Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
atilafassina
approved these changes
Sep 28, 2026
…ateway routing The no-model default path resolved DATABRICKS_SERVING_ENDPOINT_NAME inside fromModelServing(), always building a serving-endpoint URL — so a `system.*` value (e.g. system.ai.claude-opus-4-6) 404'd instead of reaching the AI Gateway. Read the env default into the resolver's `source` so it flows through adapterFromModelString() like an explicit string model, in both the agents plugin and standalone runAgent. Co-authored-by: Isaac <no-reply@databricks.com> Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
… demo Points the autocomplete agent's `endpoint` at system.ai.gemini-3-5-flash-lite so the reference app exercises the new AI Gateway routing (a system.* string resolves to /ai-gateway/mlflow/v1/chat/completions). Co-authored-by: Isaac <no-reply@databricks.com> Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Regenerated API reference for the new fromAiGateway factory. Co-authored-by: Isaac <no-reply@databricks.com> Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
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.
What
Lets AppKit agents consume models through the Databricks AI Gateway Chat Completions endpoint (
/ai-gateway/mlflow/v1/chat/completions), naming the model in the request body (a UCsystem.*name, e.g.system.ai.claude-opus-5-5) instead of a per-endpoint URL. This is the migration path off the legacydatabricks-*serving-endpoint names.Two commits:
fromAiGatewayadapter —DatabricksAdapter.fromAiGateway({ model })explicit factory.modelthat starts withsystem.resolves to the gateway; anything else resolves to Model Serving as before. So the common case needs no factory:How
The gateway speaks the same OpenAI Chat Completions wire format the adapter already used, so the change is deliberately small:
connectors/serving/client.ts— newstreamAiGateway(): hard-codes the gateway path, forcesstream: true(mirrors the existingstream()serving helper; keepsstreamPath's@internalhard-coded-path contract).agents/databricks.ts— optionalmodelon the adapter options, injected into the body only when set;fromAiGatewayfactory; andadapterFromModelString()— the single decision point that both string-model resolution sites now share (plugins/agents/agents.ts+core/agent/run-agent.ts), so they can't drift.Everything else is reused unchanged: the multi-step tool loop, SSE parsing, dot→
__tool-name mapping, thought-signature pass-through, DoS caps, generation params.Non-breaking
modelis set on the request body only on the gateway path;fromModelServing/fromServingEndpointrequests are byte-identical to before (test-pinned).[a-zA-Z0-9_-](no dots), so thesystem.prefix never matches an existing endpoint name — no current string changes routing. Asystem.*string never worked as a serving-endpoint name anyway.system.*name onto a serving endpoint, pass a pre-builtDatabricksAdapter.fromServingEndpoint(...)as the agent'smodel.Verification
dogfoodgateway:/ai-gateway/mlflow/v1/chat/completions200s,model-in-body works (system.ai.claude-opus-5-5→global.anthropic.claude-opus-5-5), streaming SSE + tool-calling return in the exactchoices[0].delta/tool_calls[]shape the adapter parses.modelin body; serving path leavesmodelout; and thesystem.*vs non-systemrouting split.genie/sql-warehouse/mock-workspace-clientfiles only).This pull request and its description were written by Isaac.