Skip to content

Class: WebSearchPlugin

AppKit plugin that resolves and holds the web-search runtime config used by the web_search / web_fetch tools.

import { createApp, server } from "@databricks/appkit";
import { webSearch } from "@dbx-tools/appkit-web-search";
await createApp({
plugins: [
server(),
webSearch({
model: "gemini",
urlPolicy: "allowlist",
allowedUrls: ["*.databricks.com"],
}),
],
});

new WebSearchPlugin(config): WebSearchPlugin

WebSearchPluginConfig

WebSearchPlugin

ToolRegistryPlugin<WebSearchPluginConfig>.constructor

protected app: AppManager

ToolRegistryPlugin.app


protected cache: CacheManager

ToolRegistryPlugin.cache


protected config: WebSearchPluginConfig

ToolRegistryPlugin.config


protected optional context?: PluginContext

ToolRegistryPlugin.context


protected devFileReader: DevFileReader

ToolRegistryPlugin.devFileReader


protected isReady: boolean

ToolRegistryPlugin.isReady


name: string

Plugin name identifier.

ToolRegistryPlugin.name


protected streamManager: StreamManager

ToolRegistryPlugin.streamManager


protected telemetry: ITelemetry

ToolRegistryPlugin.telemetry


protected readonly toolRegistry: ToolRegistry

The tools this plugin offers to an AppKit agent. Both are reads and both run under the caller’s identity.

Neither is autoInheritable. web_fetch reaches a URL the model chose, which is reachable from inside the workspace network, so it must only appear in an agent that asked for it and accepted the URL policy that comes with it. web_search is safer but still spends serving tokens on every call, so it is opt-in for cost rather than for safety.

execute re-parses its arguments with the local schema: AppKit validates against the same schema first, but re-parsing is what gives the body typed arguments instead of unknown.

ToolRegistryPlugin.toolRegistry


static manifest: object

config: object

schema: JSONSchema7 = WEB_SEARCH_CONFIG_SCHEMA

description: string

displayName: string = "Web Search"

name: "web-search" = "web-search"

resources: object

optional: object[]

required: never[] = []

stability: "beta" = "beta"


static phase: PluginPhase

Plugin initialization phase.

  • ‘core’: Initialized first (e.g., config plugins)
  • ‘normal’: Initialized second (most plugins)
  • ‘deferred’: Initialized last (e.g., server plugin)

ToolRegistryPlugin.phase

abortActiveOperations(): void

Abort in-flight work owned by this plugin instance.

void

ToolRegistryPlugin.abortActiveOperations


asUser(req): this

Execute operations using the user’s identity from the request. Returns a proxy of this plugin where all method calls execute with the user’s Databricks credentials instead of the service principal.

Request

The Express request containing the user token in headers

this

A proxied plugin instance that executes as the user

AuthenticationError if user token is not available in request headers (production only). In development mode (NODE_ENV=development), skips user impersonation instead of throwing.

ToolRegistryPlugin.asUser


attachContext(deps?): void

Binds runtime dependencies (telemetry provider, cache, plugin context) to this plugin. Called by AppKit._createApp after construction and before setup(). Idempotent: safe to call if the constructor already bound them eagerly. Kept separate so factories can eagerly construct plugin instances without running this before TelemetryManager.initialize() / CacheManager.getInstance() have run.

unknown

TelemetryOptions

void

ToolRegistryPlugin.attachContext


clientConfig(): Record<string, unknown>

Returns startup config to expose to the client. Override this to surface server-side values that are safe to publish to the frontend, such as feature flags, resource IDs, or other app boot settings.

This runs once when the server starts, so it should not depend on request-scoped or user-specific state.

String values that match non-public environment variables are redacted unless you intentionally expose them via a matching PUBLIC_APPKIT_ env var.

Values must be JSON-serializable plain data (no functions, Dates, classes, Maps, Sets, BigInts, or circular references). By default returns an empty object (plugin contributes nothing to client config).

On the client, read the config with the usePluginClientConfig hook (React) or the getPluginClientConfig function (vanilla JS), both from @databricks/appkit-ui.

Record<string, unknown>

