Plugins
SwarmClaw has an extensible plugin system for adding custom logic at key points in the agent lifecycle. Plugins from OpenClaw are also natively supported, and built-in capabilities now share the same canonical plugin-family IDs used by the Plugins UI, agent configs, approvals, and policy rules.
Installing Plugins
Need a step-by-step walkthrough? See Plugin Tutorial.
Three ways to add plugins:
Marketplace
Browse and install approved plugins directly from Settings:
- Go to Settings → Plugins → Marketplace tab
- Browse available plugins and click Install
- The plugin source is downloaded, saved to
data/plugins/, and enabled automatically
The marketplace registry is hosted at swarmclaw.ai/registry/plugins.json and sourced from swarmclawai/swarmforge. The hosted file is a generated mirror.
Refresh it before deploying the site with npm run sync:plugin-registry.
SwarmClaw also normalizes legacy swarmclawai/plugins URLs during install, so older entries continue to work without manual fixes.
Marketplace Sources
SwarmClaw now records both the publisher/source of a plugin and the install channel used to fetch it. In practice that means the UI can show combinations like:
- SwarmForge via SwarmClaw Site — first-party plugin published from
swarmforgeand installed from the hosted site mirror - ClawHub — external catalog entries installed from ClawHub
- Direct URL — manually installed over HTTPS
Treat the sources like this:
- SwarmForge is the canonical first-party registry/repo
- SwarmClaw Site hosts the public mirror at
swarmclaw.ai/registry/plugins.json - ClawHub is an external marketplace
- Manual URL is the direct install path when no registry is involved
Install from URL
Install any plugin from an HTTPS URL:
- Go to Settings → Plugins → Install from URL tab
- Paste the URL to a
.jsor.mjsplugin file - Choose a filename and click Install Plugin
Manual
Drop .js or .mjs files directly into data/plugins/. SwarmClaw hot-reloads plugin files, so installs and edits are usually visible without a restart.
If a plugin needs third-party npm packages, SwarmClaw can also manage it in a per-plugin workspace with a package.json manifest.
Trust Model
External plugins run as server-side code inside the SwarmClaw app process. Install code you trust, pin plugin URLs to stable sources when possible, and review plugin settings before enabling them on autonomous agents.
Stability & Recovery
To protect runtime stability, SwarmClaw tracks consecutive plugin failures during:
- Plugin load/startup
- Lifecycle hooks
- Plugin tool execution
- Inbound/outbound text transform hooks
If a plugin keeps failing repeatedly, SwarmClaw auto-disables it, writes failure metadata to data/plugin-failures.json, and emits a warning notification in the Notification Center with a link to the Plugins page.
You can tune the threshold with:
SWARMCLAW_PLUGIN_FAILURE_THRESHOLD=3
Default is 3 consecutive failures. Users can re-enable a disabled plugin manually from Settings → Plugins.
Plugin Format (SwarmClaw)
SwarmClaw supports CommonJS (module.exports = { ... }) and .mjs/ESM default exports. The example below uses CommonJS because it is the simplest format for local plugins.
// data/plugins/my-plugin.js
module.exports = {
name: "my-plugin",
description: "What this plugin does",
hooks: {
beforeAgentStart({ session, message }) {
// Called before an agent begins processing a message
},
afterAgentComplete({ session, response }) {
// Called after an agent finishes generating a response
},
beforeToolExec({ toolName, input }) {
// Called before a tool is executed.
// Return a replacement object to rewrite tool input.
return { ...input, traced: true };
},
afterToolExec({ session, toolName, input, output }) {
// Called after a tool completes execution
},
afterChatTurn({ session, message, response, source, internal }) {
// Called after a full chat turn completes
},
getAgentContext({ session, enabledPlugins, message, history }) {
// Return markdown context injected into the agent prompt
return `Workspace mode: ${session.cwd || "default"}`;
},
getCapabilityDescription() {
// Return one capability line injected into the system prompt
return "I can annotate pull requests with deployment risk tags.";
},
getOperatingGuidance() {
// Return one or more guidance lines injected into runtime hints
return ["Prefer dry-run mode before write actions."];
},
onTaskComplete({ taskId, result }) {
// Called when an agent successfully completes a task
},
onAgentDelegation({ sourceAgentId, targetAgentId, task }) {
// Called when an orchestrator delegates to a sub-agent
},
},
// Plugins can also define custom tools that agents can use
tools: [
{
name: "my_custom_tool",
description: "Does something amazing",
parameters: {
type: "object",
properties: {
query: { type: "string" }
},
required: ["query"]
},
execute: async (args, ctx) => {
return "Result: " + args.query;
}
}
],
// Optional plugin settings rendered in Settings -> Plugins detail panel
ui: {
settingsFields: [
{ key: "webhookUrl", label: "Webhook URL", type: "text", placeholder: "https://...", required: true },
{ key: "debug", label: "Debug Mode", type: "boolean", defaultValue: false },
{ key: "token", label: "API Token", type: "secret" },
],
},
};
Hook signatures of note:
beforeToolExec({ toolName, input })may return a replacement input object.afterToolExec({ session, toolName, input, output })observes completed tool executions.transformInboundMessage({ session, text })andtransformOutboundMessage({ session, text })run sequentially across enabled plugins.ui.settingsFieldsvalues are available throughgetPluginSettings(pluginId)andtype: "secret"values are encrypted at rest.
OpenClaw Plugin Compatibility
SwarmClaw natively supports the OpenClaw plugin format. Drop an OpenClaw plugin into data/plugins/ and it works automatically — lifecycle hooks are mapped at load time:
| OpenClaw Hook | SwarmClaw Hook |
|---|---|
onAgentStart | beforeAgentStart |
onAgentComplete | afterAgentComplete |
onToolCall | beforeToolExec |
onToolResult | afterToolExec |
onMessage | onMessage |
onAgentContext / agent:context | getAgentContext |
OpenClaw plugins use the activate(ctx) pattern:
module.exports = {
name: "my-openclaw-plugin",
version: "1.0.0",
activate(ctx) {
ctx.onAgentStart((data) => { /* ... */ });
ctx.onToolCall((data) => { /* ... */ });
},
deactivate() { /* cleanup */ },
};
This means plugins written for OpenClaw work in SwarmClaw with zero changes, and vice versa for plugins that use the hook mapping.
Available Hooks
| Hook | Trigger | Can Modify |
|---|---|---|
beforeAgentStart | Agent receives a message | Agent config, chat context |
afterAgentComplete | Agent finishes response | Nothing (observation only) |
beforeToolExec | Before a tool runs | Tool input (by returning a replacement input object) |
afterToolExec | After a tool completes | Nothing (observation only) |
afterChatTurn | Full chat turn completes | Nothing (observation only) |
transformInboundMessage | User text enters runtime | Inbound text |
transformOutboundMessage | Assistant text leaves runtime | Outbound text |
getAgentContext | Prompt context assembly | Additional markdown context block |
getCapabilityDescription | Prompt capability assembly | Capability line in system prompt |
getOperatingGuidance | Prompt guidance assembly | Runtime guidance lines |
onTaskComplete | When a task status becomes "completed" | Nothing (observation only) |
onAgentDelegation | When an orchestrator delegates to a sub-agent | Nothing (observation only) |
Plugin Settings Fields
Plugins can declare ui.settingsFields so users can configure plugin-specific values in the plugin detail sheet.
- Values are stored in app settings under
pluginSettings[pluginId] - Unknown keys are ignored on write
- Fields with
type: secretare encrypted at rest - Read/write API:
GET /api/plugins/settings?pluginId=<pluginId>PUT /api/plugins/settings?pluginId=<pluginId>
- Supported field types:
text,number,boolean,select,secret
Plugin Workspaces & Dependencies
Plugins that need runtime dependencies can be backed by a workspace under data/plugins/.workspaces/<plugin>/.
- Add a
package.jsonmanifest for the plugin - Use the Install / Refresh action in the Plugins detail sheet
- Or call
POST /api/plugins/dependencieswith{ "filename": "plugin.mjs", "packageManager": "npm" }
SwarmClaw tracks dependency install status, package manager, error state, and last-installed time in the plugin metadata shown by the UI and API.
Lifecycle Management
- Versioning: Plugins support semantic versioning metadata (for example
v1.2.3). - Updates: External plugins installed from a recorded source URL can be updated individually or in bulk from the Plugins manager. Built-ins update with the app release.
- Hot Reload: Changes inside
data/plugins/invalidate the plugin registry automatically. - Stability Guardrails: Consecutive plugin failures are tracked in
data/plugin-failures.json; failing external plugins are auto-disabled and surfaced in Notifications. - Source Metadata: Marketplace and URL installs record normalized source URL and source hash metadata in
data/plugins.json.
Built-In Plugin Families
SwarmClaw ships a growing set of built-in plugin families. Some of the most useful ones for autonomous work:
mailbox: IMAP/SMTP inbox access withlist_messages,read_message,reply,download_attachment, and durablewait_for_email.ask_human: Human-loop requests and approvals withrequest_input,request_approval,wait_for_reply,wait_for_approval,list_mailbox, andack_mailbox.document: Parse PDFs, Office docs, HTML, OCR-able images, CSV/TSV/XLSX, ZIP listings, and plain text files, then optionally store searchable document text.extract: Turn raw text or local files into validated JSON with schema-driven extraction using the current session model.table: Read, filter, sort, group, pivot, dedupe, join, summarize, and export tabular data without dropping to shell scripts.crawl: Crawl multi-page sites, follow pagination, dedupe crawled pages, and batch-extract structured results.browser: Reusable browser profiles plus higher-level actions such asread_page,extract_links,extract_form_fields,submit_form,download_file, andcomplete_web_task.schedule_wake/monitor: Durable watch jobs for time, HTTP, file, task, webhook, page, mailbox, and approval waits.delegate/spawn_subagent: Handle-based long-running delegation with persisted resume/checkpoint metadata.
Plugin API
GET /api/plugins # List installed plugins
POST /api/plugins # Toggle plugin enabled/disabled
GET /api/plugins/marketplace # Browse marketplace registry
POST /api/plugins/install # Install from URL { url, filename }
POST /api/plugins/dependencies # Install/refresh workspace deps { filename, packageManager? }
GET /api/plugins/settings # Read per-plugin settings (?pluginId=...)
PUT /api/plugins/settings # Write per-plugin settings (?pluginId=...)
GET /api/plugins includes failure metadata for operational debugging (failureCount, lastFailureAt, lastFailureStage, lastFailureError, autoDisabled).
Examples
Logging plugin — log all tool executions:
module.exports = {
name: "tool-logger",
description: "Logs all tool executions to console",
hooks: {
beforeToolExec({ toolName, input }) {
console.log(`[tool] executing ${toolName}`, input);
},
afterToolExec({ toolName, output }) {
console.log(`[tool] ${toolName} completed`);
},
},
};
Guard plugin — flag dangerous shell commands:
module.exports = {
name: "shell-gate",
description: "Flags dangerous shell commands",
hooks: {
beforeToolExec({ toolName, input }) {
if (toolName === "shell" && /rm\s+-rf\s+\//.test(input.command)) {
console.warn("Potentially dangerous shell command detected", input.command);
}
},
},
};