diff --git a/docs/docs.json b/docs/docs.json index 2b8d8d84a0c..e39cf3f25a8 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -64,6 +64,10 @@ "source": "/platforms/raspberry-pi", "destination": "/install/raspberry-pi" }, + { + "source": "/plugins/building-extensions", + "destination": "/plugins/building-plugins" + }, { "source": "/brave-search", "destination": "/tools/brave-search" @@ -1015,7 +1019,7 @@ ] }, { - "tab": "Tools", + "tab": "Tools & Plugins", "groups": [ { "group": "Overview", @@ -1024,23 +1028,20 @@ { "group": "Built-in tools", "pages": [ - "tools/apply-patch", - "tools/brave-search", - "tools/btw", - "tools/diffs", - "tools/elevated", "tools/exec", "tools/exec-approvals", + "tools/elevated", + "tools/apply-patch", + "tools/web", + "tools/brave-search", "tools/firecrawl", "tools/tavily", - "tools/llm-task", - "tools/lobster", - "tools/loop-detection", - "tools/pdf", "tools/perplexity-search", + "tools/pdf", "tools/reactions", "tools/thinking", - "tools/web" + "tools/loop-detection", + "tools/btw" ] }, { @@ -1061,22 +1062,11 @@ "tools/multi-agent-sandbox-tools" ] }, - { - "group": "Skills", - "pages": [ - "tools/creating-skills", - "tools/slash-commands", - "tools/skills", - "tools/skills-config", - "tools/clawhub", - "tools/plugin", - "prose" - ] - }, { "group": "Plugins", "pages": [ - "plugins/building-extensions", + "tools/plugin", + "plugins/building-plugins", "plugins/sdk-migration", "plugins/architecture", "plugins/community", @@ -1086,6 +1076,21 @@ "tools/capability-cookbook" ] }, + { + "group": "Skills", + "pages": [ + "tools/skills", + "tools/creating-skills", + "tools/skills-config", + "tools/slash-commands", + "tools/clawhub", + "prose" + ] + }, + { + "group": "Plugin tools", + "pages": ["tools/diffs", "tools/llm-task", "tools/lobster"] + }, { "group": "Automation", "pages": [ diff --git a/docs/plugins/building-extensions.md b/docs/plugins/building-extensions.md index 026ac4492de..f0db0f3173f 100644 --- a/docs/plugins/building-extensions.md +++ b/docs/plugins/building-extensions.md @@ -1,309 +1,10 @@ --- title: "Building Plugins" -sidebarTitle: "Building Plugins" -summary: "Step-by-step guide for creating OpenClaw plugins with any combination of capabilities" +summary: "Redirects to the current Building Plugins guide" read_when: - - You want to create a new OpenClaw plugin - - You need to understand the plugin SDK import patterns - - You are adding a new channel, provider, tool, or other capability to OpenClaw + - Legacy link to building-extensions --- # Building Plugins -Plugins extend OpenClaw with new capabilities: channels, model providers, speech, -image generation, web search, agent tools, or any combination. A single plugin -can register multiple capabilities. - -OpenClaw encourages **external plugin development**. You do not need to add your -plugin to the OpenClaw repository. Publish your plugin on npm, and users install -it with `openclaw plugins install `. OpenClaw also maintains a set of -core plugins in-repo, but the plugin system is designed for independent ownership -and distribution. - -## Prerequisites - -- Node >= 22 and a package manager (npm or pnpm) -- Familiarity with TypeScript (ESM) -- For in-repo plugins: OpenClaw repository cloned and `pnpm install` done - -## Plugin capabilities - -A plugin can register one or more capabilities. The capability you register -determines what your plugin provides to OpenClaw: - -| Capability | Registration method | What it adds | -| ------------------- | --------------------------------------------- | ------------------------------ | -| Text inference | `api.registerProvider(...)` | Model provider (LLM) | -| Channel / messaging | `api.registerChannel(...)` | Chat channel (e.g. Slack, IRC) | -| Speech | `api.registerSpeechProvider(...)` | Text-to-speech / STT | -| Media understanding | `api.registerMediaUnderstandingProvider(...)` | Image/audio/video analysis | -| Image generation | `api.registerImageGenerationProvider(...)` | Image generation | -| Web search | `api.registerWebSearchProvider(...)` | Web search provider | -| Agent tools | `api.registerTool(...)` | Tools callable by the agent | - -A plugin that registers zero capabilities but provides hooks or services is a -**hook-only** plugin. That pattern is still supported. - -## Plugin structure - -Plugins follow this layout (whether in-repo or standalone): - -``` -my-plugin/ -├── package.json # npm metadata + openclaw config -├── openclaw.plugin.json # Plugin manifest -├── index.ts # Entry point -├── setup-entry.ts # Setup wizard (optional) -├── api.ts # Public exports (optional) -├── runtime-api.ts # Internal exports (optional) -└── src/ - ├── provider.ts # Capability implementation - ├── runtime.ts # Runtime wiring - └── *.test.ts # Colocated tests -``` - -## Create a plugin - - - - Create `package.json` with the `openclaw` metadata block. The structure - depends on what capabilities your plugin provides. - - **Channel plugin example:** - - ```json - { - "name": "@myorg/openclaw-my-channel", - "version": "1.0.0", - "type": "module", - "openclaw": { - "extensions": ["./index.ts"], - "channel": { - "id": "my-channel", - "label": "My Channel", - "blurb": "Short description of the channel." - } - } - } - ``` - - **Provider plugin example:** - - ```json - { - "name": "@myorg/openclaw-my-provider", - "version": "1.0.0", - "type": "module", - "openclaw": { - "extensions": ["./index.ts"], - "providers": ["my-provider"] - } - } - ``` - - The `openclaw` field tells the plugin system what your plugin provides. - A plugin can declare both `channel` and `providers` if it provides multiple - capabilities. - - - - - The entry point registers your capabilities with the plugin API. - - **Channel plugin:** - - ```typescript - import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; - - export default defineChannelPluginEntry({ - id: "my-channel", - name: "My Channel", - description: "Connects OpenClaw to My Channel", - plugin: { - // Channel adapter implementation - }, - }); - ``` - - **Provider plugin:** - - ```typescript - import { definePluginEntry } from "openclaw/plugin-sdk/core"; - - export default definePluginEntry({ - id: "my-provider", - name: "My Provider", - register(api) { - api.registerProvider({ - // Provider implementation - }); - }, - }); - ``` - - **Multi-capability plugin** (provider + tool): - - ```typescript - import { definePluginEntry } from "openclaw/plugin-sdk/core"; - - export default definePluginEntry({ - id: "my-plugin", - name: "My Plugin", - register(api) { - api.registerProvider({ /* ... */ }); - api.registerTool({ /* ... */ }); - api.registerImageGenerationProvider({ /* ... */ }); - }, - }); - ``` - - Use `defineChannelPluginEntry` for channel plugins and `definePluginEntry` - for everything else. A single plugin can register as many capabilities as needed. - - - - - Always import from specific `openclaw/plugin-sdk/\` paths. The old - monolithic import is deprecated (see [SDK Migration](/plugins/sdk-migration)). - - ```typescript - // Correct: focused subpaths - import { definePluginEntry } from "openclaw/plugin-sdk/core"; - import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store"; - import { buildOauthProviderAuthResult } from "openclaw/plugin-sdk/provider-oauth"; - - // Wrong: monolithic root (lint will reject this) - import { ... } from "openclaw/plugin-sdk"; - ``` - - - | Subpath | Purpose | - | --- | --- | - | `plugin-sdk/core` | Plugin entry definitions and base types | - | `plugin-sdk/channel-setup` | Setup wizard adapters | - | `plugin-sdk/channel-pairing` | DM pairing primitives | - | `plugin-sdk/channel-reply-pipeline` | Reply prefix + typing wiring | - | `plugin-sdk/channel-config-schema` | Config schema builders | - | `plugin-sdk/channel-policy` | Group/DM policy helpers | - | `plugin-sdk/secret-input` | Secret input parsing/helpers | - | `plugin-sdk/webhook-ingress` | Webhook request/target helpers | - | `plugin-sdk/runtime-store` | Persistent plugin storage | - | `plugin-sdk/allow-from` | Allowlist resolution | - | `plugin-sdk/reply-payload` | Message reply types | - | `plugin-sdk/provider-oauth` | OAuth login + PKCE helpers | - | `plugin-sdk/provider-onboard` | Provider onboarding config patches | - | `plugin-sdk/testing` | Test utilities | - - - Use the narrowest subpath that matches the job. - - - - - Within your plugin, create local module files for internal code sharing - instead of re-importing through the plugin SDK: - - ```typescript - // api.ts — public exports for this plugin - export { MyConfig } from "./src/config.js"; - export { MyRuntime } from "./src/runtime.js"; - - // runtime-api.ts — internal-only exports - export { internalHelper } from "./src/helpers.js"; - ``` - - - Never import your own plugin back through its published SDK path from - production files. Route internal imports through local files like `./api.ts` - or `./runtime-api.ts`. The SDK path is for external consumers only. - - - - - - Create `openclaw.plugin.json` in your plugin root: - - ```json - { - "id": "my-plugin", - "kind": "provider", - "name": "My Plugin", - "description": "Adds My Provider to OpenClaw" - } - ``` - - For channel plugins, set `"kind": "channel"` and add `"channels": ["my-channel"]`. - - See [Plugin Manifest](/plugins/manifest) for the full schema. - - - - - **External plugins:** run your own test suite against the plugin SDK contracts. - - **In-repo plugins:** OpenClaw runs contract tests against all registered plugins: - - ```bash - pnpm test:contracts:channels # channel plugins - pnpm test:contracts:plugins # provider plugins - ``` - - For unit tests, import test helpers from the testing surface: - - ```typescript - import { createTestRuntime } from "openclaw/plugin-sdk/testing"; - ``` - - - - - **External plugins:** publish to npm, then install: - - ```bash - npm publish - openclaw plugins install @myorg/openclaw-my-plugin - ``` - - **In-repo plugins:** place the plugin under `extensions/` and it is - automatically discovered during build. - - Users can browse and install community plugins with: - - ```bash - openclaw plugins search - openclaw plugins install - ``` - - - - -## Lint enforcement (in-repo plugins) - -Three scripts enforce SDK boundaries for plugins in the OpenClaw repository: - -1. **No monolithic root imports** — `openclaw/plugin-sdk` root is rejected -2. **No direct src/ imports** — plugins cannot import `../../src/` directly -3. **No self-imports** — plugins cannot import their own `plugin-sdk/\` subpath - -Run `pnpm check` to verify all boundaries before committing. - -External plugins are not subject to these lint rules, but following the same -patterns is strongly recommended. - -## Pre-submission checklist - -**package.json** has correct `openclaw` metadata -Entry point uses `defineChannelPluginEntry` or `definePluginEntry` -All imports use focused `plugin-sdk/\` paths -Internal imports use local modules, not SDK self-imports -`openclaw.plugin.json` manifest is present and valid -Tests pass -`pnpm check` passes (in-repo plugins) - -## Related - -- [Plugin SDK Migration](/plugins/sdk-migration) — migrating from the deprecated compat import -- [Plugin Architecture](/plugins/architecture) — internals and capability model -- [Plugin Manifest](/plugins/manifest) — full manifest schema -- [Plugin Agent Tools](/plugins/agent-tools) — adding agent tools in a plugin -- [Community Plugins](/plugins/community) — listing and quality bar +This page has moved to [Building Plugins](/plugins/building-plugins). diff --git a/docs/plugins/building-plugins.md b/docs/plugins/building-plugins.md new file mode 100644 index 00000000000..026ac4492de --- /dev/null +++ b/docs/plugins/building-plugins.md @@ -0,0 +1,309 @@ +--- +title: "Building Plugins" +sidebarTitle: "Building Plugins" +summary: "Step-by-step guide for creating OpenClaw plugins with any combination of capabilities" +read_when: + - You want to create a new OpenClaw plugin + - You need to understand the plugin SDK import patterns + - 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. A single plugin +can register multiple capabilities. + +OpenClaw encourages **external plugin development**. You do not need to add your +plugin to the OpenClaw repository. Publish your plugin on npm, and users install +it with `openclaw plugins install `. OpenClaw also maintains a set of +core plugins in-repo, but the plugin system is designed for independent ownership +and distribution. + +## Prerequisites + +- Node >= 22 and a package manager (npm or pnpm) +- Familiarity with TypeScript (ESM) +- For in-repo plugins: OpenClaw repository cloned and `pnpm install` done + +## Plugin capabilities + +A plugin can register one or more capabilities. The capability you register +determines what your plugin provides to OpenClaw: + +| Capability | Registration method | What it adds | +| ------------------- | --------------------------------------------- | ------------------------------ | +| Text inference | `api.registerProvider(...)` | Model provider (LLM) | +| Channel / messaging | `api.registerChannel(...)` | Chat channel (e.g. Slack, IRC) | +| Speech | `api.registerSpeechProvider(...)` | Text-to-speech / STT | +| Media understanding | `api.registerMediaUnderstandingProvider(...)` | Image/audio/video analysis | +| Image generation | `api.registerImageGenerationProvider(...)` | Image generation | +| Web search | `api.registerWebSearchProvider(...)` | Web search provider | +| Agent tools | `api.registerTool(...)` | Tools callable by the agent | + +A plugin that registers zero capabilities but provides hooks or services is a +**hook-only** plugin. That pattern is still supported. + +## Plugin structure + +Plugins follow this layout (whether in-repo or standalone): + +``` +my-plugin/ +├── package.json # npm metadata + openclaw config +├── openclaw.plugin.json # Plugin manifest +├── index.ts # Entry point +├── setup-entry.ts # Setup wizard (optional) +├── api.ts # Public exports (optional) +├── runtime-api.ts # Internal exports (optional) +└── src/ + ├── provider.ts # Capability implementation + ├── runtime.ts # Runtime wiring + └── *.test.ts # Colocated tests +``` + +## Create a plugin + + + + Create `package.json` with the `openclaw` metadata block. The structure + depends on what capabilities your plugin provides. + + **Channel plugin example:** + + ```json + { + "name": "@myorg/openclaw-my-channel", + "version": "1.0.0", + "type": "module", + "openclaw": { + "extensions": ["./index.ts"], + "channel": { + "id": "my-channel", + "label": "My Channel", + "blurb": "Short description of the channel." + } + } + } + ``` + + **Provider plugin example:** + + ```json + { + "name": "@myorg/openclaw-my-provider", + "version": "1.0.0", + "type": "module", + "openclaw": { + "extensions": ["./index.ts"], + "providers": ["my-provider"] + } + } + ``` + + The `openclaw` field tells the plugin system what your plugin provides. + A plugin can declare both `channel` and `providers` if it provides multiple + capabilities. + + + + + The entry point registers your capabilities with the plugin API. + + **Channel plugin:** + + ```typescript + import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; + + export default defineChannelPluginEntry({ + id: "my-channel", + name: "My Channel", + description: "Connects OpenClaw to My Channel", + plugin: { + // Channel adapter implementation + }, + }); + ``` + + **Provider plugin:** + + ```typescript + import { definePluginEntry } from "openclaw/plugin-sdk/core"; + + export default definePluginEntry({ + id: "my-provider", + name: "My Provider", + register(api) { + api.registerProvider({ + // Provider implementation + }); + }, + }); + ``` + + **Multi-capability plugin** (provider + tool): + + ```typescript + import { definePluginEntry } from "openclaw/plugin-sdk/core"; + + export default definePluginEntry({ + id: "my-plugin", + name: "My Plugin", + register(api) { + api.registerProvider({ /* ... */ }); + api.registerTool({ /* ... */ }); + api.registerImageGenerationProvider({ /* ... */ }); + }, + }); + ``` + + Use `defineChannelPluginEntry` for channel plugins and `definePluginEntry` + for everything else. A single plugin can register as many capabilities as needed. + + + + + Always import from specific `openclaw/plugin-sdk/\` paths. The old + monolithic import is deprecated (see [SDK Migration](/plugins/sdk-migration)). + + ```typescript + // Correct: focused subpaths + import { definePluginEntry } from "openclaw/plugin-sdk/core"; + import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store"; + import { buildOauthProviderAuthResult } from "openclaw/plugin-sdk/provider-oauth"; + + // Wrong: monolithic root (lint will reject this) + import { ... } from "openclaw/plugin-sdk"; + ``` + + + | Subpath | Purpose | + | --- | --- | + | `plugin-sdk/core` | Plugin entry definitions and base types | + | `plugin-sdk/channel-setup` | Setup wizard adapters | + | `plugin-sdk/channel-pairing` | DM pairing primitives | + | `plugin-sdk/channel-reply-pipeline` | Reply prefix + typing wiring | + | `plugin-sdk/channel-config-schema` | Config schema builders | + | `plugin-sdk/channel-policy` | Group/DM policy helpers | + | `plugin-sdk/secret-input` | Secret input parsing/helpers | + | `plugin-sdk/webhook-ingress` | Webhook request/target helpers | + | `plugin-sdk/runtime-store` | Persistent plugin storage | + | `plugin-sdk/allow-from` | Allowlist resolution | + | `plugin-sdk/reply-payload` | Message reply types | + | `plugin-sdk/provider-oauth` | OAuth login + PKCE helpers | + | `plugin-sdk/provider-onboard` | Provider onboarding config patches | + | `plugin-sdk/testing` | Test utilities | + + + Use the narrowest subpath that matches the job. + + + + + Within your plugin, create local module files for internal code sharing + instead of re-importing through the plugin SDK: + + ```typescript + // api.ts — public exports for this plugin + export { MyConfig } from "./src/config.js"; + export { MyRuntime } from "./src/runtime.js"; + + // runtime-api.ts — internal-only exports + export { internalHelper } from "./src/helpers.js"; + ``` + + + Never import your own plugin back through its published SDK path from + production files. Route internal imports through local files like `./api.ts` + or `./runtime-api.ts`. The SDK path is for external consumers only. + + + + + + Create `openclaw.plugin.json` in your plugin root: + + ```json + { + "id": "my-plugin", + "kind": "provider", + "name": "My Plugin", + "description": "Adds My Provider to OpenClaw" + } + ``` + + For channel plugins, set `"kind": "channel"` and add `"channels": ["my-channel"]`. + + See [Plugin Manifest](/plugins/manifest) for the full schema. + + + + + **External plugins:** run your own test suite against the plugin SDK contracts. + + **In-repo plugins:** OpenClaw runs contract tests against all registered plugins: + + ```bash + pnpm test:contracts:channels # channel plugins + pnpm test:contracts:plugins # provider plugins + ``` + + For unit tests, import test helpers from the testing surface: + + ```typescript + import { createTestRuntime } from "openclaw/plugin-sdk/testing"; + ``` + + + + + **External plugins:** publish to npm, then install: + + ```bash + npm publish + openclaw plugins install @myorg/openclaw-my-plugin + ``` + + **In-repo plugins:** place the plugin under `extensions/` and it is + automatically discovered during build. + + Users can browse and install community plugins with: + + ```bash + openclaw plugins search + openclaw plugins install + ``` + + + + +## Lint enforcement (in-repo plugins) + +Three scripts enforce SDK boundaries for plugins in the OpenClaw repository: + +1. **No monolithic root imports** — `openclaw/plugin-sdk` root is rejected +2. **No direct src/ imports** — plugins cannot import `../../src/` directly +3. **No self-imports** — plugins cannot import their own `plugin-sdk/\` subpath + +Run `pnpm check` to verify all boundaries before committing. + +External plugins are not subject to these lint rules, but following the same +patterns is strongly recommended. + +## Pre-submission checklist + +**package.json** has correct `openclaw` metadata +Entry point uses `defineChannelPluginEntry` or `definePluginEntry` +All imports use focused `plugin-sdk/\` paths +Internal imports use local modules, not SDK self-imports +`openclaw.plugin.json` manifest is present and valid +Tests pass +`pnpm check` passes (in-repo plugins) + +## Related + +- [Plugin SDK Migration](/plugins/sdk-migration) — migrating from the deprecated compat import +- [Plugin Architecture](/plugins/architecture) — internals and capability model +- [Plugin Manifest](/plugins/manifest) — full manifest schema +- [Plugin Agent Tools](/plugins/agent-tools) — adding agent tools in a plugin +- [Community Plugins](/plugins/community) — listing and quality bar diff --git a/docs/plugins/sdk-migration.md b/docs/plugins/sdk-migration.md index fb745e46e91..83970720578 100644 --- a/docs/plugins/sdk-migration.md +++ b/docs/plugins/sdk-migration.md @@ -1,121 +1,117 @@ --- title: "Plugin SDK Migration" sidebarTitle: "SDK Migration" -summary: "Migrate from openclaw/plugin-sdk/compat to focused subpath imports" +summary: "Migrate from the deprecated openclaw/plugin-sdk/compat import to focused subpath imports" read_when: - You see the OPENCLAW_PLUGIN_SDK_COMPAT_DEPRECATED warning - - You are updating a plugin from the monolithic plugin-sdk import to scoped subpaths + - You are updating a plugin from the monolithic import to scoped subpaths - You maintain an external OpenClaw plugin --- # Plugin SDK Migration -OpenClaw is migrating from a single monolithic `openclaw/plugin-sdk/compat` barrel -to **focused subpath imports** (`openclaw/plugin-sdk/\`). This page explains -what changed, why, and how to migrate. +The `openclaw/plugin-sdk/compat` import is deprecated. All plugins should use +**focused subpath imports** (`openclaw/plugin-sdk/\`) instead. -## Why this change + + 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. + -The monolithic compat entry re-exported everything from a single entry point. -This caused: +## Why this changed -- **Slow startup**: importing one helper pulled in dozens of unrelated modules. -- **Circular dependency risk**: broad re-exports made it easy to create import cycles. -- **Unclear API surface**: no way to tell which exports were stable vs internal. +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. Focused subpaths fix all three: each subpath is a small, self-contained module with a clear purpose. -## What triggers the warning +## Migration steps -If your plugin imports from the compat entry, you will see: + + + Search your plugin for imports from the compat path: -``` -[OPENCLAW_PLUGIN_SDK_COMPAT_DEPRECATED] Warning: openclaw/plugin-sdk/compat is -deprecated for new plugins. Migrate to focused openclaw/plugin-sdk/\ imports. -``` + ```bash + grep -r "plugin-sdk/compat" my-plugin/ + ``` -The compat entry still works at runtime. This is a deprecation warning, not an -error. But new plugins **must not** use it, and existing plugins should migrate -before compat is removed. + -## How to migrate + + Each export maps to a specific subpath. Replace the import source: -### Step 1: Find compat imports + ```typescript + // Before (deprecated) + import { + createChannelReplyPipeline, + createPluginRuntimeStore, + resolveControlCommandGate, + } from "openclaw/plugin-sdk/compat"; -Search your extension for imports from the compat path: + // After (focused subpaths) + 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"; + ``` -```bash -grep -r "plugin-sdk/compat" extensions/my-plugin/ -``` + See the [subpath reference](#subpath-reference) below for the full mapping. -### Step 2: Replace with focused subpaths + -Each export from compat maps to a specific subpath. Replace the import source: - -```typescript -// Before (compat entry) -import { - createChannelReplyPipeline, - createPluginRuntimeStore, - resolveControlCommandGate, -} from "openclaw/plugin-sdk/compat"; - -// After (focused subpaths) -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"; -``` - -### Step 3: Verify - -Run the build and tests: - -```bash -pnpm build -pnpm test -- extensions/my-plugin/ -``` + + ```bash + pnpm build + pnpm test -- my-plugin/ + ``` + + ## Subpath reference -| Subpath | Purpose | Key exports | -| ----------------------------------- | ------------------------------------ | ---------------------------------------------------------------------- | -| `plugin-sdk/core` | Plugin entry definitions, base types | `defineChannelPluginEntry`, `definePluginEntry` | -| `plugin-sdk/channel-setup` | Setup wizard adapters | `createOptionalChannelSetupSurface` | -| `plugin-sdk/channel-pairing` | DM pairing primitives | `createChannelPairingController` | -| `plugin-sdk/channel-reply-pipeline` | Reply prefix + typing wiring | `createChannelReplyPipeline` | -| `plugin-sdk/channel-config-helpers` | Config adapter factories | `createHybridChannelConfigAdapter`, `createScopedChannelConfigAdapter` | -| `plugin-sdk/channel-config-schema` | Config schema builders | Channel config schema types | -| `plugin-sdk/channel-policy` | Group/DM policy resolution | `resolveChannelGroupRequireMention` | -| `plugin-sdk/channel-lifecycle` | Account status tracking | `createAccountStatusSink` | -| `plugin-sdk/channel-runtime` | Runtime wiring helpers | Channel runtime utilities | -| `plugin-sdk/channel-send-result` | Send result types | Reply result types | -| `plugin-sdk/runtime-store` | Persistent plugin storage | `createPluginRuntimeStore` | -| `plugin-sdk/allow-from` | Allowlist formatting | `formatAllowFromLowercase`, `formatNormalizedAllowFromEntries` | -| `plugin-sdk/allowlist-resolution` | Allowlist input mapping | `mapAllowlistResolutionInputs` | -| `plugin-sdk/command-auth` | Command gating | `resolveControlCommandGate` | -| `plugin-sdk/secret-input` | Secret input parsing | Secret input helpers | -| `plugin-sdk/webhook-ingress` | Webhook request helpers | Webhook target utilities | -| `plugin-sdk/reply-payload` | Message reply types | Reply payload types | -| `plugin-sdk/provider-onboard` | Provider onboarding patches | Onboarding config helpers | -| `plugin-sdk/keyed-async-queue` | Ordered async queue | `KeyedAsyncQueue` | -| `plugin-sdk/testing` | Test utilities | Test helpers and mocks | + + | Subpath | Purpose | Key exports | + | --- | --- | --- | + | `plugin-sdk/core` | Plugin entry definitions, base types | `defineChannelPluginEntry`, `definePluginEntry` | + | `plugin-sdk/channel-setup` | Setup wizard adapters | `createOptionalChannelSetupSurface` | + | `plugin-sdk/channel-pairing` | DM pairing primitives | `createChannelPairingController` | + | `plugin-sdk/channel-reply-pipeline` | Reply prefix + typing wiring | `createChannelReplyPipeline` | + | `plugin-sdk/channel-config-helpers` | Config adapter factories | `createHybridChannelConfigAdapter` | + | `plugin-sdk/channel-config-schema` | Config schema builders | Channel config schema types | + | `plugin-sdk/channel-policy` | Group/DM policy resolution | `resolveChannelGroupRequireMention` | + | `plugin-sdk/channel-lifecycle` | Account status tracking | `createAccountStatusSink` | + | `plugin-sdk/channel-runtime` | Runtime wiring helpers | Channel runtime utilities | + | `plugin-sdk/channel-send-result` | Send result types | Reply result types | + | `plugin-sdk/runtime-store` | Persistent plugin storage | `createPluginRuntimeStore` | + | `plugin-sdk/allow-from` | Allowlist formatting | `formatAllowFromLowercase` | + | `plugin-sdk/allowlist-resolution` | Allowlist input mapping | `mapAllowlistResolutionInputs` | + | `plugin-sdk/command-auth` | Command gating | `resolveControlCommandGate` | + | `plugin-sdk/secret-input` | Secret input parsing | Secret input helpers | + | `plugin-sdk/webhook-ingress` | Webhook request helpers | Webhook target utilities | + | `plugin-sdk/reply-payload` | Message reply types | Reply payload types | + | `plugin-sdk/provider-onboard` | Provider onboarding patches | Onboarding config helpers | + | `plugin-sdk/keyed-async-queue` | Ordered async queue | `KeyedAsyncQueue` | + | `plugin-sdk/testing` | Test utilities | Test helpers and mocks | + -Use the narrowest subpath that has what you need. If you cannot find an export, +Use the narrowest subpath that matches the job. If you cannot find an export, check the source at `src/plugin-sdk/` or ask in Discord. -## Compat barrel removal timeline +## Removal timeline -- **Now**: compat entry emits a deprecation warning at runtime. -- **Next major release**: compat entry will be removed. Plugins still using it will - fail to import. +| When | What happens | +| ---------------------- | --------------------------------------------------------------- | +| **Now** | Compat import emits a runtime deprecation warning | +| **Next major release** | Compat import will be removed; plugins still using it will fail | -Bundled plugins (under `extensions/`) have already been migrated. External plugins -should migrate before the next major release. +All core plugins have already been migrated. External plugins should migrate +before the next major release. ## Suppressing the warning temporarily -If you need to suppress the warning while migrating: +Set this environment variable while you work on migrating: ```bash OPENCLAW_SUPPRESS_PLUGIN_SDK_COMPAT_WARNING=1 openclaw gateway run @@ -123,23 +119,8 @@ OPENCLAW_SUPPRESS_PLUGIN_SDK_COMPAT_WARNING=1 openclaw gateway run This is a temporary escape hatch, not a permanent solution. -## Internal barrel pattern - -Within your extension, use local barrel files (`api.ts`, `runtime-api.ts`) for -internal code sharing instead of importing through the plugin SDK: - -```typescript -// extensions/my-plugin/api.ts — public contract for this extension -export { MyConfig } from "./src/config.js"; -export { MyRuntime } from "./src/runtime.js"; -``` - -Never import your own extension back through `openclaw/plugin-sdk/\` -from production files. That path is for external consumers only. See -[Building Extensions](/plugins/building-extensions#step-4-use-local-barrels-for-internal-imports). - ## Related -- [Building Extensions](/plugins/building-extensions) +- [Building Plugins](/plugins/building-plugins) - [Plugin Architecture](/plugins/architecture) - [Plugin Manifest](/plugins/manifest) diff --git a/docs/start/hubs.md b/docs/start/hubs.md index 7e530f769b5..8ccb2d56c66 100644 --- a/docs/start/hubs.md +++ b/docs/start/hubs.md @@ -164,7 +164,7 @@ Use these hubs to discover every page, including deep dives and reference docs t ## Extensions + plugins - [Plugins overview](/tools/plugin) -- [Building extensions](/plugins/building-extensions) +- [Building plugins](/plugins/building-plugins) - [Plugin manifest](/plugins/manifest) - [Agent tools](/plugins/agent-tools) - [Plugin bundles](/plugins/bundles) diff --git a/docs/tools/index.md b/docs/tools/index.md index 075971d6877..15b8bb24a5f 100644 --- a/docs/tools/index.md +++ b/docs/tools/index.md @@ -1,96 +1,89 @@ --- -summary: "Agent tool surface for OpenClaw (browser, canvas, nodes, message, cron) replacing legacy `openclaw-*` skills" +summary: "OpenClaw tools and plugins overview: what the agent can do and how to extend it" read_when: - - Adding or modifying agent tools - - Retiring or changing `openclaw-*` skills -title: "Tools" + - You want to understand what tools OpenClaw provides + - You need to configure, allow, or deny tools + - You are deciding between built-in tools, skills, and plugins +title: "Tools and Plugins" --- -# Tools (OpenClaw) +# Tools and Plugins -OpenClaw exposes **first-class agent tools** for browser, canvas, nodes, and cron. -These replace the old `openclaw-*` skills: the tools are typed, no shelling, -and the agent should rely on them directly. +OpenClaw gives the agent a set of **tools** it can call during a conversation. +Tools are how the agent reads files, runs commands, browses the web, sends +messages, and interacts with devices. Everything the agent does beyond generating +text happens through tools. -## Disabling tools +## How it all fits together -You can globally allow/deny tools via `tools.allow` / `tools.deny` in `openclaw.json` -(deny wins). This prevents disallowed tools from being sent to model providers. + + + Core tools shipped with OpenClaw: exec, browser, web search, file I/O, + messaging, cron, canvas, and nodes. + + + Markdown instructions that teach the agent how and when to use tools. + Skills ship inside plugins or live in your workspace. + + + Packages that add new capabilities: channels, model providers, tools, + skills, or any combination. Published on npm and installed with the CLI. + + + Hooks, cron jobs, heartbeats, webhooks, and scheduled tasks that run + without manual messages. + + + +## Tool configuration + +### Allow and deny lists + +Control which tools the agent can call via `tools.allow` / `tools.deny` in +config. Deny always wins over allow. ```json5 { - tools: { deny: ["browser"] }, + tools: { + allow: ["group:fs", "browser", "web_search"], + deny: ["exec"], + }, } ``` -Notes: +### Tool profiles -- Matching is case-insensitive. -- `*` wildcards are supported (`"*"` means all tools). -- If `tools.allow` only references unknown or unloaded plugin tool names, OpenClaw logs a warning and ignores the allowlist so core tools stay available. - -## Tool profiles (base allowlist) - -`tools.profile` sets a **base tool allowlist** before `tools.allow`/`tools.deny`. +`tools.profile` sets a base allowlist before `allow`/`deny` is applied. Per-agent override: `agents.list[].tools.profile`. -Profiles: +| Profile | What it includes | +| ----------- | ------------------------------------------- | +| `full` | All tools (default) | +| `coding` | File I/O, runtime, sessions, memory, image | +| `messaging` | Messaging, session list/history/send/status | +| `minimal` | `session_status` only | -- `minimal`: `session_status` only -- `coding`: `group:fs`, `group:runtime`, `group:sessions`, `group:memory`, `image` -- `messaging`: `group:messaging`, `sessions_list`, `sessions_history`, `sessions_send`, `session_status` -- `full`: no restriction (same as unset) +### Tool groups -Example (messaging-only by default, allow Slack + Discord tools too): +Use `group:*` shorthands in allow/deny lists: -```json5 -{ - tools: { - profile: "messaging", - allow: ["slack", "discord"], - }, -} -``` +| Group | Tools | +| ------------------ | ------------------------------------------------------------------------------ | +| `group:runtime` | exec, bash, process | +| `group:fs` | read, write, edit, apply_patch | +| `group:sessions` | sessions_list, sessions_history, sessions_send, sessions_spawn, session_status | +| `group:memory` | memory_search, memory_get | +| `group:web` | web_search, web_fetch | +| `group:ui` | browser, canvas | +| `group:automation` | cron, gateway | +| `group:messaging` | message | +| `group:nodes` | nodes | +| `group:openclaw` | All built-in OpenClaw tools (excludes plugin tools) | -Example (coding profile, but deny exec/process everywhere): +### Provider-specific restrictions -```json5 -{ - tools: { - profile: "coding", - deny: ["group:runtime"], - }, -} -``` - -Example (global coding profile, messaging-only support agent): - -```json5 -{ - tools: { profile: "coding" }, - agents: { - list: [ - { - id: "support", - tools: { profile: "messaging", allow: ["slack"] }, - }, - ], - }, -} -``` - -## Provider-specific tool policy - -Use `tools.byProvider` to **further restrict** tools for specific providers -(or a single `provider/model`) without changing your global defaults. -Per-agent override: `agents.list[].tools.byProvider`. - -This is applied **after** the base tool profile and **before** allow/deny lists, -so it can only narrow the tool set. -Provider keys accept either `provider` (e.g. `google-antigravity`) or -`provider/model` (e.g. `openai/gpt-5.2`). - -Example (keep global coding profile, but minimal tools for Google Antigravity): +Use `tools.byProvider` to restrict tools for specific providers without +changing global defaults: ```json5 { @@ -103,514 +96,43 @@ Example (keep global coding profile, but minimal tools for Google Antigravity): } ``` -Example (provider/model-specific allowlist for a flaky endpoint): - -```json5 -{ - tools: { - allow: ["group:fs", "group:runtime", "sessions_list"], - byProvider: { - "openai/gpt-5.2": { allow: ["group:fs", "sessions_list"] }, - }, - }, -} -``` - -Example (agent-specific override for a single provider): - -```json5 -{ - agents: { - list: [ - { - id: "support", - tools: { - byProvider: { - "google-antigravity": { allow: ["message", "sessions_list"] }, - }, - }, - }, - ], - }, -} -``` - -## Tool groups (shorthands) - -Tool policies (global, agent, sandbox) support `group:*` entries that expand to multiple tools. -Use these in `tools.allow` / `tools.deny`. - -Available groups: - -- `group:runtime`: `exec`, `bash`, `process` -- `group:fs`: `read`, `write`, `edit`, `apply_patch` -- `group:sessions`: `sessions_list`, `sessions_history`, `sessions_send`, `sessions_spawn`, `session_status` -- `group:memory`: `memory_search`, `memory_get` -- `group:web`: `web_search`, `web_fetch` -- `group:ui`: `browser`, `canvas` -- `group:automation`: `cron`, `gateway` -- `group:messaging`: `message` -- `group:nodes`: `nodes` -- `group:openclaw`: all built-in OpenClaw tools (excludes provider plugins) - -Example (allow only file tools + browser): - -```json5 -{ - tools: { - allow: ["group:fs", "browser"], - }, -} -``` - -## Plugins + tools - -Plugins can register **additional tools** (and CLI commands) beyond the core set. -See [Plugins](/tools/plugin) for install + config, and [Skills](/tools/skills) for how -tool usage guidance is injected into prompts. Some plugins ship their own skills -alongside tools (for example, the voice-call plugin). - -Optional plugin tools: - -- [Lobster](/tools/lobster): typed workflow runtime with resumable approvals (requires the Lobster CLI on the gateway host). -- [LLM Task](/tools/llm-task): JSON-only LLM step for structured workflow output (optional schema validation). -- [Diffs](/tools/diffs): read-only diff viewer and PNG or PDF file renderer for before/after text or unified patches. - -## Tool inventory - -### `apply_patch` - -Apply structured patches across one or more files. Use for multi-hunk edits. -Experimental: enable via `tools.exec.applyPatch.enabled` (OpenAI models only). -`tools.exec.applyPatch.workspaceOnly` defaults to `true` (workspace-contained). Set it to `false` only if you intentionally want `apply_patch` to write/delete outside the workspace directory. - -### `exec` - -Run shell commands in the workspace. - -Core parameters: - -- `command` (required) -- `yieldMs` (auto-background after timeout, default 10000) -- `background` (immediate background) -- `timeout` (seconds; kills the process if exceeded, default 1800) -- `elevated` (bool; run on host if elevated mode is enabled/allowed; only changes behavior when the agent is sandboxed) -- `host` (`sandbox | gateway | node`) -- `security` (`deny | allowlist | full`) -- `ask` (`off | on-miss | always`) -- `node` (node id/name for `host=node`) -- Need a real TTY? Set `pty: true`. - -Notes: - -- Returns `status: "running"` with a `sessionId` when backgrounded. -- Use `process` to poll/log/write/kill/clear background sessions. -- If `process` is disallowed, `exec` runs synchronously and ignores `yieldMs`/`background`. -- `elevated` is gated by `tools.elevated` plus any `agents.list[].tools.elevated` override (both must allow) and is an alias for `host=gateway` + `security=full`. -- `elevated` only changes behavior when the agent is sandboxed (otherwise it’s a no-op). -- `host=node` can target a macOS companion app or a headless node host (`openclaw node run`). -- gateway/node approvals and allowlists: [Exec approvals](/tools/exec-approvals). - -### `process` - -Manage background exec sessions. - -Core actions: - -- `list`, `poll`, `log`, `write`, `kill`, `clear`, `remove` - -Notes: - -- `poll` returns new output and exit status when complete. -- `log` supports line-based `offset`/`limit` (omit `offset` to grab the last N lines). -- `process` is scoped per agent; sessions from other agents are not visible. - -### `loop-detection` (tool-call loop guardrails) - -OpenClaw tracks recent tool-call history and blocks or warns when it detects repetitive no-progress loops. -Enable with `tools.loopDetection.enabled: true` (default is `false`). - -```json5 -{ - tools: { - loopDetection: { - enabled: true, - warningThreshold: 10, - criticalThreshold: 20, - globalCircuitBreakerThreshold: 30, - historySize: 30, - detectors: { - genericRepeat: true, - knownPollNoProgress: true, - pingPong: true, - }, - }, - }, -} -``` - -- `genericRepeat`: repeated same tool + same params call pattern. -- `knownPollNoProgress`: repeating poll-like tools with identical outputs. -- `pingPong`: alternating `A/B/A/B` no-progress patterns. -- Per-agent override: `agents.list[].tools.loopDetection`. - -### `web_search` - -Search the web using Brave, Firecrawl, Gemini, Grok, Kimi, Perplexity, or Tavily. - -Core parameters: - -- `query` (required) -- `count` (1–10; default from `tools.web.search.maxResults`) - -Notes: - -- Requires an API key for the chosen provider (recommended: `openclaw configure --section web`). -- Enable via `tools.web.search.enabled`. -- Responses are cached (default 15 min). -- See [Web tools](/tools/web) for setup. - -### `web_fetch` - -Fetch and extract readable content from a URL (HTML → markdown/text). - -Core parameters: - -- `url` (required) -- `extractMode` (`markdown` | `text`) -- `maxChars` (truncate long pages) - -Notes: - -- Enable via `tools.web.fetch.enabled`. -- `maxChars` is clamped by `tools.web.fetch.maxCharsCap` (default 50000). -- Responses are cached (default 15 min). -- For JS-heavy sites, prefer the browser tool. -- See [Web tools](/tools/web) for setup. -- See [Firecrawl](/tools/firecrawl) for the optional anti-bot fallback. - -### `browser` - -Control the dedicated OpenClaw-managed browser. - -Core actions: - -- `status`, `start`, `stop`, `tabs`, `open`, `focus`, `close` -- `snapshot` (aria/ai) -- `screenshot` (returns image block + `MEDIA:`) -- `act` (UI actions: click/type/press/hover/drag/select/fill/resize/wait/evaluate) -- `navigate`, `console`, `pdf`, `upload`, `dialog` - -Profile management: - -- `profiles` — list all browser profiles with status -- `create-profile` — create new profile with auto-allocated port (or `cdpUrl`) -- `delete-profile` — stop browser, delete user data, remove from config (local only) -- `reset-profile` — kill orphan process on profile's port (local only) - -Common parameters: - -- `profile` (optional; defaults to `browser.defaultProfile`) -- `target` (`sandbox` | `host` | `node`) -- `node` (optional; picks a specific node id/name) - Notes: -- Requires `browser.enabled=true` (default is `true`; set `false` to disable). -- All actions accept optional `profile` parameter for multi-instance support. -- Omit `profile` for the safe default: isolated OpenClaw-managed browser (`openclaw`). -- Use `profile="user"` for the real local host browser when existing logins/cookies matter and the user is present to click/approve any attach prompt. -- `profile="user"` is host-only; do not combine it with sandbox/node targets. -- When `profile` is omitted, uses `browser.defaultProfile` (defaults to `openclaw`). -- Profile names: lowercase alphanumeric + hyphens only (max 64 chars). -- Port range: 18800-18899 (~100 profiles max). -- Remote profiles are attach-only (no start/stop/reset). -- If a browser-capable node is connected, the tool may auto-route to it (unless you pin `target`). -- `snapshot` defaults to `ai` when Playwright is installed; use `aria` for the accessibility tree. -- `snapshot` also supports role-snapshot options (`interactive`, `compact`, `depth`, `selector`) which return refs like `e12`. -- `act` requires `ref` from `snapshot` (numeric `12` from AI snapshots, or `e12` from role snapshots); use `evaluate` for rare CSS selector needs. -- Avoid `act` → `wait` by default; use it only in exceptional cases (no reliable UI state to wait on). -- `upload` can optionally pass a `ref` to auto-click after arming. -- `upload` also supports `inputRef` (aria ref) or `element` (CSS selector) to set `` directly. - -### `canvas` - -Drive the node Canvas (present, eval, snapshot, A2UI). - -Core actions: - -- `present`, `hide`, `navigate`, `eval` -- `snapshot` (returns image block + `MEDIA:`) -- `a2ui_push`, `a2ui_reset` - -Notes: - -- Uses gateway `node.invoke` under the hood. -- If no `node` is provided, the tool picks a default (single connected node or local mac node). -- A2UI is v0.8 only (no `createSurface`); the CLI rejects v0.9 JSONL with line errors. -- Quick smoke: `openclaw nodes canvas a2ui push --node --text "Hello from A2UI"`. - -### `nodes` - -Discover and target paired nodes; send notifications; capture camera/screen. - -Core actions: - -- `status`, `describe` -- `pending`, `approve`, `reject` (pairing) -- `notify` (macOS `system.notify`) -- `run` (macOS `system.run`) -- `camera_list`, `camera_snap`, `camera_clip`, `screen_record` -- `location_get`, `notifications_list`, `notifications_action` -- `device_status`, `device_info`, `device_permissions`, `device_health` - -Notes: - -- Camera/screen commands require the node app to be foregrounded. -- Images return image blocks + `MEDIA:`. -- Videos return `FILE:` (mp4). -- Location returns a JSON payload (lat/lon/accuracy/timestamp). -- `run` params: `command` argv array; optional `cwd`, `env` (`KEY=VAL`), `commandTimeoutMs`, `invokeTimeoutMs`, `needsScreenRecording`. - -Example (`run`): - -```json -{ - "action": "run", - "node": "office-mac", - "command": ["echo", "Hello"], - "env": ["FOO=bar"], - "commandTimeoutMs": 12000, - "invokeTimeoutMs": 45000, - "needsScreenRecording": false -} -``` - -### `image` - -Analyze an image with the configured image model. - -Core parameters: - -- `image` (required path or URL) -- `prompt` (optional; defaults to "Describe the image.") -- `model` (optional override) -- `maxBytesMb` (optional size cap) - -Notes: - -- Only available when `agents.defaults.imageModel` is configured (primary or fallbacks), or when an implicit image model can be inferred from your default model + configured auth (best-effort pairing). -- Uses the image model directly (independent of the main chat model). - -### `image_generate` - -Generate one or more images with the configured or inferred image-generation model. - -Core parameters: - -- `action` (optional: `generate` or `list`; default `generate`) -- `prompt` (required) -- `image` or `images` (optional reference image path/URL for edit mode) -- `model` (optional provider/model override) -- `size` (optional size hint) -- `resolution` (optional `1K|2K|4K` hint) -- `count` (optional, `1-4`, default `1`) - -Notes: - -- Available when `agents.defaults.imageGenerationModel` is configured, or when OpenClaw can infer a compatible image-generation default from your enabled providers plus available auth. -- Explicit `agents.defaults.imageGenerationModel` still wins over any inferred default. -- Use `action: "list"` to inspect registered providers, default models, supported model ids, sizes, resolutions, and edit support. -- Returns local `MEDIA:` lines so channels can deliver the generated files directly. -- Uses the image-generation model directly (independent of the main chat model). -- Google-backed flows, including `google/gemini-3-pro-image-preview` for the native Nano Banana-style path, support reference-image edits plus explicit `1K|2K|4K` resolution hints. -- When editing and `resolution` is omitted, OpenClaw infers a draft/final resolution from the input image size. -- This is the built-in replacement for the old `nano-banana-pro` skill workflow. Use `agents.defaults.imageGenerationModel`, not `skills.entries`, for stock image generation. - -Native example: - -```json5 -{ - agents: { - defaults: { - imageGenerationModel: { - primary: "google/gemini-3-pro-image-preview", // native Nano Banana path - fallbacks: ["fal/fal-ai/flux/dev"], - }, - }, - }, -} -``` - -### `pdf` - -Analyze one or more PDF documents. - -For full behavior, limits, config, and examples, see [PDF tool](/tools/pdf). - -### `message` - -Send messages and channel actions across Discord/Google Chat/Slack/Telegram/WhatsApp/Signal/iMessage/Microsoft Teams. - -Core actions: - -- `send` (text + optional media; Microsoft Teams also supports `card` for Adaptive Cards) -- `poll` (WhatsApp/Discord/Microsoft Teams polls) -- `react` / `reactions` / `read` / `edit` / `delete` -- `pin` / `unpin` / `list-pins` -- `permissions` -- `thread-create` / `thread-list` / `thread-reply` -- `search` -- `sticker` -- `member-info` / `role-info` -- `emoji-list` / `emoji-upload` / `sticker-upload` -- `role-add` / `role-remove` -- `channel-info` / `channel-list` -- `voice-status` -- `event-list` / `event-create` -- `timeout` / `kick` / `ban` - -Notes: - -- `send` routes WhatsApp via the Gateway; other channels go direct. -- `poll` uses the Gateway for WhatsApp and Microsoft Teams; Discord polls go direct. -- When a message tool call is bound to an active chat session, sends are constrained to that session’s target to avoid cross-context leaks. - -### `cron` - -Manage Gateway cron jobs and wakeups. - -Core actions: - -- `status`, `list` -- `add`, `update`, `remove`, `run`, `runs` -- `wake` (enqueue system event + optional immediate heartbeat) - -Notes: - -- `add` expects a full cron job object (same schema as `cron.add` RPC). -- `update` uses `{ jobId, patch }` (`id` accepted for compatibility). - -### `gateway` - -Restart or apply updates to the running Gateway process (in-place). - -Core actions: - -- `restart` (authorizes + sends `SIGUSR1` for in-process restart; `openclaw gateway` restart in-place) -- `config.schema.lookup` (inspect one config path at a time without loading the full schema into prompt context) -- `config.get` -- `config.apply` (validate + write config + restart + wake) -- `config.patch` (merge partial update + restart + wake) -- `update.run` (run update + restart + wake) - -Notes: - -- `config.schema.lookup` expects a targeted config path such as `gateway.auth` or `agents.list.*.heartbeat`. -- Paths may include slash-delimited plugin ids when addressing `plugins.entries.`, for example `plugins.entries.pack/one.config`. -- Use `delayMs` (defaults to 2000) to avoid interrupting an in-flight reply. -- `config.schema` remains available to internal Control UI flows and is not exposed through the agent `gateway` tool. -- `restart` is enabled by default; set `commands.restart: false` to disable it. - -### `sessions_list` / `sessions_history` / `sessions_send` / `sessions_spawn` / `session_status` - -List sessions, inspect transcript history, or send to another session. - -Core parameters: - -- `sessions_list`: `kinds?`, `limit?`, `activeMinutes?`, `messageLimit?` (0 = none) -- `sessions_history`: `sessionKey` (or `sessionId`), `limit?`, `includeTools?` -- `sessions_send`: `sessionKey` (or `sessionId`), `message`, `timeoutSeconds?` (0 = fire-and-forget) -- `sessions_spawn`: `task`, `label?`, `runtime?`, `agentId?`, `model?`, `thinking?`, `cwd?`, `runTimeoutSeconds?`, `thread?`, `mode?`, `cleanup?`, `sandbox?`, `streamTo?`, `attachments?`, `attachAs?` -- `session_status`: `sessionKey?` (default current; accepts `sessionId`), `model?` (`default` clears override) - -Notes: - -- `main` is the canonical direct-chat key; global/unknown are hidden. -- `messageLimit > 0` fetches last N messages per session (tool messages filtered). -- Session targeting is controlled by `tools.sessions.visibility` (default `tree`: current session + spawned subagent sessions). If you run a shared agent for multiple users, consider setting `tools.sessions.visibility: "self"` to prevent cross-session browsing. -- `sessions_send` waits for final completion when `timeoutSeconds > 0`. -- Delivery/announce happens after completion and is best-effort; `status: "ok"` confirms the agent run finished, not that the announce was delivered. -- `sessions_spawn` supports `runtime: "subagent" | "acp"` (`subagent` default). For ACP runtime behavior, see [ACP Agents](/tools/acp-agents). -- For ACP runtime, `streamTo: "parent"` routes initial-run progress summaries back to the requester session as system events instead of direct child delivery. -- `sessions_spawn` starts a sub-agent run and posts an announce reply back to the requester chat. - - Supports one-shot mode (`mode: "run"`) and persistent thread-bound mode (`mode: "session"` with `thread: true`). - - If `thread: true` and `mode` is omitted, mode defaults to `session`. - - `mode: "session"` requires `thread: true`. - - If `runTimeoutSeconds` is omitted, OpenClaw uses `agents.defaults.subagents.runTimeoutSeconds` when set; otherwise timeout defaults to `0` (no timeout). - - Discord thread-bound flows depend on `session.threadBindings.*` and `channels.discord.threadBindings.*`. - - Reply format includes `Status`, `Result`, and compact stats. - - `Result` is the assistant completion text; if missing, the latest `toolResult` is used as fallback. -- Manual completion-mode spawns send directly first, with queue fallback and retry on transient failures (`status: "ok"` means run finished, not that announce delivered). -- `sessions_spawn` supports inline file attachments for subagent runtime only (ACP rejects them). Each attachment has `name`, `content`, and optional `encoding` (`utf8` or `base64`) and `mimeType`. Files are materialized into the child workspace at `.openclaw/attachments//` with a `.manifest.json` metadata file. The tool returns a receipt with `count`, `totalBytes`, per file `sha256`, and `relDir`. Attachment content is automatically redacted from transcript persistence. - - Configure limits via `tools.sessions_spawn.attachments` (`enabled`, `maxTotalBytes`, `maxFiles`, `maxFileBytes`, `retainOnSessionKeep`). - - `attachAs.mountPath` is a reserved hint for future mount implementations. -- `sessions_spawn` is non-blocking and returns `status: "accepted"` immediately. -- ACP `streamTo: "parent"` responses may include `streamLogPath` (session-scoped `*.acp-stream.jsonl`) for tailing progress history. -- `sessions_send` runs a reply‑back ping‑pong (reply `REPLY_SKIP` to stop; max turns via `session.agentToAgent.maxPingPongTurns`, 0–5). -- After the ping‑pong, the target agent runs an **announce step**; reply `ANNOUNCE_SKIP` to suppress the announcement. -- Sandbox clamp: when the current session is sandboxed and `agents.defaults.sandbox.sessionToolsVisibility: "spawned"`, OpenClaw clamps `tools.sessions.visibility` to `tree`. - -### `agents_list` - -List agent ids that the current session may target with `sessions_spawn`. - -Notes: - -- Result is restricted to per-agent allowlists (`agents.list[].subagents.allowAgents`). -- When `["*"]` is configured, the tool includes all configured agents and marks `allowAny: true`. - -## Parameters (common) - -Gateway-backed tools (`canvas`, `nodes`, `cron`): - -- `gatewayUrl` (default `ws://127.0.0.1:18789`) -- `gatewayToken` (if auth enabled) -- `timeoutMs` - -Note: when `gatewayUrl` is set, include `gatewayToken` explicitly. Tools do not inherit config -or environment credentials for overrides, and missing explicit credentials is an error. - -Browser tool: - -- `profile` (optional; defaults to `browser.defaultProfile`) -- `target` (`sandbox` | `host` | `node`) -- `node` (optional; pin a specific node id/name) -- Troubleshooting guides: - - Linux startup/CDP issues: [Browser troubleshooting (Linux)](/tools/browser-linux-troubleshooting) - - WSL2 Gateway + Windows remote Chrome CDP: [WSL2 + Windows + remote Chrome CDP troubleshooting](/tools/browser-wsl2-windows-remote-cdp-troubleshooting) - -## Recommended agent flows - -Browser automation: - -1. `browser` → `status` / `start` -2. `snapshot` (ai or aria) -3. `act` (click/type/press) -4. `screenshot` if you need visual confirmation - -Canvas render: - -1. `canvas` → `present` -2. `a2ui_push` (optional) -3. `snapshot` - -Node targeting: - -1. `nodes` → `status` -2. `describe` on the chosen node -3. `notify` / `run` / `camera_snap` / `screen_record` - -## Safety - -- Avoid direct `system.run`; use `nodes` → `run` only with explicit user consent. -- Respect user consent for camera/screen capture. -- Use `status/describe` to ensure permissions before invoking media commands. - -## How tools are presented to the agent +## Built-in tool reference + +For the full tool-by-tool reference (parameters, actions, notes), see the +individual tool pages in the sidebar. Key tools: + +| Tool | What it does | Page | +| ---------------------------- | -------------------------------------------------------- | --------------------------------- | +| `exec` / `process` | Run shell commands, manage background processes | [Exec](/tools/exec) | +| `browser` | Control a Chromium browser (navigate, click, screenshot) | [Browser](/tools/browser) | +| `web_search` / `web_fetch` | Search the web, fetch page content | [Web](/tools/web) | +| `read` / `write` / `edit` | File I/O in the workspace | | +| `apply_patch` | Multi-hunk file patches | [Apply Patch](/tools/apply-patch) | +| `message` | Send messages across all channels | [Agent Send](/tools/agent-send) | +| `canvas` | Drive node Canvas (present, eval, snapshot) | | +| `nodes` | Discover and target paired devices | | +| `cron` / `gateway` | Manage scheduled jobs, restart gateway | | +| `image` / `image_generate` | Analyze or generate images | | +| `sessions_*` / `agents_list` | Session management, sub-agents | [Sub-agents](/tools/subagents) | + +## Plugins add more + +Plugins can register **additional tools** beyond the built-in set. Some examples: + +- [Lobster](/tools/lobster) — typed workflow runtime with resumable approvals +- [LLM Task](/tools/llm-task) — JSON-only LLM step for structured output +- [Diffs](/tools/diffs) — diff viewer and renderer +- [OpenProse](/prose) — markdown-first workflow orchestration + +Plugins can also ship **skills** alongside tools, so the agent gets both the +tool definition and the instructions for using it. See +[Building Plugins](/plugins/building-plugins) to create your own. + +## How tools reach the agent Tools are exposed in two parallel channels: -1. **System prompt text**: a human-readable list + guidance. -2. **Tool schema**: the structured function definitions sent to the model API. +1. **System prompt text** — a human-readable list with guidance (from skills) +2. **Tool schemas** — structured function definitions sent to the model API -That means the agent sees both “what tools exist” and “how to call them.” If a tool -doesn’t appear in the system prompt or the schema, the model cannot call it. +If a tool doesn't appear in either, the model cannot call it. diff --git a/docs/tools/plugin.md b/docs/tools/plugin.md index 7f1ba0fade4..9b61c2ee015 100644 --- a/docs/tools/plugin.md +++ b/docs/tools/plugin.md @@ -1,13 +1,14 @@ --- -summary: "OpenClaw plugins/extensions: discovery, config, and safety" +summary: "OpenClaw plugins: install, configure, and manage plugins that extend the gateway" read_when: - - Adding or modifying plugins/extensions - - Documenting plugin install or load rules + - Installing or configuring plugins + - Understanding plugin discovery and load rules - Working with Codex/Claude-compatible plugin bundles title: "Plugins" +sidebarTitle: "Install and Configure" --- -# Plugins (Extensions) +# Plugins ## Quick start @@ -329,7 +330,7 @@ See [Plugin manifest](/plugins/manifest) for the manifest file format. - [Plugin architecture and internals](/plugins/architecture) -- capability model, ownership model, contracts, load pipeline, runtime helpers, and developer API reference -- [Building extensions](/plugins/building-extensions) +- [Building plugins](/plugins/building-plugins) - [Plugin bundles](/plugins/bundles) - [Plugin manifest](/plugins/manifest) - [Plugin agent tools](/plugins/agent-tools)