--- title: "Building Plugins" sidebarTitle: "Getting Started" summary: "Create your first OpenClaw plugin in minutes" read_when: - You want to create a new OpenClaw plugin - You need a quick-start for plugin development - You are adding a new channel, provider, tool, or other capability to OpenClaw --- # Building Plugins Plugins extend OpenClaw with new capabilities: channels, model providers, speech, image generation, web search, agent tools, or any combination. You do not need to add your plugin to the OpenClaw repository. Publish on npm and users install with `openclaw plugins install `. ## Prerequisites - Node >= 22 and a package manager (npm or pnpm) - Familiarity with TypeScript (ESM) - For in-repo plugins: repository cloned and `pnpm install` done ## What kind of plugin? Connect OpenClaw to a messaging platform (Discord, IRC, etc.) Add a model provider (LLM, proxy, or custom endpoint) Register agent tools, event hooks, or services — continue below ## Quick start: tool plugin This walkthrough creates a minimal plugin that registers an agent tool. Channel and provider plugins have dedicated guides linked above. ```json package.json { "name": "@myorg/openclaw-my-plugin", "version": "1.0.0", "type": "module", "openclaw": { "extensions": ["./index.ts"] } } ``` ```json openclaw.plugin.json { "id": "my-plugin", "name": "My Plugin", "description": "Adds a custom tool to OpenClaw", "configSchema": { "type": "object", "additionalProperties": false } } ``` Every plugin needs a manifest, even with no config. See [Manifest](/plugins/manifest) for the full schema. ```typescript // index.ts import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; import { Type } from "@sinclair/typebox"; export default definePluginEntry({ id: "my-plugin", name: "My Plugin", description: "Adds a custom tool to OpenClaw", register(api) { api.registerTool({ name: "my_tool", description: "Do a thing", parameters: Type.Object({ input: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: `Got: ${params.input}` }] }; }, }); }, }); ``` `definePluginEntry` is for non-channel plugins. For channels, use `defineChannelPluginEntry` — see [Channel Plugins](/plugins/sdk-channel-plugins). For full entry point options, see [Entry Points](/plugins/sdk-entrypoints). **External plugins:** ```bash npm publish openclaw plugins install @myorg/openclaw-my-plugin ``` **In-repo plugins:** place under `extensions/` — automatically discovered. ```bash pnpm test -- extensions/my-plugin/ ``` ## Plugin capabilities A single plugin can register any number of capabilities via the `api` object: | Capability | Registration method | Detailed guide | | -------------------- | --------------------------------------------- | ------------------------------------------------------------------------------- | | Text inference (LLM) | `api.registerProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins) | | Channel / messaging | `api.registerChannel(...)` | [Channel Plugins](/plugins/sdk-channel-plugins) | | Speech (TTS/STT) | `api.registerSpeechProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) | | Media understanding | `api.registerMediaUnderstandingProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) | | Image generation | `api.registerImageGenerationProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) | | Web search | `api.registerWebSearchProvider(...)` | [Provider Plugins](/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) | | Agent tools | `api.registerTool(...)` | Below | | Custom commands | `api.registerCommand(...)` | [Entry Points](/plugins/sdk-entrypoints) | | Event hooks | `api.registerHook(...)` | [Entry Points](/plugins/sdk-entrypoints) | | HTTP routes | `api.registerHttpRoute(...)` | [Internals](/plugins/architecture#gateway-http-routes) | | CLI subcommands | `api.registerCli(...)` | [Entry Points](/plugins/sdk-entrypoints) | For the full registration API, see [SDK Overview](/plugins/sdk-overview#registration-api). ## Registering agent tools Tools are typed functions the LLM can call. They can be required (always available) or optional (user opt-in): ```typescript register(api) { // Required tool — always available api.registerTool({ name: "my_tool", description: "Do a thing", parameters: Type.Object({ input: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: params.input }] }; }, }); // Optional tool — user must add to allowlist api.registerTool( { name: "workflow_tool", description: "Run a workflow", parameters: Type.Object({ pipeline: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: params.pipeline }] }; }, }, { optional: true }, ); } ``` Users enable optional tools in config: ```json5 { tools: { allow: ["workflow_tool"] }, } ``` - Tool names must not clash with core tools (conflicts are skipped) - Use `optional: true` for tools with side effects or extra binary requirements - Users can enable all tools from a plugin by adding the plugin id to `tools.allow` ## Import conventions Always import from focused `openclaw/plugin-sdk/` paths: ```typescript import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store"; // Wrong: monolithic root (deprecated, will be removed) import { ... } from "openclaw/plugin-sdk"; ``` For the full subpath reference, see [SDK Overview](/plugins/sdk-overview). Within your plugin, use local barrel files (`api.ts`, `runtime-api.ts`) for internal imports — never import your own plugin through its SDK path. ## Pre-submission checklist **package.json** has correct `openclaw` metadata **openclaw.plugin.json** manifest is present and valid Entry point uses `defineChannelPluginEntry` or `definePluginEntry` All imports use focused `plugin-sdk/` paths Internal imports use local modules, not SDK self-imports Tests pass (`pnpm test -- extensions/my-plugin/`) `pnpm check` passes (in-repo plugins) ## Next steps Build a messaging channel plugin Build a model provider plugin Import map and registration API reference TTS, search, subagent via api.runtime Test utilities and patterns Full manifest schema reference