docs/PLUGIN_DEVELOPMENT.md
In elizaOS, a plugin is a plain object implementing the Plugin interface (packages/typescript/src/types/plugin.ts). Plugins extend the runtime by registering:
@elizaos/plugin-sql)import type { Plugin } from "@elizaos/core";
export const myPlugin: Plugin = {
name: "my-plugin",
description: "Example plugin showing the main extension points.",
};
Register it by passing it to new AgentRuntime({ plugins: [...] }) and calling runtime.initialize(). See examples/chat/typescript/chat.ts for a minimal "runtime + plugins" setup.
Actions are registered via plugin.actions and are executed by runtime.processActions(...) after the model returns an action plan.
Key types:
Action: packages/typescript/src/types/components.ts(runtime, message, state, options, callback, responses) => Promise<ActionResult | undefined>Example:
import type { Action, Plugin } from "@elizaos/core";
const pingAction: Action = {
name: "PING",
description: "Respond with pong.",
validate: async () => true,
handler: async (_runtime, _message, _state, _options, callback) => {
await callback?.({ text: "pong", actions: ["REPLY"], simple: true });
return { success: true, text: "pong" };
},
};
export const myPlugin: Plugin = {
name: "my-plugin",
description: "Adds a PING action.",
actions: [pingAction],
};
Actions can declare parameters (JSON-schema-like) to have the LLM extract validated values into options.parameters.
See: ActionParameter, HandlerOptions in packages/typescript/src/types/components.ts.
Providers contribute to State via runtime.composeState(...) (packages/typescript/src/runtime.ts).
Provider characteristics:
position: ordering in the prompt/state aggregation (lower runs earlier)private: excluded from the default provider set; must be explicitly includeddynamic: excluded from the default provider set; must be explicitly includedExample provider:
import type { Plugin, Provider } from "@elizaos/core";
const currentTimeProvider: Provider = {
name: "CURRENT_TIME",
position: 10,
get: async () => ({
text: `Current time: ${new Date().toISOString()}`,
values: { nowIso: new Date().toISOString() },
}),
};
export const myPlugin: Plugin = {
name: "my-plugin",
description: "Adds a time provider.",
providers: [currentTimeProvider],
};
Services are long-lived objects (connections, caches, API clients). Plugins register service classes through plugin.services.
At registration time (AgentRuntime.registerPlugin()), services are registered asynchronously and can be retrieved via runtime.getService("serviceType") (see packages/typescript/src/runtime.ts).
Plugins can register model handlers through plugin.models. The runtime selects the highest priority handler for a given model type.
This is how LLM providers (OpenAI, Anthropic, etc.) integrate: they implement a handler for ModelType.TEXT_LARGE, ModelType.TEXT_SMALL, etc.
Relevant types:
ModelParamsMap / ModelTypeName: packages/typescript/src/types/model.tsIAgentRuntime.useModel(...) overloads in packages/typescript/src/types/runtime.tsPlugins can add HTTP routes via plugin.routes. When registered, the runtime namespaces the path under /${plugin.name} (see AgentRuntime.registerPlugin()).
Example:
import type { Plugin, Route } from "@elizaos/core";
const routes: Route[] = [
{
type: "GET",
public: true,
name: "health",
path: "/health",
handler: async (_req, res) => {
res.status(200).json({ ok: true });
},
},
];
export const myPlugin: Plugin = {
name: "my-plugin",
description: "Adds a /my-plugin/health route.",
routes,
};
Plugins can register event handlers via plugin.events (a map of event name → handlers).
The message pipeline emits events such as RUN_STARTED, RUN_TIMEOUT, and RUN_ENDED (see packages/typescript/src/services/message.ts).
Plugins can optionally provide:
schema: an object describing plugin-specific DB schemaAt runtime initialization, plugin migrations can be executed (unless skipMigrations: true is passed to runtime.initialize).
Plugins can declare:
dependencies: runtime dependenciestestDependencies: extra dependencies only for test modeThe dependency resolver and Node/Bun auto-install logic live in packages/typescript/src/plugin.ts.
The built-in basic-capabilities plugin is auto-included by AgentRuntime.initialize() unless already provided. When registering it, AgentRuntime.registerPlugin() can replace it with a configured basic-capabilities plugin based on:
disableBasicCapabilities, enableExtendedCapabilities, enableAutonomyDISABLE_BASIC_CAPABILITIES, ENABLE_EXTENDED_CAPABILITIES, ENABLE_AUTONOMYThis repository contains TypeScript unit tests for the core runtime under:
packages/typescript/src/__tests__/For plugin development examples, see the various plugins in the plugins/ directory. For plugin starter templates, follow the patterns in examples/_plugin/.