// Server — plugin definition
class MyPlugin extends Plugin<MyConfig> {
clientConfig() {
return {
warehouseId: this.config.warehouseId,
features: { darkMode: true },
};
}
}
// Client — React component
import { usePluginClientConfig } from "@databricks/appkit-ui/react";
interface MyPluginConfig { warehouseId: string; features: { darkMode: boolean } }
const config = usePluginClientConfig<MyPluginConfig>("myPlugin");
config.warehouseId; // "abc-123"
// Client — vanilla JS
import { getPluginClientConfig } from "@databricks/appkit-ui/js";
const config = getPluginClientConfig<MyPluginConfig>("myPlugin");

ToolRegistryPlugin.clientConfig


protected execute<T>(fn, options, userKey?): Promise<ExecutionResult<T>>

Execute a function with the plugin’s interceptor chain.

Returns an ExecutionResult discriminated union:

  • { ok: true, data: T } on success
  • { ok: false, status: number, message: string } on failure

Errors are never thrown — the method is production-safe.

T

(signal?) => Promise<T>

PluginExecutionSettings

string

Promise<ExecutionResult<T>>

ToolRegistryPlugin.execute


executeAgentTool(name, args, signal?, context?): Promise<unknown>

Dispatch with the actual calling model and optional host progress sink.

string

unknown

AbortSignal

AgentToolExecutionContext

Promise<unknown>

ToolRegistryPlugin.executeAgentTool


protected executeStream<T>(res, fn, options, userKey?): Promise<void>

T

IAppResponse

StreamExecuteHandler<T>

StreamExecutionSettings

string

Promise<void>

ToolRegistryPlugin.executeStream


exports(): object

Returns the public exports for this plugin. Override this to define a custom public API. By default, returns an empty object.

The returned object becomes the plugin’s public API on the AppKit instance (e.g. appkit.myPlugin.method()). AppKit automatically binds method context and adds asUser(req) for user-scoped execution.

fetch: (request, signal?) => Promise<{ content: string; contentType?: string; status: number; title?: string; truncated: boolean; url: string; }>

Fetch one URL directly (bypassing the agent tool). Enforces the configured URL policy.

"text" | "html" = ...

number = ...

string = ...

AbortSignal

Promise<{ content: string; contentType?: string; status: number; title?: string; truncated: boolean; url: string; }>

search: (request, signal?) => Promise<{ answer: string; citations: object[]; model: string; query: string; }>

Run a web search directly (bypassing the agent tool). Resolves the OBO client from the active execution context and reads this plugin’s runtime config.

string = ...

string = ...

AbortSignal

Promise<{ answer: string; citations: object[]; model: string; query: string; }>

class MyPlugin extends Plugin {
private getData() { return []; }
exports() {
return { getData: this.getData };
}
}
// After registration:
const appkit = await createApp({ plugins: [myPlugin()] });
appkit.myPlugin.getData();

ToolRegistryPlugin.exports


getAgentTools(): AgentToolDefinition[]

Tool definitions offered to an AppKit agent.

AgentToolDefinition[]

ToolRegistryPlugin.getAgentTools


getEndpoints(): PluginEndpointMap

PluginEndpointMap

ToolRegistryPlugin.getEndpoints


getSkipBodyParsingPaths(): ReadonlySet<string>

ReadonlySet<string>

ToolRegistryPlugin.getSkipBodyParsingPaths


injectRoutes(_): void

Router

void

ToolRegistryPlugin.injectRoutes


protected registerEndpoint(name, path): void

string

string

void

ToolRegistryPlugin.registerEndpoint


protected resolveUserId(req): string

Resolve the effective user ID from a request.

Returns the x-forwarded-user header when present. In development mode (NODE_ENV=development) falls back to the current context user ID so that callers outside an active runInUserContext scope still get a consistent value.

Request

string

AuthenticationError in production when no user header is present.

ToolRegistryPlugin.resolveUserId


protected route<_TResponse>(router, config): void

_TResponse

Router

RouteConfig

void

ToolRegistryPlugin.route


setup(): Promise<void>

Log the effective policy so an active allow-list and caps are obvious at boot. Runtime construction already resolved config and captured this plugin’s interceptor chain.

Promise<void>

ToolRegistryPlugin.setup


shutdown(): void

No runtime resources require draining. The instance-owned config and executor become unreachable with this plugin.

void


static getResourceRequirements(config): ResourceRequirement[]

Promote the serving endpoint to a required resource once a deployment pins one, through plugin config or either environment name. Left optional otherwise, because the plugin picks a web-search-capable endpoint out of the live catalogue on its own.

WebSearchPluginConfig

ResourceRequirement[]