Skip to content

Commit 888f8ba

Browse files
committed
feat(appkit): supervisor api adapter
1 parent d0013ae commit 888f8ba

10 files changed

Lines changed: 1650 additions & 62 deletions

File tree

apps/dev-playground/server/index.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
tool,
1515
WRITE_ACTIONS,
1616
} from "@databricks/appkit";
17+
import { fromSupervisorApi } from "@databricks/appkit/agents/supervisor-api";
1718
import { WorkspaceClient } from "@databricks/sdk-experimental";
1819
import { z } from "zod";
1920
import { lakebaseExamples } from "./lakebase-examples-plugin";
@@ -68,6 +69,33 @@ const helper = createAgent({
6869
},
6970
});
7071

72+
// Supervisor API demo agent. Tools are configured on the adapter (the SA
73+
// endpoint executes them server-side), not on the createAgent definition.
74+
// Uncomment a `supervisorTools.*` entry (and import 'supervisorTools' from
75+
// '@databricks/appkit/agents/supervisor-api') to give the model real powers.
76+
//
77+
// We `await` the factory at module init so a misconfigured workspace
78+
// (missing host, bad credentials) fails fast with a clear error here
79+
// instead of as an unhandled rejection. Top-level await is fine in this
80+
// ESM module.
81+
const supervisor = createAgent({
82+
instructions:
83+
"You are an assistant powered by the Databricks Supervisor API.",
84+
model: fromSupervisorApi({
85+
model: "databricks-claude-sonnet-4-5",
86+
tools: [
87+
// supervisorTools.genieSpace(
88+
// "01ABCDEF12345678",
89+
// "NYC taxi trip records and zones",
90+
// ),
91+
// supervisorTools.ucFunction(
92+
// "main.default.add",
93+
// "Adds two integers and returns the sum.",
94+
// ),
95+
],
96+
}),
97+
});
98+
7199
/*
72100
* Smart-Dashboard agents.
73101
*
@@ -367,7 +395,7 @@ createApp({
367395
}),
368396
serving(),
369397
agents({
370-
agents: { helper, sql_analyst, dashboard_pilot },
398+
agents: { helper, sql_analyst, dashboard_pilot, supervisor },
371399
// `query` (markdown dispatcher) + `sql_analyst` + `dashboard_pilot`
372400
// wire the /smart-dashboard route. `insights` and `anomaly` are
373401
// ephemeral markdown agents auto-fired by the route's AgentSidebar.

packages/appkit/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
"development": "./src/agents/databricks.ts",
4242
"default": "./dist/agents/databricks.js"
4343
},
44+
"./agents/supervisor-api": {
45+
"development": "./src/agents/supervisor-api.ts",
46+
"default": "./dist/agents/supervisor-api.js"
47+
},
4448
"./type-generator": {
4549
"types": "./dist/type-generator/index.d.ts",
4650
"development": "./src/type-generator/index.ts",
@@ -126,6 +130,7 @@
126130
"./agents/vercel-ai": "./dist/agents/vercel-ai.js",
127131
"./agents/langchain": "./dist/agents/langchain.js",
128132
"./agents/databricks": "./dist/agents/databricks.js",
133+
"./agents/supervisor-api": "./dist/agents/supervisor-api.js",
129134
"./dist/shared/src/plugin": "./dist/shared/src/plugin.d.ts",
130135
"./type-generator": "./dist/type-generator/index.js",
131136
"./package.json": "./package.json"

packages/appkit/src/agents/databricks.ts

Lines changed: 27 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
AgentToolDefinition,
77
} from "shared";
88
import { stream as servingStream } from "../connectors/serving/client";
9+
import { readSseEvents } from "../stream";
910

1011
/**
1112
* Transport shim: given an OpenAI-compatible request body, returns the raw
@@ -388,68 +389,47 @@ export class DatabricksAdapter implements AgentAdapter {
388389
}
389390

390391
const responseBody = await this.streamBody(body, context.signal);
391-
const reader = responseBody.getReader();
392392

393-
const decoder = new TextDecoder();
394-
let buffer = "";
395393
let fullText = "";
396394
const toolCallAccumulator = new Map<
397395
number,
398396
{ id: string; name: string; arguments: string }
399397
>();
400398

401-
try {
402-
while (true) {
403-
if (context.signal?.aborted) break;
399+
for await (const { data } of readSseEvents(responseBody, context.signal)) {
400+
if (data === "[DONE]") continue;
404401

405-
const { done, value } = await reader.read();
406-
if (done) break;
407-
408-
buffer += decoder.decode(value, { stream: true });
409-
const lines = buffer.split("\n");
410-
buffer = lines.pop() ?? "";
411-
412-
for (const line of lines) {
413-
const trimmed = line.trim();
414-
if (!trimmed.startsWith("data: ")) continue;
415-
const data = trimmed.slice(6);
416-
if (data === "[DONE]") continue;
417-
418-
let parsed: any;
419-
try {
420-
parsed = JSON.parse(data);
421-
} catch {
422-
continue;
423-
}
402+
let parsed: any;
403+
try {
404+
parsed = JSON.parse(data);
405+
} catch {
406+
continue;
407+
}
424408

425-
const delta = parsed.choices?.[0]?.delta;
426-
if (!delta) continue;
409+
const delta = parsed.choices?.[0]?.delta;
410+
if (!delta) continue;
427411

428-
if (delta.content) {
429-
fullText += delta.content;
430-
yield { type: "message_delta" as const, content: delta.content };
431-
}
412+
if (delta.content) {
413+
fullText += delta.content;
414+
yield { type: "message_delta" as const, content: delta.content };
415+
}
432416

433-
if (delta.tool_calls) {
434-
for (const tc of delta.tool_calls as DeltaToolCall[]) {
435-
const existing = toolCallAccumulator.get(tc.index);
436-
if (existing) {
437-
if (tc.function?.arguments) {
438-
existing.arguments += tc.function.arguments;
439-
}
440-
} else {
441-
toolCallAccumulator.set(tc.index, {
442-
id: tc.id ?? `call_${tc.index}`,
443-
name: tc.function?.name ?? "",
444-
arguments: tc.function?.arguments ?? "",
445-
});
446-
}
417+
if (delta.tool_calls) {
418+
for (const tc of delta.tool_calls as DeltaToolCall[]) {
419+
const existing = toolCallAccumulator.get(tc.index);
420+
if (existing) {
421+
if (tc.function?.arguments) {
422+
existing.arguments += tc.function.arguments;
447423
}
424+
} else {
425+
toolCallAccumulator.set(tc.index, {
426+
id: tc.id ?? `call_${tc.index}`,
427+
name: tc.function?.name ?? "",
428+
arguments: tc.function?.arguments ?? "",
429+
});
448430
}
449431
}
450432
}
451-
} finally {
452-
reader.releaseLock();
453433
}
454434

455435
const toolCalls: OpenAIToolCall[] = Array.from(

0 commit comments

Comments
 (0)