Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions apps/agent-app/config/agents/assistant.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
---

## default: true
endpoint: databricks-claude-sonnet-4-5
default: true
---

You are a helpful data assistant running on Databricks.

Use the available tools to query data, browse files, and help users with their analysis.

When using analytics.query, write Databricks SQL. When results are large, summarize the key findings rather than dumping raw data.
When using `analytics.query`, write Databricks SQL. When results are large, summarize the key findings rather than dumping raw data.

You also have access to additional tools from MCP servers — use them when relevant.
You also have access to additional tools from MCP servers — use them when relevant.
75 changes: 53 additions & 22 deletions apps/agent-app/server.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,72 @@
import {
agents,
analytics,
createAgent,
createApp,
files,
mcpServer,
server,
tool,
} from "@databricks/appkit";
import { z } from "zod";

const port = Number(process.env.DATABRICKS_APP_PORT) || 8003;

createAgent({
plugins: [analytics(), files()],
tools: [
tool({
name: "get_weather",
description: "Get the current weather for a city",
schema: z.object({
city: z.string().describe("City name"),
}),
execute: async ({ city }) => `The weather in ${city} is sunny, 22°C`,
}),
mcpServer(
"mario-mcp-hello",
"https://mario-mcp-hello-6051921418418893.staging.aws.databricksapps.com/mcp",
),
mcpServer(
// Shared tool available to any agent that declares `tools: [get_weather]` in
// its markdown frontmatter.
const get_weather = tool({
name: "get_weather",
description: "Get the current weather for a city",
schema: z.object({
city: z.string().describe("City name"),
}),
execute: async ({ city }) => `The weather in ${city} is sunny, 22°C`,
});

// Code-defined agent. Overrides config/agents/support.md if a file with that
// name exists. Tools here are explicit; defaults are strict (no auto-inherit
// for code-defined agents).
const support = createAgent({
instructions:
"You help customers with data analysis, file browsing, and general questions. " +
"Use the available tools as needed and summarize results concisely.",
tools: {
get_weather,
"mcp.vector-search": mcpServer(
"vector-search",
"https://e2-dogfood.staging.cloud.databricks.com/api/2.0/mcp/vector-search/main/default",
),
mcpServer(
"mcp.uc-greet": mcpServer(
"uc-greet",
"https://e2-dogfood.staging.cloud.databricks.com/api/2.0/mcp/functions/main/mario/greet",
),
"mcp.mario-hello": mcpServer(
"mario-mcp-hello",
"https://mario-mcp-hello-6051921418418893.staging.aws.databricksapps.com/mcp",
),
},
});

const appkit = await createApp({
plugins: [
server({ port }),
analytics(),
files(),
agents({
// Ambient tool library referenced by markdown frontmatter `tools: [...]`.
tools: { get_weather },
// Code-defined agents are merged with markdown agents; code wins on key
// collision. Markdown agents still auto-inherit analytics+files tools
// unless their frontmatter says otherwise.
agents: { support },
}),
],
port,
}).then((agent) => {
console.log(
`Agent running on port ${port} with ${agent.getTools().length} tools`,
);
});

const registry = appkit.agent as {
list: () => string[];
getDefault: () => string | null;
};
console.log(
`Agent app running on port ${port}. Agents: ${registry.list().join(", ")}. Default: ${registry.getDefault() ?? "(none)"}.`,
);
4 changes: 3 additions & 1 deletion apps/dev-playground/config/agents/assistant.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---

## default: true
## endpoint: databricks-claude-sonnet-4-5

default: true

You are a helpful data assistant. Use the available tools to query data and help users with their analysis.
6 changes: 3 additions & 3 deletions apps/dev-playground/config/agents/autocomplete.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---

## endpoint: databricks-gemini-3-1-flash-lite
endpoint: databricks-gemini-3-1-flash-lite
maxSteps: 1
---

You are an autocomplete engine. The user will give you the beginning of a sentence or paragraph. Continue the text naturally, as if you are the same author. Do NOT repeat the input. Only output the continuation. Do NOT use tools. Do NOT explain. Just write the next words.
You are an autocomplete engine. The user will give you the beginning of a sentence or paragraph. Continue the text naturally, as if you are the same author. Do NOT repeat the input. Only output the continuation. Do NOT use tools. Do NOT explain. Just write the next words.
4 changes: 2 additions & 2 deletions apps/dev-playground/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "reflect-metadata";
import {
agent,
agents,
analytics,
createApp,
files,
Expand Down Expand Up @@ -33,7 +33,7 @@ createApp({
}),
lakebaseExamples(),
files(),
agent(),
agents(),
],
...(process.env.APPKIT_E2E_TEST && { client: createMockClient() }),
}).then((appkit) => {
Expand Down
173 changes: 173 additions & 0 deletions docs/docs/guides/migrating-to-agents-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Migrating to the `agents()` plugin

The old `createAgent({ adapter, port, tools, plugins })` shortcut from the agent PR stack is deprecated. The new shape splits agent *definition* (pure data) from app *composition* (plugin registration).

The old exports still work — they're kept side-by-side until a future removal release. This guide shows how to port code incrementally.

## Name changes at a glance

| Old | New |
|---|---|
| `createAgent(config)` (app shortcut) | `createAgentApp(config)` (deprecated) |
| — | `createAgent(def)` (pure factory, **same name, new meaning**) |
| `agent()` plugin | `agents()` plugin (plural) |
| `tools: AgentTool[]` | `tools: Record<string, AgentTool>` |
| Auto-inherit all plugin tools | Asymmetric: markdown yes, code no |

## Before: old shortcut

```ts
import {
analytics,
createAgent,
files,
mcpServer,
tool,
} from "@databricks/appkit";
import { z } from "zod";

createAgent({
plugins: [analytics(), files()],
tools: [
tool({
name: "get_weather",
description: "Weather",
schema: z.object({ city: z.string() }),
execute: async ({ city }) => `Sunny in ${city}`,
}),
mcpServer("vector-search", "https://…/mcp/vector-search"),
],
port: 8000,
}).then((agent) => {
console.log(`Running with ${agent.getTools().length} tools`);
});
```

## After: createApp + agents()

```ts
import {
agents,
analytics,
createApp,
files,
mcpServer,
server,
tool,
} from "@databricks/appkit";
import { z } from "zod";

const get_weather = tool({
name: "get_weather",
description: "Weather",
schema: z.object({ city: z.string() }),
execute: async ({ city }) => `Sunny in ${city}`,
});

await createApp({
plugins: [
server({ port: 8000 }),
analytics(),
files(),
agents({
tools: {
get_weather,
"mcp.vector-search": mcpServer(
"vector-search",
"https://…/mcp/vector-search",
),
},
}),
],
});
```

Key differences:

- `plugins` moves to the top level of `createApp`; `agents()` goes into the plugin list.
- `server()` is explicit — required when you want HTTP.
- `tools` is a record on `agents({ tools })`, keyed by the tool-call name the LLM will see. Spread into agent definitions via markdown `tools: [get_weather]` or inline in `createAgent({ tools: { get_weather } })`.
- `port` moves to `server({ port })`.

## Frontmatter migration

The old parser was a flat key=value regex. The new parser is real YAML (`js-yaml`). Two things to watch for:

1. **Remove `##` markers**: `## default: true` was a Markdown heading that the old parser tolerated. YAML requires `default: true`.
2. **Validate structure**: previously typos were silently dropped; the new parser logs warnings for unknown keys and throws on truly invalid YAML.

Old:

```md
---
## default: true
## endpoint: databricks-claude-sonnet-4-5
---

You are helpful.
```

New:

```md
---
default: true
endpoint: databricks-claude-sonnet-4-5
---

You are helpful.
```

## Scoping tools in markdown

The new schema lets you declare tool scope right in the markdown file:

```md
---
endpoint: databricks-claude-sonnet-4-5
toolkits:
- analytics
- files: [uploads.read, uploads.list]
tools: [get_weather]
---

You are a read-only data assistant.
```

Engineers declare tools in code; prompt authors pick from a menu in frontmatter. No YAML-as-code ceremony required.

## Standalone runs

The old `createAgent` returned a running HTTP app. Sometimes you want to run an agent in a script, cron, or test without HTTP. Use `runAgent`:

```ts
import { createAgent, runAgent, tool } from "@databricks/appkit";

const classifier = createAgent({
instructions: "Classify tickets.",
model: "databricks-claude-sonnet-4-5",
tools: { /* inline tools only */ },
});

const result = await runAgent(classifier, { messages: "Billing issue please help" });
console.log(result.text);
```

Plugin toolkits (`ToolkitEntry` from `.toolkit()`) require `createApp`; `runAgent` throws a clear error if invoked with one.

## Gradual migration

Both APIs coexist. You can land the dependency bump today, keep using `createAgentApp` (the renamed old shortcut), and migrate call sites one at a time:

```ts
import { createAgentApp, analytics, tool } from "@databricks/appkit";

// Old shape still works, just renamed:
createAgentApp({ plugins: [analytics()], tools: [/* ... */] });
```

When you're ready, switch the import to `createApp({ plugins: [..., agents()] })` and remove the `createAgentApp` call. No other code needs to change.

## Removal timeline

The old `agent()` and `createAgentApp` exports remain until feedback on the new shape stabilizes. A follow-up PR will remove them in a future release; use of the deprecated exports surfaces via IDE strikethrough (JSDoc `@deprecated`) but does not log runtime warnings.
Loading