diff --git a/docs/docs.json b/docs/docs.json
index 2ae489a38b0..87ae0c5a120 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -68,6 +68,14 @@
"source": "/plugins/building-extensions",
"destination": "/plugins/building-plugins"
},
+ {
+ "source": "/plugins/agent-tools",
+ "destination": "/plugins/building-plugins#registering-agent-tools"
+ },
+ {
+ "source": "/tools/capability-cookbook",
+ "destination": "/plugins/architecture"
+ },
{
"source": "/brave-search",
"destination": "/tools/brave-search"
@@ -1033,10 +1041,8 @@
"plugins/community",
"plugins/bundles",
"plugins/manifest",
- "plugins/agent-tools",
"plugins/sdk-migration",
- "plugins/architecture",
- "tools/capability-cookbook"
+ "plugins/architecture"
]
},
{
diff --git a/docs/plugins/agent-tools.md b/docs/plugins/agent-tools.md
index ea3cd7e231d..930bdfbe629 100644
--- a/docs/plugins/agent-tools.md
+++ b/docs/plugins/agent-tools.md
@@ -1,103 +1,10 @@
---
-summary: "Register custom agent tools in a plugin with schemas, optional opt-in, and allowlists"
+summary: "Redirects to Building Plugins (registering tools section)"
read_when:
- - You want to add a new agent tool in a plugin
- - You need to make a tool opt-in via allowlists
-title: "Registering Tools in Plugins"
-sidebarTitle: "Registering Tools"
+ - Legacy link to agent-tools
+title: "Registering Tools"
---
# Registering Tools in Plugins
-Plugins can register **agent tools** — typed functions that the LLM can call
-during agent runs. Tools can be **required** (always available) or
-**optional** (users opt in via allowlists).
-
-See [Building Plugins](/plugins/building-plugins) for the full plugin creation
-guide. This page focuses on the tool registration API.
-
-Agent tools are configured under `tools` in the main config, or per‑agent under
-`agents.list[].tools`. The allowlist/denylist policy controls which tools the agent
-can call.
-
-## Basic tool
-
-```ts
-import { Type } from "@sinclair/typebox";
-
-export default function (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: params.input }] };
- },
- });
-}
-```
-
-## Optional tool (opt-in)
-
-Optional tools are **never** auto‑enabled. Users must add them to an agent
-allowlist.
-
-```ts
-export default function (api) {
- api.registerTool(
- {
- name: "workflow_tool",
- description: "Run a local workflow",
- parameters: {
- type: "object",
- properties: {
- pipeline: { type: "string" },
- },
- required: ["pipeline"],
- },
- async execute(_id, params) {
- return { content: [{ type: "text", text: params.pipeline }] };
- },
- },
- { optional: true },
- );
-}
-```
-
-Enable optional tools in `agents.list[].tools.allow` (or global `tools.allow`):
-
-```json5
-{
- agents: {
- list: [
- {
- id: "main",
- tools: {
- allow: [
- "workflow_tool", // specific tool name
- "workflow", // plugin id (enables all tools from that plugin)
- "group:plugins", // all plugin tools
- ],
- },
- },
- ],
- },
-}
-```
-
-Other config knobs that affect tool availability:
-
-- Allowlists that only name plugin tools are treated as plugin opt-ins; core tools remain
- enabled unless you also include core tools or groups in the allowlist.
-- `tools.profile` / `agents.list[].tools.profile` (base allowlist)
-- `tools.byProvider` / `agents.list[].tools.byProvider` (provider‑specific allow/deny)
-- `tools.sandbox.tools.*` (sandbox tool policy when sandboxed)
-
-## Rules + tips
-
-- Tool names must **not** clash with core tool names; conflicting tools are skipped.
-- Plugin ids used in allowlists must not clash with core tool names.
-- Prefer `optional: true` for tools that trigger side effects or require extra
- binaries/credentials.
+This page has moved. See [Building Plugins: Registering agent tools](/plugins/building-plugins#registering-agent-tools).
diff --git a/docs/plugins/building-plugins.md b/docs/plugins/building-plugins.md
index eea080fb406..9e6d1a71880 100644
--- a/docs/plugins/building-plugins.md
+++ b/docs/plugins/building-plugins.md
@@ -285,6 +285,58 @@ my-plugin/
+## Registering agent tools
+
+Plugins can register **agent tools** — typed functions the LLM can call. Tools
+can be required (always available) or optional (users opt in via allowlists).
+
+```typescript
+import { Type } from "@sinclair/typebox";
+
+export default definePluginEntry({
+ id: "my-plugin",
+ name: "My Plugin",
+ 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 },
+ );
+ },
+});
+```
+
+Enable optional tools in config:
+
+```json5
+{
+ tools: { allow: ["workflow_tool"] },
+}
+```
+
+Tips:
+
+- Tool names must not clash with core tool names (conflicts are skipped)
+- Use `optional: true` for tools that trigger side effects or require extra binaries
+- Users can enable all tools from a plugin by adding the plugin id to `tools.allow`
+
## Lint enforcement (in-repo plugins)
Three scripts enforce SDK boundaries for plugins in the OpenClaw repository:
diff --git a/docs/plugins/bundles.md b/docs/plugins/bundles.md
index 82a5605e099..b60b110e6b7 100644
--- a/docs/plugins/bundles.md
+++ b/docs/plugins/bundles.md
@@ -1,307 +1,181 @@
---
-summary: "Unified bundle format guide for Codex, Claude, and Cursor bundles in OpenClaw"
+summary: "Install and use Codex, Claude, and Cursor bundles as OpenClaw plugins"
read_when:
- - You want to install or debug a Codex, Claude, or Cursor-compatible bundle
+ - You want to install a Codex, Claude, or Cursor-compatible bundle
- You need to understand how OpenClaw maps bundle content into native features
- - You are documenting bundle compatibility or current support limits
+ - You are debugging bundle detection or missing capabilities
title: "Plugin Bundles"
---
-# Plugin bundles
+# Plugin Bundles
-OpenClaw supports one shared class of external plugin package: **bundle
-plugins**.
+OpenClaw can install plugins from three external ecosystems: **Codex**, **Claude**,
+and **Cursor**. These are called **bundles** — content and metadata packs that
+OpenClaw maps into native features like skills, hooks, and MCP tools.
-Today that means three closely related ecosystems:
+
+ Bundles are **not** the same as native OpenClaw plugins. Native plugins run
+ in-process and can register any capability. Bundles are content packs with
+ selective feature mapping and a narrower trust boundary.
+
-- Codex bundles
-- Claude bundles
-- Cursor bundles
+## Why bundles exist
-OpenClaw shows all of them as `Format: bundle` in `openclaw plugins list`.
-Verbose output and `openclaw plugins inspect ` also show the subtype
-(`codex`, `claude`, or `cursor`).
+Many useful plugins are published in Codex, Claude, or Cursor format. Instead
+of requiring authors to rewrite them as native OpenClaw plugins, OpenClaw
+detects these formats and maps their supported content into the native feature
+set. This means you can install a Claude command pack or a Codex skill bundle
+and use it immediately.
-Related:
+## Install a bundle
-- Plugin system overview: [Plugins](/tools/plugin)
-- CLI install/list flows: [plugins](/cli/plugins)
-- Native manifest schema: [Plugin manifest](/plugins/manifest)
+
+
+ ```bash
+ # Local directory
+ openclaw plugins install ./my-bundle
-## What a bundle is
+ # Archive
+ openclaw plugins install ./my-bundle.tgz
-A bundle is a **content/metadata pack**, not a native in-process OpenClaw
-plugin.
+ # Claude marketplace
+ openclaw plugins marketplace list
+ openclaw plugins install @
+ ```
-Today, OpenClaw does **not** execute bundle runtime code in-process. Instead,
-it detects known bundle files, reads the metadata, and maps supported bundle
-content into native OpenClaw surfaces such as skills, hook packs, MCP config,
-and embedded Pi settings.
+
-That is the main trust boundary:
+
+ ```bash
+ openclaw plugins list
+ openclaw plugins inspect
+ ```
-- native OpenClaw plugin: runtime module executes in-process
-- bundle: metadata/content pack, with selective feature mapping
+ Bundles show as `Format: bundle` with a subtype of `codex`, `claude`, or `cursor`.
-## Shared bundle model
+
-Codex, Claude, and Cursor bundles are similar enough that OpenClaw treats them
-as one normalized model.
+
+ ```bash
+ openclaw gateway restart
+ ```
-Shared idea:
+ Mapped features (skills, hooks, MCP tools) are available in the next session.
-- a small manifest file, or a default directory layout
-- one or more content roots such as `skills/` or `commands/`
-- optional tool/runtime metadata such as MCP, hooks, agents, or LSP
-- install as a directory or archive, then enable in the normal plugin list
+
+
-Common OpenClaw behavior:
+## What OpenClaw maps from bundles
-- detect the bundle subtype
-- normalize it into one internal bundle record
-- map supported parts into native OpenClaw features
-- report unsupported parts as detected-but-not-wired capabilities
-
-In practice, most users do not need to think about the vendor-specific format
-first. The more useful question is: which bundle surfaces does OpenClaw map
-today?
-
-## Detection order
-
-OpenClaw prefers native OpenClaw plugin/package layouts before bundle handling.
-
-Practical effect:
-
-- `openclaw.plugin.json` wins over bundle detection
-- package installs with valid `package.json` + `openclaw.extensions` use the
- native install path
-- if a directory contains both native and bundle metadata, OpenClaw treats it
- as native first
-
-That avoids partially installing a dual-format package as a bundle and then
-loading it later as a native plugin.
-
-## What works today
-
-OpenClaw normalizes bundle metadata into one internal bundle record, then maps
-supported surfaces into existing native behavior.
+Not every bundle feature runs in OpenClaw today. Here is what works and what
+is detected but not yet wired.
### Supported now
-#### Skill content
-
-- bundle skill roots load as normal OpenClaw skill roots
-- Claude `commands` roots are treated as additional skill roots
-- Cursor `.cursor/commands` roots are treated as additional skill roots
-
-This means Claude markdown command files work through the normal OpenClaw skill
-loader. Cursor command markdown works through the same path.
-
-#### Hook packs
-
-- bundle hook roots work **only** when they use the normal OpenClaw hook-pack
- layout. Today this is primarily the Codex-compatible case:
- - `HOOK.md`
- - `handler.ts` or `handler.js`
-
-#### MCP for Pi
-
-- enabled bundles can contribute MCP server config
-- OpenClaw merges bundle MCP config into the effective embedded Pi settings as
- `mcpServers`
-- OpenClaw also exposes supported bundle MCP tools during embedded Pi agent
- turns by launching supported stdio MCP servers as subprocesses
-- project-local Pi settings still apply after bundle defaults, so workspace
- settings can override bundle MCP entries when needed
-
-#### Embedded Pi settings
-
-- Claude `settings.json` is imported as default embedded Pi settings when the
- bundle is enabled
-- OpenClaw sanitizes shell override keys before applying them
-
-Sanitized keys:
-
-- `shellPath`
-- `shellCommandPrefix`
+| Feature | How it maps | Applies to |
+| ------------- | ---------------------------------------------------------------------------------------------------- | -------------- |
+| Skill content | Bundle skill roots load as normal OpenClaw skills | All formats |
+| Commands | `commands/` and `.cursor/commands/` treated as skill roots | Claude, Cursor |
+| Hook packs | OpenClaw-style `HOOK.md` + `handler.ts` layouts | Codex |
+| MCP tools | Bundle MCP config merged into embedded Pi settings; supported stdio servers launched as subprocesses | All formats |
+| Settings | Claude `settings.json` imported as embedded Pi defaults | Claude |
### Detected but not executed
-These surfaces are detected, shown in bundle capabilities, and may appear in
-diagnostics/info output, but OpenClaw does not run them yet:
+These are recognized and shown in diagnostics, but OpenClaw does not run them:
-- Claude `agents`
-- Claude `hooks.json` automation
-- Claude `lspServers`
-- Claude `outputStyles`
-- Cursor `.cursor/agents`
-- Cursor `.cursor/hooks.json`
-- Cursor `.cursor/rules`
+- Claude `agents`, `hooks.json` automation, `lspServers`, `outputStyles`
+- Cursor `.cursor/agents`, `.cursor/hooks.json`, `.cursor/rules`
- Codex inline/app metadata beyond capability reporting
-## Capability reporting
+## Bundle formats
-`openclaw plugins inspect ` shows bundle capabilities from the normalized
-bundle record.
+
+
+ Markers: `.codex-plugin/plugin.json`
-Supported capabilities are loaded quietly. Unsupported capabilities produce a
-warning such as:
+ Optional content: `skills/`, `hooks/`, `.mcp.json`, `.app.json`
-```text
-bundle capability detected but not wired into OpenClaw yet: agents
-```
+ Codex bundles fit OpenClaw best when they use skill roots and OpenClaw-style
+ hook-pack directories (`HOOK.md` + `handler.ts`).
-Current exceptions:
+
-- Claude `commands` is considered supported because it maps to skills
-- Claude `settings` is considered supported because it maps to embedded Pi settings
-- Cursor `commands` is considered supported because it maps to skills
-- bundle MCP is considered supported because it maps into embedded Pi settings
- and exposes supported stdio tools to embedded Pi
-- Codex `hooks` is considered supported only for OpenClaw hook-pack layouts
+
+ Two detection modes:
-## Format differences
+ - **Manifest-based:** `.claude-plugin/plugin.json`
+ - **Manifestless:** default Claude layout (`skills/`, `commands/`, `agents/`, `hooks/`, `.mcp.json`, `settings.json`)
-The formats are close, but not byte-for-byte identical. These are the practical
-differences that matter in OpenClaw.
+ Claude-specific behavior:
-### Codex
+ - `commands/` is treated as skill content
+ - `settings.json` is imported into embedded Pi settings (shell override keys are sanitized)
+ - `.mcp.json` exposes supported stdio tools to embedded Pi
+ - `hooks/hooks.json` is detected but not executed
+ - Custom component paths in the manifest are additive (they extend defaults, not replace them)
-Typical markers:
+
-- `.codex-plugin/plugin.json`
-- optional `skills/`
-- optional `hooks/`
-- optional `.mcp.json`
-- optional `.app.json`
+
+ Markers: `.cursor-plugin/plugin.json`
-Codex bundles fit OpenClaw best when they use skill roots and OpenClaw-style
-hook-pack directories.
+ Optional content: `skills/`, `.cursor/commands/`, `.cursor/agents/`, `.cursor/rules/`, `.cursor/hooks.json`, `.mcp.json`
-### Claude
+ - `.cursor/commands/` is treated as skill content
+ - `.cursor/rules/`, `.cursor/agents/`, and `.cursor/hooks.json` are detect-only
-OpenClaw supports both:
+
+
-- manifest-based Claude bundles: `.claude-plugin/plugin.json`
-- manifestless Claude bundles that use the default Claude layout
+## Detection precedence
-Default Claude layout markers OpenClaw recognizes:
+OpenClaw checks for native plugin format first:
-- `skills/`
-- `commands/`
-- `agents/`
-- `hooks/hooks.json`
-- `.mcp.json`
-- `.lsp.json`
-- `settings.json`
+1. `openclaw.plugin.json` or valid `package.json` with `openclaw.extensions` — treated as **native plugin**
+2. Bundle markers (`.codex-plugin/`, `.claude-plugin/`, or default Claude/Cursor layout) — treated as **bundle**
-Claude-specific notes:
+If a directory contains both, OpenClaw uses the native path. This prevents
+dual-format packages from being partially installed as bundles.
-- `commands/` is treated like skill content
-- `settings.json` is imported into embedded Pi settings
-- `.mcp.json` and manifest `mcpServers` can expose supported stdio tools to
- embedded Pi
-- `hooks/hooks.json` is detected, but not executed as Claude automation
+## Security
-### Cursor
+Bundles have a narrower trust boundary than native plugins:
-Typical markers:
+- OpenClaw does **not** load arbitrary bundle runtime modules in-process
+- Skills and hook-pack paths must stay inside the plugin root (boundary-checked)
+- Settings files are read with the same boundary checks
+- Supported stdio MCP servers may be launched as subprocesses
-- `.cursor-plugin/plugin.json`
-- optional `skills/`
-- optional `.cursor/commands/`
-- optional `.cursor/agents/`
-- optional `.cursor/rules/`
-- optional `.cursor/hooks.json`
-- optional `.mcp.json`
-
-Cursor-specific notes:
-
-- `.cursor/commands/` is treated like skill content
-- `.cursor/rules/`, `.cursor/agents/`, and `.cursor/hooks.json` are
- detect-only today
-
-## Claude custom paths
-
-Claude bundle manifests can declare custom component paths. OpenClaw treats
-those paths as **additive**, not replacing defaults.
-
-Currently recognized custom path keys:
-
-- `skills`
-- `commands`
-- `agents`
-- `hooks`
-- `mcpServers`
-- `lspServers`
-- `outputStyles`
-
-Examples:
-
-- default `commands/` plus manifest `commands: "extra-commands"` =>
- OpenClaw scans both
-- default `skills/` plus manifest `skills: ["team-skills"]` =>
- OpenClaw scans both
-
-## Security model
-
-Bundle support is intentionally narrower than native plugin support.
-
-Current behavior:
-
-- bundle discovery reads files inside the plugin root with boundary checks
-- skills and hook-pack paths must stay inside the plugin root
-- bundle settings files are read with the same boundary checks
-- supported stdio bundle MCP servers may be launched as subprocesses for
- embedded Pi tool calls
-- OpenClaw does not load arbitrary bundle runtime modules in-process
-
-This makes bundle support safer by default than native plugin modules, but you
-should still treat third-party bundles as trusted content for the features they
-do expose.
-
-## Install examples
-
-```bash
-openclaw plugins install ./my-codex-bundle
-openclaw plugins install ./my-claude-bundle
-openclaw plugins install ./my-cursor-bundle
-openclaw plugins install ./my-bundle.tgz
-openclaw plugins marketplace list
-openclaw plugins install @
-openclaw plugins inspect my-bundle
-```
-
-If the directory is a native OpenClaw plugin/package, the native install path
-still wins.
-
-For Claude marketplace names, OpenClaw reads the local Claude known-marketplace
-registry at `~/.claude/plugins/known_marketplaces.json`. Marketplace entries
-can resolve to bundle-compatible directories/archives or to native plugin
-sources; after resolution, the normal install rules still apply.
+This makes bundles safer by default, but you should still treat third-party
+bundles as trusted content for the features they do expose.
## Troubleshooting
-### Bundle is detected but capabilities do not run
+
+
+ Run `openclaw plugins inspect `. If a capability is listed but marked as
+ not wired, that is a product limit — not a broken install.
+
-Check `openclaw plugins inspect `.
+
+ Make sure the bundle is enabled and the markdown files are inside a detected
+ `commands/` or `skills/` root.
+
-If the capability is listed but OpenClaw says it is not wired yet, that is a
-real product limit, not a broken install.
+
+ Only embedded Pi settings from `settings.json` are supported. OpenClaw does
+ not treat bundle settings as raw config patches.
+
-### Claude command files do not appear
+
+ `hooks/hooks.json` is detect-only. If you need runnable hooks, use the
+ OpenClaw hook-pack layout or ship a native plugin.
+
+
-Make sure the bundle is enabled and the markdown files are inside a detected
-`commands` root or `skills` root.
+## Related
-### Claude settings do not apply
-
-Current support is limited to embedded Pi settings from `settings.json`.
-OpenClaw does not treat bundle settings as raw OpenClaw config patches.
-
-### Claude hooks do not execute
-
-`hooks/hooks.json` is only detected today.
-
-If you need runnable bundle hooks today, use the normal OpenClaw hook-pack
-layout through a supported Codex hook root or ship a native OpenClaw plugin.
+- [Install and Configure Plugins](/tools/plugin)
+- [Building Plugins](/plugins/building-plugins) — create a native plugin
+- [Plugin Manifest](/plugins/manifest) — native manifest schema
diff --git a/docs/plugins/community.md b/docs/plugins/community.md
index 0ff0ef7e69c..6aeda3aca44 100644
--- a/docs/plugins/community.md
+++ b/docs/plugins/community.md
@@ -45,17 +45,6 @@ openclaw plugins install
-
- Supports text, image, and file exchange with keyword-triggered conversations.
-
- - **npm:** `@icesword760/openclaw-wechat`
- - **repo:** [github.com/icesword0760/openclaw-wechat](https://github.com/icesword0760/openclaw-wechat)
-
- ```bash
- openclaw plugins install @icesword760/openclaw-wechat
- ```
-
-
## Submit your plugin
diff --git a/docs/plugins/sdk-migration.md b/docs/plugins/sdk-migration.md
index 53ac7d71750..52501f5b9c7 100644
--- a/docs/plugins/sdk-migration.md
+++ b/docs/plugins/sdk-migration.md
@@ -1,41 +1,52 @@
---
title: "Plugin SDK Migration"
sidebarTitle: "SDK Migration"
-summary: "Migrate from legacy compat surfaces to focused plugin-sdk subpaths and injected runtime helpers"
+summary: "Migrate from the legacy backwards-compatibility layer to the modern plugin SDK"
read_when:
- You see the OPENCLAW_PLUGIN_SDK_COMPAT_DEPRECATED warning
- You see the OPENCLAW_EXTENSION_API_DEPRECATED warning
- - You are updating a plugin from the monolithic plugin-sdk import to scoped subpaths
- - You are updating a plugin away from openclaw/extension-api
+ - You are updating a plugin to the modern plugin architecture
- You maintain an external OpenClaw plugin
---
# Plugin SDK Migration
-OpenClaw is migrating from broad compatibility surfaces to narrower, documented
-contracts:
+OpenClaw has moved from a broad backwards-compatibility layer to a modern plugin
+architecture with focused, documented imports. If your plugin was built before
+the new architecture, this guide helps you migrate.
-- `openclaw/plugin-sdk/compat` -> focused `openclaw/plugin-sdk/` imports
-- `openclaw/extension-api` -> injected runtime helpers such as `api.runtime.agent.*`
+## What is changing
-This page explains what changed, why, and how to migrate.
+The old plugin system provided two wide-open surfaces that let plugins import
+anything they needed from a single entry point:
-
- The compat import still works at runtime. This is a deprecation warning, not
- a breaking change yet. But new plugins **must not** use it, and existing
- plugins should migrate before the next major release removes it.
-
+- **`openclaw/plugin-sdk/compat`** — a single import that re-exported dozens of
+ helpers. It was introduced to keep older hook-based plugins working while the
+ new plugin architecture was being built.
+- **`openclaw/extension-api`** — a bridge that gave plugins direct access to
+ host-side helpers like the embedded agent runner.
+
+Both surfaces are now **deprecated**. They still work at runtime, but new
+plugins must not use them, and existing plugins should migrate before the next
+major release removes them.
+
+
+ The backwards-compatibility layer will be removed in a future major release.
+ Plugins that still import from these surfaces will break when that happens.
+
## Why this changed
-The old monolithic `openclaw/plugin-sdk/compat` re-exported everything from one
-entry point. This caused slow startup (importing one helper loaded dozens of
-unrelated modules), circular dependency risk, and an unclear API surface.
+The old approach caused problems:
-Focused subpaths fix all three: each subpath is a small, self-contained module
-with a clear purpose.
+- **Slow startup** — importing one helper loaded dozens of unrelated modules
+- **Circular dependencies** — broad re-exports made it easy to create import cycles
+- **Unclear API surface** — no way to tell which exports were stable vs internal
-## Migration steps
+The modern plugin SDK fixes this: each import path (`openclaw/plugin-sdk/\`)
+is a small, self-contained module with a clear purpose and documented contract.
+
+## How to migrate
@@ -43,91 +54,66 @@ with a clear purpose.
```bash
grep -r "plugin-sdk/compat" my-plugin/
- grep -r "openclaw/extension-api" extensions/my-plugin/
+ grep -r "openclaw/extension-api" my-plugin/
```
-
- Each export from compat maps to a specific subpath. Replace the import
- source:
+
+ Each export from the old surface maps to a specific modern import path:
```typescript
- // Before (compat entry)
+ // Before (deprecated backwards-compatibility layer)
import {
createChannelReplyPipeline,
createPluginRuntimeStore,
resolveControlCommandGate,
} from "openclaw/plugin-sdk/compat";
- // After (focused subpaths)
+ // After (modern focused imports)
import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
import { resolveControlCommandGate } from "openclaw/plugin-sdk/command-auth";
```
- If your plugin imports from `openclaw/extension-api`, you will now see:
-
- ```text
- [OPENCLAW_EXTENSION_API_DEPRECATED] Warning: openclaw/extension-api is deprecated.
- Migrate to api.runtime.agent.* or focused openclaw/plugin-sdk/ imports.
- ```
-
- That bridge also still works at runtime today. It exists to preserve older
- plugins while they migrate to the injected plugin runtime.
-
- Move host-side helpers onto the injected plugin runtime instead of
- importing them directly:
+ For host-side helpers, use the injected plugin runtime instead of importing
+ directly:
```typescript
// Before (deprecated extension-api bridge)
import { runEmbeddedPiAgent } from "openclaw/extension-api";
+ const result = await runEmbeddedPiAgent({ sessionId, prompt });
- const result = await runEmbeddedPiAgent({
- sessionId,
- sessionFile,
- workspaceDir,
- prompt,
- timeoutMs,
- });
-
- // After (preferred injected runtime)
- const result = await api.runtime.agent.runEmbeddedPiAgent({
- sessionId,
- sessionFile,
- workspaceDir,
- prompt,
- timeoutMs,
- });
+ // After (injected runtime)
+ const result = await api.runtime.agent.runEmbeddedPiAgent({ sessionId, prompt });
```
- The same pattern applies to the other legacy `extension-api` helpers:
+ The same pattern applies to other legacy bridge helpers:
- - `resolveAgentDir` -> `api.runtime.agent.resolveAgentDir`
- - `resolveAgentWorkspaceDir` -> `api.runtime.agent.resolveAgentWorkspaceDir`
- - `resolveAgentIdentity` -> `api.runtime.agent.resolveAgentIdentity`
- - `resolveThinkingDefault` -> `api.runtime.agent.resolveThinkingDefault`
- - `resolveAgentTimeoutMs` -> `api.runtime.agent.resolveAgentTimeoutMs`
- - `ensureAgentWorkspace` -> `api.runtime.agent.ensureAgentWorkspace`
- - session store helpers -> `api.runtime.agent.session.*`
-
- See the [subpath reference](#subpath-reference) below for the scoped import
- mapping.
+ | Old import | Modern equivalent |
+ | --- | --- |
+ | `resolveAgentDir` | `api.runtime.agent.resolveAgentDir` |
+ | `resolveAgentWorkspaceDir` | `api.runtime.agent.resolveAgentWorkspaceDir` |
+ | `resolveAgentIdentity` | `api.runtime.agent.resolveAgentIdentity` |
+ | `resolveThinkingDefault` | `api.runtime.agent.resolveThinkingDefault` |
+ | `resolveAgentTimeoutMs` | `api.runtime.agent.resolveAgentTimeoutMs` |
+ | `ensureAgentWorkspace` | `api.runtime.agent.ensureAgentWorkspace` |
+ | session store helpers | `api.runtime.agent.session.*` |
```bash
pnpm build
- pnpm test -- extensions/my-plugin/
+ pnpm test -- my-plugin/
```
-## Subpath reference
+## Import path reference
-
- | Subpath | Purpose | Key exports |
+
+ | Import path | Purpose | Key exports |
| --- | --- | --- |
| `plugin-sdk/core` | Plugin entry definitions, base types | `defineChannelPluginEntry`, `definePluginEntry` |
| `plugin-sdk/channel-setup` | Setup wizard adapters | `createOptionalChannelSetupSurface` |
@@ -151,22 +137,22 @@ with a clear purpose.
| `plugin-sdk/testing` | Test utilities | Test helpers and mocks |
-Use the narrowest subpath that matches the job. If you cannot find an export,
+Use the narrowest import that matches the job. If you cannot find an export,
check the source at `src/plugin-sdk/` or ask in Discord.
## Removal timeline
-| When | What happens |
-| --- | --- |
-| **Now** | Compat import and `openclaw/extension-api` emit runtime warnings |
-| **Next major release** | These legacy bridges may be removed; plugins still using them will fail |
+| When | What happens |
+| ---------------------- | ----------------------------------------------------------------------- |
+| **Now** | Deprecated surfaces emit runtime warnings |
+| **Next major release** | Deprecated surfaces will be removed; plugins still using them will fail |
All core plugins have already been migrated. External plugins should migrate
before the next major release.
-## Suppressing the warning temporarily
+## Suppressing the warnings temporarily
-Set this environment variable while you work on migrating:
+Set these environment variables while you work on migrating:
```bash
OPENCLAW_SUPPRESS_PLUGIN_SDK_COMPAT_WARNING=1 openclaw gateway run
@@ -178,5 +164,5 @@ This is a temporary escape hatch, not a permanent solution.
## Related
- [Building Plugins](/plugins/building-plugins)
-- [Plugin Architecture](/plugins/architecture)
+- [Plugin Internals](/plugins/architecture)
- [Plugin Manifest](/plugins/manifest)