Plugins
Plugins bouwen
Plugins breiden OpenClaw uit met nieuwe mogelijkheden: kanalen, modelproviders, spraak, realtime transcriptie, realtime spraak, mediabegrip, afbeeldingsgeneratie, videogeneratie, web-fetch, webzoekopdrachten, agenttools of elke combinatie.
Je hoeft je Plugin niet toe te voegen aan de OpenClaw-repository. Publiceer naar
ClawHub en gebruikers installeren met
openclaw plugins install clawhub:<package-name>. Kale pakketspecificaties
installeren tijdens de lanceringsomschakeling nog steeds vanaf npm.
Vereisten
- Node >= 22 en een pakketbeheerder (npm of pnpm)
- Bekendheid met TypeScript (ESM)
- Voor Plugins in de repository: repository gekloond en
pnpm installuitgevoerd. Ontwikkeling van Plugins vanuit een source-checkout is alleen pnpm, omdat OpenClaw gebundelde Plugins laadt uit deextensions/*-workspacepakketten.
Wat voor soort Plugin?
Verbind OpenClaw met een berichtenplatform (Discord, IRC, enz.)
Voeg een modelprovider toe (LLM, proxy of aangepast eindpunt)
Registreer agenttools, event hooks of services - ga hieronder verder
Gebruik voor een kanaalplugin waarvan niet gegarandeerd is dat die is geïnstalleerd wanneer onboarding/setup
wordt uitgevoerd createOptionalChannelSetupSurface(...) uit
openclaw/plugin-sdk/channel-setup. Dit produceert een setupadapter + wizardpaar
dat de installatievereiste aangeeft en veilig faalt bij echte configuratieschrijfbewerkingen
totdat de Plugin is geïnstalleerd.
Snelstart: toolplugin
Deze walkthrough maakt een minimale Plugin die een agenttool registreert. Kanaal- en providerplugins hebben eigen gidsen die hierboven zijn gelinkt.
Maak het pakket en het manifest
{
"name": "@myorg/openclaw-my-plugin",
"version": "1.0.0",
"type": "module",
"openclaw": {
"extensions": ["./index.ts"],
"compat": {
"pluginApi": ">=2026.3.24-beta.2",
"minGatewayVersion": "2026.3.24-beta.2"
},
"build": {
"openclawVersion": "2026.3.24-beta.2",
"pluginSdkVersion": "2026.3.24-beta.2"
}
}
}
{
"id": "my-plugin",
"name": "My Plugin",
"description": "Adds a custom tool to OpenClaw",
"contracts": {
"tools": ["my_tool"]
},
"activation": {
"onStartup": true
},
"configSchema": {
"type": "object",
"additionalProperties": false
}
}
Elke Plugin heeft een manifest nodig, zelfs zonder configuratie. Tools die tijdens runtime worden geregistreerd
moeten worden vermeld in contracts.tools, zodat OpenClaw de eigenaar-
Plugin kan ontdekken zonder elke Plugin-runtime te laden. Plugins moeten ook
activation.onStartup bewust declareren. Dit voorbeeld stelt het in op true. Zie
Manifest voor het volledige schema. De canonieke ClawHub-
publicatiesnippets staan in docs/snippets/plugin-publish/.
Schrijf het entrypoint
// index.ts
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import { Type } from "@sinclair/typebox";
export default definePluginEntry({
id: "my-plugin",
name: "My Plugin",
description: "Adds a custom tool to OpenClaw",
register(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: `Got: ${params.input}` }] };
},
});
},
});
definePluginEntry is voor niet-kanaalplugins. Gebruik voor kanalen
defineChannelPluginEntry - zie Kanaalplugins.
Zie Entrypoints voor alle entrypointopties.
Test en publiceer
Externe Plugins: valideer en publiceer met ClawHub, en installeer daarna:
clawhub package publish your-org/your-plugin --dry-run
clawhub package publish your-org/your-plugin
openclaw plugins install clawhub:@myorg/openclaw-my-plugin
Kale pakketspecificaties zoals @myorg/openclaw-my-plugin installeren tijdens
de lanceringsomschakeling vanaf npm. Gebruik clawhub: wanneer je ClawHub-resolutie wilt.
Plugins in de repository: plaats ze onder de gebundelde Plugin-workspaceboom - ze worden automatisch ontdekt.
pnpm test -- <bundled-plugin-root>/my-plugin/
Pluginmogelijkheden
Een enkele Plugin kan elk aantal mogelijkheden registreren via het api-object:
| Mogelijkheid | Registratiemethode | Gedetailleerde gids |
|---|---|---|
| Tekstinferentie (LLM) | api.registerProvider(...) |
Providerplugins |
| CLI-inferentiebackend | api.registerCliBackend(...) |
CLI-backends |
| Kanaal / berichten | api.registerChannel(...) |
Kanaalplugins |
| Spraak (TTS/STT) | api.registerSpeechProvider(...) |
Providerplugins |
| Realtime transcriptie | api.registerRealtimeTranscriptionProvider(...) |
Providerplugins |
| Realtime spraak | api.registerRealtimeVoiceProvider(...) |
Providerplugins |
| Mediabegrip | api.registerMediaUnderstandingProvider(...) |
Providerplugins |
| Afbeeldingsgeneratie | api.registerImageGenerationProvider(...) |
Providerplugins |
| Muziekgeneratie | api.registerMusicGenerationProvider(...) |
Providerplugins |
| Videogeneratie | api.registerVideoGenerationProvider(...) |
Providerplugins |
| Web-fetch | api.registerWebFetchProvider(...) |
Providerplugins |
| Webzoekopdracht | api.registerWebSearchProvider(...) |
Providerplugins |
| Toolresultaatmiddleware | api.registerAgentToolResultMiddleware(...) |
SDK-overzicht |
| Agenttools | api.registerTool(...) |
Hieronder |
| Aangepaste opdrachten | api.registerCommand(...) |
Entrypoints |
| Plugin hooks | api.on(...) |
Plugin hooks |
| Interne event hooks | api.registerHook(...) |
Entrypoints |
| HTTP-routes | api.registerHttpRoute(...) |
Internals |
| CLI-subopdrachten | api.registerCli(...) |
Entrypoints |
Zie SDK-overzicht voor de volledige registratie-API.
Gebundelde Plugins kunnen api.registerAgentToolResultMiddleware(...) gebruiken wanneer ze
asynchrone herschrijving van toolresultaten nodig hebben voordat het model de output ziet. Declareer de
gerichte runtimes in contracts.agentToolResultMiddleware, bijvoorbeeld
["pi", "codex"]. Dit is een vertrouwde seam voor gebundelde Plugins; externe
Plugins moeten reguliere OpenClaw Plugin hooks gebruiken, tenzij OpenClaw een
expliciet vertrouwensbeleid voor deze mogelijkheid krijgt.
Als je Plugin aangepaste Gateway-RPC-methoden registreert, houd ze dan op een
Plugin-specifiek prefix. Core-adminnamespaces (config.*,
exec.approvals.*, wizard.*, update.*) blijven gereserveerd en verwijzen altijd naar
operator.admin, zelfs als een Plugin om een smallere scope vraagt.
Hook-guardsemantiek om in gedachten te houden:
before_tool_call:{ block: true }is terminaal en stopt handlers met lagere prioriteit.before_tool_call:{ block: false }wordt behandeld als geen beslissing.before_tool_call:{ requireApproval: true }pauzeert agentuitvoering en vraagt de gebruiker om goedkeuring via de exec-goedkeuringsoverlay, Telegram-knoppen, Discord-interacties of de opdracht/approveop elk kanaal.before_install:{ block: true }is terminaal en stopt handlers met lagere prioriteit.before_install:{ block: false }wordt behandeld als geen beslissing.message_sending:{ cancel: true }is terminaal en stopt handlers met lagere prioriteit.message_sending:{ cancel: false }wordt behandeld als geen beslissing.message_received: geef de voorkeur aan het getypte veldthreadIdwanneer je routering van inkomende threads/topics nodig hebt. Bewaarmetadatavoor kanaalspecifieke extra's.message_sending: geef de voorkeur aan getypte routeringsveldenreplyToId/threadIdboven kanaalspecifieke metadatakeys.
De opdracht /approve verwerkt zowel exec- als Plugin-goedkeuringen met begrensde fallback: wanneer een exec-goedkeurings-id niet wordt gevonden, probeert OpenClaw dezelfde id opnieuw via Plugin-goedkeuringen. Het doorsturen van Plugin-goedkeuringen kan onafhankelijk worden geconfigureerd via approvals.plugin in de configuratie.
Als aangepaste goedkeuringsplumbing diezelfde begrensde fallbackcase moet detecteren,
gebruik dan bij voorkeur isApprovalNotFoundError uit openclaw/plugin-sdk/error-runtime
in plaats van handmatig approval-expiry-strings te matchen.
Zie Plugin hooks voor voorbeelden en de hookreferentie.
Agenttools registreren
Tools zijn getypte functies die de LLM kan aanroepen. Ze kunnen vereist zijn (altijd beschikbaar) of optioneel (opt-in door gebruiker):
register(api) {
// Required tool - always available
api.registerTool({
name: "my_tool",
description: "Do a thing",
parameters: Type.Object({ input: Type.String() }),
async execute(_id, params) {
return { content: [{ type: "text", text: params.input }] };
},
});
// Optional tool - user must add to allowlist
api.registerTool(
{
name: "workflow_tool",
description: "Run a workflow",
parameters: Type.Object({ pipeline: Type.String() }),
async execute(_id, params) {
return { content: [{ type: "text", text: params.pipeline }] };
},
},
{ optional: true },
);
}
Elke tool die met api.registerTool(...) wordt geregistreerd, moet ook worden gedeclareerd in het
Plugin-manifest:
{
"contracts": {
"tools": ["my_tool", "workflow_tool"]
},
"toolMetadata": {
"workflow_tool": {
"optional": true
}
}
}
OpenClaw legt de gevalideerde descriptor van de geregistreerde tool vast en cachet deze,
zodat plugins geen description- of schemagegevens in het manifest dupliceren. Het
manifestcontract verklaart alleen eigendom en vindbaarheid; uitvoering roept nog steeds
de live geregistreerde toolimplementatie aan.
Stel toolMetadata.<tool>.optional: true in voor tools die zijn geregistreerd met
api.registerTool(..., { optional: true }), zodat OpenClaw kan voorkomen dat die
plugin-runtime wordt geladen totdat de tool expliciet is toegestaan.
Gebruikers schakelen optionele tools in de configuratie in:
{
tools: { allow: ["workflow_tool"] },
}
- Toolnamen mogen niet botsen met kerntools (conflicten worden overgeslagen)
- Tools met misvormde registratieobjecten, inclusief ontbrekende
parameters, worden overgeslagen en gemeld in plugin-diagnostiek in plaats van agent-runs te onderbreken - Gebruik
optional: truevoor tools met neveneffecten of extra binaire vereisten - Gebruikers kunnen alle tools van een plugin inschakelen door de plugin-id toe te voegen aan
tools.allow
CLI-opdrachten registreren
Plugins kunnen hoofdgroepen voor openclaw-opdrachten toevoegen met api.registerCli. Geef
descriptors op voor elke opdrachtroot op het hoogste niveau, zodat OpenClaw de
opdracht kan tonen en routeren zonder elke plugin-runtime vooraf te laden.
register(api) {
api.registerCli(
({ program }) => {
const demo = program
.command("demo-plugin")
.description("Run demo plugin commands");
demo
.command("ping")
.description("Check that the plugin CLI is executable")
.action(() => {
console.log("demo-plugin:pong");
});
},
{
descriptors: [
{
name: "demo-plugin",
description: "Run demo plugin commands",
hasSubcommands: true,
},
],
},
);
}
Verifieer na installatie de runtime-registratie en voer de opdracht uit:
openclaw plugins inspect demo-plugin --runtime --json
openclaw demo-plugin ping
Importconventies
Importeer altijd vanuit gerichte openclaw/plugin-sdk/<subpath>-paden:
// Wrong: monolithic root (deprecated, will be removed)
Zie SDK-overzicht voor de volledige subpadreferentie.
Gebruik binnen je plugin lokale barrelbestanden (api.ts, runtime-api.ts) voor
interne imports - importeer je eigen plugin nooit via het SDK-pad.
Voor provider-plugins bewaar je providerspecifieke helpers in die barrels op pakketrootniveau, tenzij de seam echt generiek is. Huidige gebundelde voorbeelden:
- Anthropic: Claude-streamwrappers en
service_tier- / bètahelpers - OpenAI: providerbouwers, helpers voor standaardmodellen, realtime providers
- OpenRouter: providerbouwer plus onboarding-/configuratiehelpers
Als een helper alleen nuttig is binnen één gebundeld providerpakket, houd deze dan op die
seam op pakketrootniveau in plaats van hem naar openclaw/plugin-sdk/* te promoveren.
Sommige gegenereerde openclaw/plugin-sdk/<bundled-id>-helperseams bestaan nog steeds voor
onderhoud van gebundelde plugins wanneer ze bijgehouden gebruik door eigenaren hebben. Behandel die als
gereserveerde oppervlakken, niet als het standaardpatroon voor nieuwe plugins van derden.
Checklist vóór indiening
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
package.json heeft correcte openclaw-metadata
OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s openclaw.plugin.json-manifest is aanwezig en geldig OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
Entry point gebruikt defineChannelPluginEntry of definePluginEntry
OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
Alle imports gebruiken gerichte plugin-sdk/<subpath>-paden
OPENCLAW_DOCS_MARKER:calloutClose: