feat: add plugin architecture
This commit is contained in:
@@ -63,6 +63,13 @@ clawdbot [--dev] [--profile <name>] <command>
|
||||
list
|
||||
info
|
||||
check
|
||||
plugins
|
||||
list
|
||||
info
|
||||
install
|
||||
enable
|
||||
disable
|
||||
doctor
|
||||
message
|
||||
agent
|
||||
agents
|
||||
@@ -167,6 +174,20 @@ clawdbot [--dev] [--profile <name>] <command>
|
||||
tui
|
||||
```
|
||||
|
||||
Note: plugins can add additional top-level commands (for example `clawdbot voicecall`).
|
||||
|
||||
## Plugins
|
||||
|
||||
Manage extensions and their config:
|
||||
|
||||
- `clawdbot plugins list` — discover plugins (use `--json` for machine output).
|
||||
- `clawdbot plugins info <id>` — show details for a plugin.
|
||||
- `clawdbot plugins install <path>` — add a plugin path to `plugins.load.paths`.
|
||||
- `clawdbot plugins enable <id>` / `disable <id>` — toggle `plugins.entries.<id>.enabled`.
|
||||
- `clawdbot plugins doctor` — report plugin load errors.
|
||||
|
||||
Most plugin changes require a gateway restart. See [/plugin](/plugin).
|
||||
|
||||
## Chat slash commands
|
||||
|
||||
Chat messages support `/...` commands (text and native). See [/tools/slash-commands](/tools/slash-commands).
|
||||
|
||||
@@ -548,6 +548,10 @@
|
||||
{
|
||||
"source": "/oauth",
|
||||
"destination": "/concepts/oauth"
|
||||
},
|
||||
{
|
||||
"source": "/plugins",
|
||||
"destination": "/plugin"
|
||||
}
|
||||
],
|
||||
"navigation": {
|
||||
@@ -689,6 +693,7 @@
|
||||
"group": "Tools & Skills",
|
||||
"pages": [
|
||||
"tools",
|
||||
"plugin",
|
||||
"tools/bash",
|
||||
"tools/elevated",
|
||||
"tools/browser",
|
||||
|
||||
@@ -1775,6 +1775,44 @@ Example:
|
||||
}
|
||||
```
|
||||
|
||||
### `plugins` (extensions)
|
||||
|
||||
Controls plugin discovery, allow/deny, and per-plugin config. Plugins are loaded
|
||||
from `~/.clawdbot/extensions`, `<workspace>/.clawdbot/extensions`, plus any
|
||||
`plugins.load.paths` entries. **Config changes require a gateway restart.**
|
||||
See [/plugin](/plugin) for full usage.
|
||||
|
||||
Fields:
|
||||
- `enabled`: master toggle for plugin loading (default: true).
|
||||
- `allow`: optional allowlist of plugin ids; when set, only listed plugins load.
|
||||
- `deny`: optional denylist of plugin ids (deny wins).
|
||||
- `load.paths`: extra plugin files or directories to load (absolute or `~`).
|
||||
- `entries.<pluginId>`: per-plugin overrides.
|
||||
- `enabled`: set `false` to disable.
|
||||
- `config`: plugin-specific config object (validated by the plugin if provided).
|
||||
|
||||
Example:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
enabled: true,
|
||||
allow: ["voice-call"],
|
||||
load: {
|
||||
paths: ["~/Projects/oss/voice-call-extension"]
|
||||
},
|
||||
entries: {
|
||||
"voice-call": {
|
||||
enabled: true,
|
||||
config: {
|
||||
provider: "twilio"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `browser` (clawd-managed Chrome)
|
||||
|
||||
Clawdbot can start a **dedicated, isolated** Chrome/Chromium instance for clawd and expose a small loopback control server.
|
||||
@@ -1942,6 +1980,7 @@ Requires full Gateway restart:
|
||||
- `bridge`
|
||||
- `discovery`
|
||||
- `canvasHost`
|
||||
- `plugins`
|
||||
- Any unknown/unsupported config path (defaults to restart for safety)
|
||||
|
||||
### Multi-instance isolation
|
||||
|
||||
@@ -34,6 +34,15 @@ Clawdbot’s stance:
|
||||
- **Scope next:** decide where the bot is allowed to act (group allowlists + mention gating, tools, sandboxing, device permissions).
|
||||
- **Model last:** assume the model can be manipulated; design so manipulation has limited blast radius.
|
||||
|
||||
## Plugins/extensions
|
||||
|
||||
Plugins run **in-process** with the Gateway. Treat them as trusted code:
|
||||
|
||||
- Only install plugins from sources you trust.
|
||||
- Prefer explicit `plugins.allow` allowlists.
|
||||
- Review plugin config before enabling.
|
||||
- Restart the Gateway after plugin changes.
|
||||
|
||||
## DM access model (pairing / allowlist / open / disabled)
|
||||
|
||||
All current DM-capable providers support a DM policy (`dmPolicy` or `*.dm.policy`) that gates inbound DMs **before** the message is processed:
|
||||
|
||||
192
docs/plugin.md
Normal file
192
docs/plugin.md
Normal file
@@ -0,0 +1,192 @@
|
||||
---
|
||||
summary: "Clawdbot plugins/extensions: discovery, config, and safety"
|
||||
read_when:
|
||||
- Adding or modifying plugins/extensions
|
||||
- Documenting plugin install or load rules
|
||||
---
|
||||
# Plugins (Extensions)
|
||||
|
||||
Clawdbot plugins are **TypeScript modules** loaded at runtime via jiti. They can
|
||||
register:
|
||||
|
||||
- Gateway RPC methods
|
||||
- Agent tools
|
||||
- CLI commands
|
||||
- Background services
|
||||
- Optional config validation
|
||||
|
||||
Plugins run **in‑process** with the Gateway, so treat them as trusted code.
|
||||
|
||||
## Discovery & precedence
|
||||
|
||||
Clawdbot scans, in order:
|
||||
|
||||
1) Global extensions
|
||||
- `~/.clawdbot/extensions/*.ts`
|
||||
- `~/.clawdbot/extensions/*/index.ts`
|
||||
|
||||
2) Workspace extensions
|
||||
- `<workspace>/.clawdbot/extensions/*.ts`
|
||||
- `<workspace>/.clawdbot/extensions/*/index.ts`
|
||||
|
||||
3) Config paths
|
||||
- `plugins.load.paths` (file or directory)
|
||||
|
||||
### Package packs
|
||||
|
||||
A plugin directory may include a `package.json` with `clawdbot.extensions`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-pack",
|
||||
"clawdbot": {
|
||||
"extensions": ["./src/safety.ts", "./src/tools.ts"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each entry becomes a plugin. If the pack lists multiple extensions, the plugin id
|
||||
becomes `name/<fileBase>`.
|
||||
|
||||
If your plugin imports npm deps, install them in that directory so
|
||||
`node_modules` is available (`npm install` / `pnpm install`).
|
||||
|
||||
## Plugin IDs
|
||||
|
||||
Default plugin ids:
|
||||
|
||||
- Package packs: `package.json` `name`
|
||||
- Standalone file: file base name (`~/.../voice-call.ts` → `voice-call`)
|
||||
|
||||
If a plugin exports `id`, Clawdbot uses it but warns when it doesn’t match the
|
||||
configured id.
|
||||
|
||||
## Config
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
enabled: true,
|
||||
allow: ["voice-call"],
|
||||
deny: ["untrusted-plugin"],
|
||||
load: { paths: ["~/Projects/oss/voice-call-extension"] },
|
||||
entries: {
|
||||
"voice-call": { enabled: true, config: { provider: "twilio" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Fields:
|
||||
- `enabled`: master toggle (default: true)
|
||||
- `allow`: allowlist (optional)
|
||||
- `deny`: denylist (optional; deny wins)
|
||||
- `load.paths`: extra plugin files/dirs
|
||||
- `entries.<id>`: per‑plugin toggles + config
|
||||
|
||||
Config changes **require a gateway restart**.
|
||||
|
||||
## CLI
|
||||
|
||||
```bash
|
||||
clawdbot plugins list
|
||||
clawdbot plugins info <id>
|
||||
clawdbot plugins install <path>
|
||||
clawdbot plugins enable <id>
|
||||
clawdbot plugins disable <id>
|
||||
clawdbot plugins doctor
|
||||
```
|
||||
|
||||
Plugins may also register their own top‑level commands (example: `clawdbot voicecall`).
|
||||
|
||||
## Plugin API (overview)
|
||||
|
||||
Plugins export either:
|
||||
|
||||
- A function: `(api) => { ... }`
|
||||
- An object: `{ id, name, configSchema, register(api) { ... } }`
|
||||
|
||||
### Register a tool
|
||||
|
||||
```ts
|
||||
import { Type } from "@sinclair/typebox";
|
||||
|
||||
export default function (api) {
|
||||
api.registerTool({
|
||||
name: "my_tool",
|
||||
description: "Do a thing",
|
||||
parameters: Type.Object({
|
||||
input: Type.String(),
|
||||
}),
|
||||
async execute(_id, params) {
|
||||
return { content: [{ type: "text", text: params.input }] };
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Register a gateway RPC method
|
||||
|
||||
```ts
|
||||
export default function (api) {
|
||||
api.registerGatewayMethod("myplugin.status", ({ respond }) => {
|
||||
respond(true, { ok: true });
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Register CLI commands
|
||||
|
||||
```ts
|
||||
export default function (api) {
|
||||
api.registerCli(({ program }) => {
|
||||
program.command("mycmd").action(() => {
|
||||
console.log("Hello");
|
||||
});
|
||||
}, { commands: ["mycmd"] });
|
||||
}
|
||||
```
|
||||
|
||||
### Register background services
|
||||
|
||||
```ts
|
||||
export default function (api) {
|
||||
api.registerService({
|
||||
id: "my-service",
|
||||
start: () => api.logger.info("ready"),
|
||||
stop: () => api.logger.info("bye"),
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Naming conventions
|
||||
|
||||
- Gateway methods: `pluginId.action` (example: `voicecall.status`)
|
||||
- Tools: `snake_case` (example: `voice_call`)
|
||||
- CLI commands: kebab or camel, but avoid clashing with core commands
|
||||
|
||||
## Skills
|
||||
|
||||
Plugins can ship a skill in the repo (`skills/<name>/SKILL.md`).
|
||||
Enable it with `plugins.entries.<id>.enabled` (or other config gates) and ensure
|
||||
it’s present in your workspace/managed skills locations.
|
||||
|
||||
## Example plugin: Voice Call
|
||||
|
||||
This repo includes a voice‑call placeholder plugin:
|
||||
|
||||
- Source: `extensions/voice-call`
|
||||
- Skill: `skills/voice-call`
|
||||
- CLI: `clawdbot voicecall status`
|
||||
- Tool: `voice_call`
|
||||
- RPC: `voicecall.status`
|
||||
|
||||
See `extensions/voice-call/README.md` for setup and usage.
|
||||
|
||||
## Safety notes
|
||||
|
||||
Plugins run in-process with the Gateway. Treat them as trusted code:
|
||||
|
||||
- Only install plugins you trust.
|
||||
- Prefer `plugins.allow` allowlists.
|
||||
- Restart the Gateway after changes.
|
||||
@@ -22,6 +22,13 @@ You can globally allow/deny tools via `tools.allow` / `tools.deny` in `clawdbot.
|
||||
}
|
||||
```
|
||||
|
||||
## Plugins + tools
|
||||
|
||||
Plugins can register **additional tools** (and CLI commands) beyond the core set.
|
||||
See [Plugins](/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).
|
||||
|
||||
## Tool inventory
|
||||
|
||||
### `bash`
|
||||
|
||||
@@ -36,6 +36,13 @@ In **multi-agent** setups, each agent has its own workspace. That means:
|
||||
If the same skill name exists in more than one place, the usual precedence
|
||||
applies: workspace wins, then managed/local, then bundled.
|
||||
|
||||
## Plugins + skills
|
||||
|
||||
Plugins can ship their own skills (for example, `voice-call`) and gate them via
|
||||
`metadata.clawdbot.requires.config` on the plugin’s config entry. See
|
||||
[Plugins](/plugin) for plugin discovery/config and [Tools](/tools) for the tool
|
||||
surface those skills teach.
|
||||
|
||||
## ClawdHub (install + sync)
|
||||
|
||||
ClawdHub is the public skills registry for Clawdbot. Use it to discover,
|
||||
|
||||
Reference in New Issue
Block a user