mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-22 07:20:59 +00:00
docs: restructure Tools & Plugins section, rename building-extensions to building-plugins, rewrite tools landing page and SDK migration
This commit is contained in:
@@ -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": [
|
||||
|
||||
@@ -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 <npm-spec>`. 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
|
||||
|
||||
<Steps>
|
||||
<Step title="Create the package">
|
||||
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.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Define the entry point">
|
||||
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.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Import from focused SDK subpaths">
|
||||
Always import from specific `openclaw/plugin-sdk/\<subpath\>` 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";
|
||||
```
|
||||
|
||||
<Accordion title="Common subpaths reference">
|
||||
| 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 |
|
||||
</Accordion>
|
||||
|
||||
Use the narrowest subpath that matches the job.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Use local modules for internal imports">
|
||||
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";
|
||||
```
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add a plugin manifest">
|
||||
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.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Test your plugin">
|
||||
**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";
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Publish and install">
|
||||
**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 <query>
|
||||
openclaw plugins install <npm-spec>
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 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/\<name\>` 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
|
||||
|
||||
<Check>**package.json** has correct `openclaw` metadata</Check>
|
||||
<Check>Entry point uses `defineChannelPluginEntry` or `definePluginEntry`</Check>
|
||||
<Check>All imports use focused `plugin-sdk/\<subpath\>` paths</Check>
|
||||
<Check>Internal imports use local modules, not SDK self-imports</Check>
|
||||
<Check>`openclaw.plugin.json` manifest is present and valid</Check>
|
||||
<Check>Tests pass</Check>
|
||||
<Check>`pnpm check` passes (in-repo plugins)</Check>
|
||||
|
||||
## 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).
|
||||
|
||||
309
docs/plugins/building-plugins.md
Normal file
309
docs/plugins/building-plugins.md
Normal file
@@ -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 <npm-spec>`. 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
|
||||
|
||||
<Steps>
|
||||
<Step title="Create the package">
|
||||
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.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Define the entry point">
|
||||
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.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Import from focused SDK subpaths">
|
||||
Always import from specific `openclaw/plugin-sdk/\<subpath\>` 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";
|
||||
```
|
||||
|
||||
<Accordion title="Common subpaths reference">
|
||||
| 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 |
|
||||
</Accordion>
|
||||
|
||||
Use the narrowest subpath that matches the job.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Use local modules for internal imports">
|
||||
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";
|
||||
```
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add a plugin manifest">
|
||||
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.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Test your plugin">
|
||||
**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";
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Publish and install">
|
||||
**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 <query>
|
||||
openclaw plugins install <npm-spec>
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 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/\<name\>` 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
|
||||
|
||||
<Check>**package.json** has correct `openclaw` metadata</Check>
|
||||
<Check>Entry point uses `defineChannelPluginEntry` or `definePluginEntry`</Check>
|
||||
<Check>All imports use focused `plugin-sdk/\<subpath\>` paths</Check>
|
||||
<Check>Internal imports use local modules, not SDK self-imports</Check>
|
||||
<Check>`openclaw.plugin.json` manifest is present and valid</Check>
|
||||
<Check>Tests pass</Check>
|
||||
<Check>`pnpm check` passes (in-repo plugins)</Check>
|
||||
|
||||
## 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
|
||||
@@ -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/\<subpath\>`). 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/\<subpath\>`) instead.
|
||||
|
||||
## Why this change
|
||||
<Info>
|
||||
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.
|
||||
</Info>
|
||||
|
||||
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:
|
||||
<Steps>
|
||||
<Step title="Find deprecated imports">
|
||||
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/\<subpath\> 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.
|
||||
</Step>
|
||||
|
||||
## How to migrate
|
||||
<Step title="Replace with focused subpaths">
|
||||
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
|
||||
</Step>
|
||||
|
||||
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/
|
||||
```
|
||||
<Step title="Build and test">
|
||||
```bash
|
||||
pnpm build
|
||||
pnpm test -- my-plugin/
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 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 |
|
||||
<Accordion title="Full subpath table">
|
||||
| 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 |
|
||||
</Accordion>
|
||||
|
||||
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/\<your-extension\>`
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Built-in tools" icon="wrench" href="/tools/exec">
|
||||
Core tools shipped with OpenClaw: exec, browser, web search, file I/O,
|
||||
messaging, cron, canvas, and nodes.
|
||||
</Card>
|
||||
<Card title="Skills" icon="book-open" href="/tools/skills">
|
||||
Markdown instructions that teach the agent how and when to use tools.
|
||||
Skills ship inside plugins or live in your workspace.
|
||||
</Card>
|
||||
<Card title="Plugins" icon="puzzle-piece" href="/tools/plugin">
|
||||
Packages that add new capabilities: channels, model providers, tools,
|
||||
skills, or any combination. Published on npm and installed with the CLI.
|
||||
</Card>
|
||||
<Card title="Automation" icon="clock" href="/automation/hooks">
|
||||
Hooks, cron jobs, heartbeats, webhooks, and scheduled tasks that run
|
||||
without manual messages.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 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:<path>`)
|
||||
- `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 `<input type="file">` directly.
|
||||
|
||||
### `canvas`
|
||||
|
||||
Drive the node Canvas (present, eval, snapshot, A2UI).
|
||||
|
||||
Core actions:
|
||||
|
||||
- `present`, `hide`, `navigate`, `eval`
|
||||
- `snapshot` (returns image block + `MEDIA:<path>`)
|
||||
- `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 <id> --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:<path>`.
|
||||
- Videos return `FILE:<path>` (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:<path>` 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.<id>`, 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/<uuid>/` 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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user