Skip to main content
Plugins add cross-cutting behavior and can contribute components. Typical uses: auth/session helpers, PII filtering, tracing, logging, caching, error policy, rate-limits.

Basic Plugin

A simple plugin uses the @Plugin decorator:

Using Plugins

Attach plugins at app scope:

Dynamic Plugin with Options

For plugins that need runtime configuration, extend DynamicPlugin:

Type-Safe Options with Zod

For complex options with defaults, use Zod schemas with two types:
my-plugin.types.ts
my-plugin.plugin.ts

Adding Hooks

Plugins can intercept flow stages using hooks. Use this.get(Token) to access providers:

Contributing Skills

Plugins can contribute skills that teach AI how to perform workflows using the plugin’s tools:
Plugin skills are automatically adopted into the app’s skill registry when the plugin is attached. They appear in searchSkills results alongside app-level skills and can be loaded with loadSkill.
Use plugin skills to bundle workflow knowledge with the tools they use. This creates self-contained, reusable functionality modules.

Available Hooks

ToolHook (tools:call-tool)

Intercept tool execution flow:

ListToolsHook (tools:list-tools)

Intercept tool listing flow:

Hook Timing

  • .Will(stage) - runs before the stage
  • .Did(stage) - runs after the stage

DynamicPlugin API

The init() method accepts your plugin’s input options type and returns a provider configuration that the framework uses internally. You don’t need to import or reference the return type—just pass the result directly to the plugins array.

Extending Tool Metadata

Plugins can extend the global tool metadata interface:
Tools can then use this metadata:

Plugin Scope

By default, plugins operate at the app scope - their hooks only fire for requests to that specific app. For cross-app functionality, you can use server scope.

App Scope (Default)

Hooks fire only for requests to the app where the plugin is registered:

Server Scope

Hooks fire at the gateway level for all apps in the server:
Server-scoped plugins can only be used in non-standalone apps (standalone: false). Using scope: 'server' in a standalone app will throw an InvalidPluginScopeError.

When to Use Each Scope

Accessing Other Apps (Server Scope)

Server-scoped plugins can access other apps via scope.apps:

Composition

Plugins compose depth-first at the app level. Later plugins can depend on providers exported by earlier ones.
Put organization-wide concerns (auth, audit, tracing) in plugins so all generated and inline components inherit the behavior without boilerplate.