Skip to main content
Runtime capabilities are the typed boundary between a plugin and services owned by the Xpert host. They let plugin code use workspace storage, knowledgebases, Artifacts, Sandbox Jobs, actor tokens, and project provisioning without importing host implementation classes or creating parallel infrastructure. All public types and capability keys on this page are exported from @xpert-ai/plugin-sdk.

Capability model

A capability key is a frozen object containing a stable ID, a description, and a TypeScript-only API type:
Use the exported key object instead of a raw string. The key carries the API type into get() and require(), while the stable ID lets the host and dynamically loaded plugins agree on the same contract. The registry exposes four operations:

Resolve a capability in Agent middleware

Agent middleware receives the scoped registry on context.runtime.capabilities:
Use get() when the feature can be hidden or degraded. Use require() only after the plugin has established that the capability is mandatory for the current operation:
The registry is scoped by the host. Capability methods still enforce tenant, organization, user, workspace, project, and Xpert boundaries; a caller-supplied identifier does not bypass those boundaries.

Resolve a capability in a NestJS provider

A NestJS provider is not inherently bound to one Agent execution, so first distinguish whether a capability depends on the current runtime scope: Data-owning capabilities such as WorkspaceFilesRuntimeCapability must be resolved from the scoped runtime API first. An unbound global registry may intentionally omit Workspace Files when no xpertId or projectId is bound. A plugin must not work around that boundary by asking the host to restore unscoped file access. The following example creates a scoped API for each export operation. The global registry is only a compatibility fallback for older hosts; omit that fallback in a new plugin that does not support those hosts:
The tenantId, organizationId, userId, xpertId, projectId, conversationId, catalog, and scopeId passed to createScopedApi() must come from host-resolved server context, never from untrusted iframe, form, or action-input identifiers. Create the scoped API and resolve the capability close to each operation so availability is reported accurately. Do not cache user- or execution-scoped APIs or capability instances across requests.

Capabilities in the runtime package

Continue with the detailed references:

Define and test capability consumers

createRuntimeCapability<T>() creates a typed key for a host or plugin subsystem. Do not reuse a platform.* ID for a different contract. RuntimeCapabilityResolver is the read-only get() view to use when a consumer must not register implementations.
For unit tests, register a typed fake in DefaultRuntimeCapabilityRegistry:
Production plugin code normally consumes platform keys; host infrastructure owns their registration. Test both the available path and the unavailable path when a capability is optional.

Compatibility rules

  • Import keys and API types from @xpert-ai/plugin-sdk; do not copy the interfaces into a plugin.
  • A NestJS provider that consumes a scope-sensitive capability must use XPERT_AGENT_MIDDLEWARE_RUNTIME_TOKEN.createScopedApi(); do not use an unbound global registry as its primary source.
  • Treat capability availability as a runtime condition. Package installation alone does not prove that a host service, provider, binding, or registered Sandbox Action is ready.
  • Keep portable references and structured DTOs at async boundaries. Do not pass raw file bytes, bearer tokens, host paths, or implementation instances through queues or persisted chat metadata.
  • Keep capability results within the current authorized scope and re-resolve them for later jobs or callbacks.