Skip to content
Closed
3 changes: 2 additions & 1 deletion apps/dev-playground/.env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ OTEL_RESOURCE_ATTRIBUTES='service.sample_attribute=dev'
OTEL_SERVICE_NAME='dev-playground'
DATABRICKS_VOLUME_PLAYGROUND=
DATABRICKS_VOLUME_OTHER=
DATABRICKS_GENIE_SPACE_ID=
DATABRICKS_GENIE_SPACE_ID='01f0b972bf391ccd8b60840332bb2e5b' # appkit NYC Taxi space
DATABRICKS_UC_FUNCTION_NAME='system.ai.python_exec'
DATABRICKS_JOB_ID=
DATABRICKS_SERVING_ENDPOINT_NAME=
LAKEBASE_ENDPOINT='' # Run: databricks postgres list-endpoints projects/{project-id}/branches/{branch-id} — use the `name` field from the output
Expand Down
70 changes: 52 additions & 18 deletions apps/dev-playground/client/src/routes/agent.route.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { getPluginClientConfig } from "@databricks/appkit-ui/js";
import { Button } from "@databricks/appkit-ui/react";
import {
Button,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@databricks/appkit-ui/react";
import { createFileRoute } from "@tanstack/react-router";
import { useCallback, useEffect, useRef, useState } from "react";

export const Route = createFileRoute("/agent")({
component: AgentRoute,
});

const AGENT_OPTIONS = [
{ value: "helper", label: "Helper — general assistant" },
{ value: "sql_analyst", label: "SQL Analyst — NYC taxi queries" },
{ value: "supervisor", label: "Supervisor — Databricks-hosted tools" },
] as const;

interface SSEEvent {
type: string;
delta?: string;
Expand Down Expand Up @@ -142,6 +155,7 @@ function AgentRoute() {
const [input, setInput] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [threadId, setThreadId] = useState<string | null>(null);
const [agent, setAgent] = useState<string>(AGENT_OPTIONS[0].value);
const [pendingApprovals, setPendingApprovals] = useState<PendingApproval[]>(
[],
);
Expand Down Expand Up @@ -211,6 +225,7 @@ function AgentRoute() {
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
message: userMessage,
agent,
...(threadId && { threadId }),
}),
});
Expand Down Expand Up @@ -310,7 +325,7 @@ function AgentRoute() {
} finally {
setIsLoading(false);
}
}, [input, isLoading, threadId, clearSuggestion]);
}, [input, isLoading, threadId, agent, clearSuggestion]);

const handleInputChange = (value: string) => {
setInput(value);
Expand All @@ -328,23 +343,42 @@ function AgentRoute() {
return (
<div className="min-h-screen bg-background">
<div className="max-w-7xl mx-auto px-6 py-12">
<div className="mb-8 flex items-end justify-between">
<div>
<h1 className="text-3xl font-bold mb-2">Agent Chat</h1>
<p className="text-base text-muted-foreground">
AI agent with auto-discovered tools from all AppKit plugins.
{threadId && (
<span className="ml-2 text-xs font-mono opacity-60">
Thread: {threadId.slice(0, 8)}...
</span>
)}
</p>
<div className="flex items-center gap-6 justify-between">
<div className="mb-8 flex-1 flex items-end justify-between">
<div>
<h1 className="text-3xl font-bold mb-2">Agent Chat</h1>
<p className="text-base text-muted-foreground">
AI agent with auto-discovered tools from all AppKit plugins.
{threadId && (
<span className="ml-2 text-xs font-mono opacity-60">
Thread: {threadId.slice(0, 8)}...
</span>
)}
</p>
</div>
{hasAutocomplete && (
<span className="text-xs text-muted-foreground bg-muted px-2 py-1 rounded">
Autocomplete enabled
</span>
)}
</div>
<div className="w-80 flex items-center gap-3">
<div className="flex flex-1 flex-col gap-1">
<span className="text-xs font-medium">Agent</span>
<Select value={agent} onValueChange={setAgent}>
<SelectTrigger className="w-80 h-8">
<SelectValue />
</SelectTrigger>
<SelectContent>
{AGENT_OPTIONS.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
{hasAutocomplete && (
<span className="text-xs text-muted-foreground bg-muted px-2 py-1 rounded">
Autocomplete enabled
</span>
)}
</div>

<div className="flex gap-6 h-[700px]">
Expand Down
39 changes: 37 additions & 2 deletions apps/dev-playground/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import {
serving,
WRITE_ACTIONS,
} from "@databricks/appkit";
import { agents, createAgent, tool } from "@databricks/appkit/beta";
import {
agents,
createAgent,
DatabricksAdapter,
supervisorTools,
tool,
} from "@databricks/appkit/beta";
import { WorkspaceClient } from "@databricks/sdk-experimental";
import { z } from "zod";
import { lakebaseExamples } from "./lakebase-examples-plugin";
Expand Down Expand Up @@ -68,6 +74,35 @@ const helper = createAgent({
},
});

// Supervisor API demo agent. The Databricks AI Gateway executes hosted
// tools server-side; declare them via `createAgent({ tools })` like any
// other agent tool — the agents plugin classifies the tagged record and
// routes it to the adapter via AgentInput.extensions. Import
// `supervisorTools` from '@databricks/appkit/beta' and uncomment an
// entry below to give the model real powers.
//
// `createAgent({ model })` accepts an adapter promise, so the factory's
// host/credential resolution is awaited lazily on first dispatch (via
// `resolveAdapter` in the agents plugin). A misconfigured workspace will
// surface at first chat request, not at module init.
const supervisor = createAgent({
instructions:
"You are an assistant powered by the Databricks Supervisor API.",
model: DatabricksAdapter.fromSupervisorApi({
model: "databricks-claude-sonnet-4-5",
}),
tools: () => ({
nyc: supervisorTools.genieSpace({
id: process.env.DATABRICKS_GENIE_SPACE_ID ?? "",
description: "NYC taxi trip records and zones",
}),
add: supervisorTools.ucFunction({
name: process.env.DATABRICKS_UC_FUNCTION_NAME ?? "",
description: "Adds two integers and returns the sum.",
}),
}),
});

/*
* Smart-Dashboard agents.
*
Expand Down Expand Up @@ -385,7 +420,7 @@ createApp({
}),
serving(),
agents({
agents: { helper, sql_analyst, dashboard_pilot },
agents: { helper, sql_analyst, dashboard_pilot, supervisor },
// `query` (markdown dispatcher) + `sql_analyst` + `dashboard_pilot`
// wire the /smart-dashboard route. `insights` and `anomaly` are
// ephemeral markdown agents auto-fired by the route's AgentSidebar.
Expand Down
39 changes: 39 additions & 0 deletions docs/docs/api/appkit/Class.DatabricksAdapter.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

141 changes: 141 additions & 0 deletions docs/docs/api/appkit/Class.SupervisorApiAdapter.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading