Class: MastraPlugin
AppKit plugin (registered name: mastra) that hosts Mastra agents
with optional Lakebase-backed memory and AI SDK chat routes under
the plugin mount (typically /api/mastra).
Examples
Section titled “Examples”Register the plugin
import { createApp, lakebase } from "@databricks/appkit";import { createAgent, mastra } from "@dbx-tools/appkit-mastra";
// `lakebase` first: registering it auto-enables Mastra storage + memory.const app = await createApp({ plugins: [ lakebase(), mastra({ genieSpaces: { default: process.env.DATABRICKS_GENIE_SPACE_ID! }, agents: createAgent({ name: "analyst", instructions: "You answer questions about revenue and returns.", tools(plugins) { return { ...plugins.genie?.toolkit() }; }, }), }), ],});Read the agents back off the AppKit instance
const agentIds = app.mastra.list();const endpoints = await app.mastra.listModels();Extends
Section titled “Extends”Plugin<MastraPluginConfig>
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new MastraPlugin(
config):MastraPlugin
Parameters
Section titled “Parameters”config
Section titled “config”Returns
Section titled “Returns”MastraPlugin
Inherited from
Section titled “Inherited from”Plugin<MastraPluginConfig>.constructor
Properties
Section titled “Properties”
protectedapp:AppManager
Inherited from
Section titled “Inherited from”Plugin.app
protectedcache:CacheManager
Inherited from
Section titled “Inherited from”Plugin.cache
config
Section titled “config”
protectedconfig:MastraPluginConfig
Inherited from
Section titled “Inherited from”Plugin.config
context?
Section titled “context?”
protectedoptionalcontext?:PluginContext
Inherited from
Section titled “Inherited from”Plugin.context
devFileReader
Section titled “devFileReader”
protecteddevFileReader:DevFileReader
Inherited from
Section titled “Inherited from”Plugin.devFileReader
isReady
Section titled “isReady”
protectedisReady:boolean
Inherited from
Section titled “Inherited from”Plugin.isReady
name:
string
Plugin name identifier.
Inherited from
Section titled “Inherited from”Plugin.name
streamManager
Section titled “streamManager”
protectedstreamManager:StreamManager
Inherited from
Section titled “Inherited from”Plugin.streamManager
telemetry
Section titled “telemetry”
protectedtelemetry:ITelemetry
Inherited from
Section titled “Inherited from”Plugin.telemetry
manifest
Section titled “manifest”
staticmanifest:PluginManifest<"mastra">
staticphase:PluginPhase
Plugin initialization phase.
- ‘core’: Initialized first (e.g., config plugins)
- ‘normal’: Initialized second (most plugins)
- ‘deferred’: Initialized last (e.g., server plugin)
Inherited from
Section titled “Inherited from”Plugin.phase
Methods
Section titled “Methods”abortActiveOperations()
Section titled “abortActiveOperations()”abortActiveOperations():
void
Abort in-flight work. AppKit’s graceful shutdown calls this hook
synchronously and never awaits shutdown, so the pool drain is
started here too; it cannot be awaited from a void hook, and
shutdown is idempotent so the duplicate call is free.
Returns
Section titled “Returns”void
Overrides
Section titled “Overrides”Plugin.abortActiveOperations
asUser()
Section titled “asUser()”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.
Parameters
Section titled “Parameters”Request
The Express request containing the user token in headers
Returns
Section titled “Returns”this
A proxied plugin instance that executes as the user
Throws
Section titled “Throws”AuthenticationError if user token is not available in request headers (production only).
In development mode (NODE_ENV=development), skips user impersonation instead of throwing.
Inherited from
Section titled “Inherited from”Plugin.asUser
attachContext()
Section titled “attachContext()”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.
Parameters
Section titled “Parameters”context?
Section titled “context?”unknown
telemetryConfig?
Section titled “telemetryConfig?”TelemetryOptions
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”Plugin.attachContext
clientConfig()
Section titled “clientConfig()”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.
Returns
Section titled “Returns”Record<string, unknown>
Example
Section titled “Example”// Server — plugin definitionclass MyPlugin extends Plugin<MyConfig> { clientConfig() { return { warehouseId: this.config.warehouseId, features: { darkMode: true }, }; }}
// Client — React componentimport { usePluginClientConfig } from "@databricks/appkit-ui/react";
interface MyPluginConfig { warehouseId: string; features: { darkMode: boolean } }
const config = usePluginClientConfig<MyPluginConfig>("myPlugin");config.warehouseId; // "abc-123"
// Client — vanilla JSimport { getPluginClientConfig } from "@databricks/appkit-ui/js";
const config = getPluginClientConfig<MyPluginConfig>("myPlugin");Overrides
Section titled “Overrides”Plugin.clientConfig
execute()
Section titled “execute()”
protectedexecute<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.
Type Parameters
Section titled “Type Parameters”T
Parameters
Section titled “Parameters”(signal?) => Promise<T>
options
Section titled “options”PluginExecutionSettings
userKey?
Section titled “userKey?”string
Returns
Section titled “Returns”Promise<ExecutionResult<T>>
Inherited from
Section titled “Inherited from”Plugin.execute
executeStream()
Section titled “executeStream()”
protectedexecuteStream<T>(res,fn,options,userKey?):Promise<void>
Type Parameters
Section titled “Type Parameters”T
Parameters
Section titled “Parameters”IAppResponse
StreamExecuteHandler<T>
options
Section titled “options”StreamExecutionSettings
userKey?
Section titled “userKey?”string
Returns
Section titled “Returns”Promise<void>
Inherited from
Section titled “Inherited from”Plugin.executeStream
exports()
Section titled “exports()”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.
Returns
Section titled “Returns”clearModelsCache
Section titled “clearModelsCache”clearModelsCache: (
host?) =>Promise<void>
Force-evict cached endpoint listings via AppKit’s
CacheManager. Useful in tests or right after an admin
deploys a new endpoint and doesn’t want to wait for the TTL.
Returns the underlying CacheManager.delete/clear promise.
Parameters
Section titled “Parameters”string
Returns
Section titled “Returns”Promise<void>
createRequestContext
Section titled “createRequestContext”createRequestContext: (
options) =>Promise<RequestContext<unknown>>
Build the RequestContext an agent turn driven from OUTSIDE this
plugin’s routes needs (a Teams activity on another plugin’s endpoint, a
scheduled job).
Mastra’s user-scoped tools - ask_genie most visibly - read the AppKit
user off the request context, which only the HTTP middleware stamps.
Calling agent.generate with a raw prompt therefore answers “the data
source is unreachable” where the chat routes answer with real data.
Passing this as requestContext closes that gap, so an out-of-band turn
has exactly the capabilities a chat turn has.
Must be called INSIDE an asUser(req) scope to inherit the caller’s
OBO identity; outside one it resolves to the service principal.
Parameters
Section titled “Parameters”options?
Section titled “options?”requestId?
Section titled “requestId?”string
resourceId?
Section titled “resourceId?”string
threadId?
Section titled “threadId?”string
Returns
Section titled “Returns”Promise<RequestContext<unknown>>
get: (
id) =>Agent<string,ToolsInput,undefined,unknown,AgentEditorConfig|undefined> |null
Look up a registered agent by id. Returns null (not
undefined) when unknown so call sites can early-return without
a separate in check.
Parameters
Section titled “Parameters”string
Returns
Section titled “Returns”Agent<string, ToolsInput, undefined, unknown, AgentEditorConfig | undefined> | null
getDefault
Section titled “getDefault”getDefault: () =>
Agent<string,ToolsInput,undefined,unknown,AgentEditorConfig|undefined> |null
The agent the client converses with when it doesn’t name one.
Resolves to config.defaultAgent, the first registered id, or
the built-in default fallback.
Returns
Section titled “Returns”Agent<string, ToolsInput, undefined, unknown, AgentEditorConfig | undefined> | null
getMastra
Section titled “getMastra”getMastra: () =>
Mastra<Record<string,Agent<any,ToolsInput,undefined,unknown,AgentEditorConfig|undefined>>,Record<string,AnyWorkflow>,Record<string,MastraVector<any>>,Record<string,MastraTTS>,IMastraLogger,Record<string,MCPServerBase<any>>,Record<string,MastraScorer<any,any,any,any>>,Record<string,ToolAction<any,any,any,any,any,any,unknown>>,Record<string,Processor<any,unknown>>,Record<string,MastraMemory>,Record<string,ChannelProvider>> |null
Underlying Mastra instance for advanced use (custom routes etc.).
Returns
Section titled “Returns”Mastra<Record<string, Agent<any, ToolsInput, undefined, unknown, AgentEditorConfig | undefined>>, Record<string, AnyWorkflow>, Record<string, MastraVector<any>>, Record<string, MastraTTS>, IMastraLogger, Record<string, MCPServerBase<any>>, Record<string, MastraScorer<any, any, any, any>>, Record<string, ToolAction<any, any, any, any, any, any, unknown>>, Record<string, Processor<any, unknown>>, Record<string, MastraMemory>, Record<string, ChannelProvider>> | null
getMastraServer
Section titled “getMastraServer”getMastraServer: () =>
MastraServer|null
Express subapp Mastra is mounted on; mostly for tests.
Returns
Section titled “Returns”MastraServer | null
getMcp
Section titled “getMcp”getMcp: () => {
http:string;httpPath:string;messagePath:string;messages:string;serverId:string;sse:string;ssePath:string; } |null
MCP endpoint info when config.mcp is enabled, else null.
Streamable HTTP is http; the SSE pair is the legacy transport.
Each path is given twice: mount-relative (httpPath, ssePath,
messagePath) for anything that already knows where the plugin is
mounted, and absolute (http, sse, messages) for MCP clients,
which take a single URL and cannot compose one. The absolute form is
built from basePath, so it honors a config.name override but
still assumes AppKit’s default /api/<name> mount.
Returns
Section titled “Returns”{ http: string; httpPath: string; messagePath: string; messages: string; serverId: string; sse: string; ssePath: string; } | null
list: () =>
string[]
Ids of every registered agent in registration order. Matches
AppKit agents.list() so callers can iterate the registry the
same way under both plugins.
Returns
Section titled “Returns”string[]
listModels
Section titled “listModels”listModels: () =>
Promise<object[]>
Fetch the workspace’s Model Serving endpoints (cached). Same
payload the GET /models route returns; surfaced here so
other plugins / scripts can introspect the catalogue without
an HTTP round-trip. AppKit wraps this with asUser(req) for
OBO scoping automatically. Throws when the listing fails, since
there is no status code to hand back on this surface.
Returns
Section titled “Returns”Promise<object[]>
Example
Section titled “Example”class MyPlugin extends Plugin { private getData() { return []; }
exports() { return { getData: this.getData }; }}
// After registration:const appkit = await createApp({ plugins: [myPlugin()] });appkit.myPlugin.getData();Overrides
Section titled “Overrides”Plugin.exports
getEndpoints()
Section titled “getEndpoints()”getEndpoints():
PluginEndpointMap
Returns
Section titled “Returns”PluginEndpointMap
Inherited from
Section titled “Inherited from”Plugin.getEndpoints
getSkipBodyParsingPaths()
Section titled “getSkipBodyParsingPaths()”getSkipBodyParsingPaths():
ReadonlySet<string>
Returns
Section titled “Returns”ReadonlySet<string>
Inherited from
Section titled “Inherited from”Plugin.getSkipBodyParsingPaths
injectRoutes()
Section titled “injectRoutes()”injectRoutes(
router):void
Parameters
Section titled “Parameters”router
Section titled “router”Router
Returns
Section titled “Returns”void
Overrides
Section titled “Overrides”Plugin.injectRoutes
registerEndpoint()
Section titled “registerEndpoint()”
protectedregisterEndpoint(name,path):void
Parameters
Section titled “Parameters”string
string
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”Plugin.registerEndpoint
resolveUserId()
Section titled “resolveUserId()”
protectedresolveUserId(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.
Parameters
Section titled “Parameters”Request
Returns
Section titled “Returns”string
Throws
Section titled “Throws”AuthenticationError in production when no user header is present.
Inherited from
Section titled “Inherited from”Plugin.resolveUserId
route()
Section titled “route()”
protectedroute<_TResponse>(router,config):void
Type Parameters
Section titled “Type Parameters”_TResponse
Section titled “_TResponse”_TResponse
Parameters
Section titled “Parameters”router
Section titled “router”Router
config
Section titled “config”RouteConfig
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”Plugin.route
setup()
Section titled “setup()”setup():
Promise<void>
Returns
Section titled “Returns”Promise<void>
Overrides
Section titled “Overrides”Plugin.setup
shutdown()
Section titled “shutdown()”shutdown():
Promise<void>
Drain the memory service-principal pool. Idempotent: the handle is
cleared before the drain starts, so a second call is a no-op and a
later setup() rebuilds the pool. Bounded by
POOL_DRAIN_TIMEOUT_MS to stay well inside the 15s graceful
shutdown budget.
Returns
Section titled “Returns”Promise<void>
getResourceRequirements()
Section titled “getResourceRequirements()”
staticgetResourceRequirements(config):ResourceRequirement[]
Tighten resource requirements based on which features are enabled. AppKit calls this at registration time (config-aware) so disabled features don’t surface their resource asks to the host app.
Parameters
Section titled “Parameters”config
Section titled “config”Returns
Section titled “Returns”ResourceRequirement[]