Building plugins
Plugin di strumenti
I Plugin di strumenti aggiungono a OpenClaw strumenti richiamabili dagli agenti senza aggiungere un canale,
provider di modelli, hook, servizio o backend di configurazione. Usa defineToolPlugin quando il
Plugin possiede un elenco fisso di strumenti e vuoi che OpenClaw generi i metadati del manifesto
che mantengono quegli strumenti rilevabili senza caricare codice di runtime.
Il flusso consigliato è:
- Genera lo scaffold di un pacchetto con
openclaw plugins init. - Scrivi gli strumenti con
defineToolPlugin. - Compila JavaScript.
- Genera i metadati di
openclaw.plugin.jsonepackage.jsonconopenclaw plugins build. - Valida i metadati generati prima di pubblicare o installare.
Per Plugin provider, di canale, hook, servizio o con funzionalità miste, inizia invece da Creare Plugin, Plugin di canale o Plugin provider.
Requisiti
- Node >= 22.
- Output del pacchetto TypeScript ESM.
typeboxper schemi di configurazione e dei parametri degli strumenti.openclaw >=2026.5.17, la prima versione di OpenClaw che esportaopenclaw/plugin-sdk/tool-plugin.- Una radice del pacchetto che possa distribuire
dist/,openclaw.plugin.jsonepackage.json.
Il Plugin generato importa typebox a runtime, quindi mantieni typebox in
dependencies, non solo in devDependencies.
Avvio rapido
Crea un nuovo pacchetto Plugin:
openclaw plugins init stock-quotes --name "Stock Quotes"cd stock-quotesnpm installnpm run plugin:buildnpm run plugin:validatenpm testLo scaffold crea:
src/index.ts: una vocedefineToolPlugincon uno strumentoecho.src/index.test.ts: un piccolo test dei metadati.tsconfig.json: output TypeScript NodeNext indist/.package.json: script, dipendenze di runtime eopenclaw.extensions: ["./dist/index.js"].openclaw.plugin.json: metadati del manifesto generati per lo strumento iniziale.
Output di validazione previsto:
Plugin stock-quotes is valid.Scrivere uno strumento
defineToolPlugin accetta l'identità del Plugin, uno schema di configurazione opzionale e un
elenco statico di strumenti. I tipi dei parametri e della configurazione vengono dedotti dagli
schemi TypeBox.
export default defineToolPlugin({ id: "stock-quotes", name: "Stock Quotes", description: "Fetch stock quote snapshots.", configSchema: Type.Object({ apiKey: Type.Optional(Type.String({ description: "Quote API key." })), baseUrl: Type.Optional(Type.String({ description: "Quote API base URL." })), }), tools: (tool) => [ tool({ name: "stock_quote", label: "Stock Quote", description: "Fetch a stock quote snapshot.", parameters: Type.Object({ symbol: Type.String({ description: "Ticker symbol, for example OPEN." }), }), async execute({ symbol }, config, context) { context.signal?.throwIfAborted(); return { symbol: symbol.toUpperCase(), configured: Boolean(config.apiKey), baseUrl: config.baseUrl ?? "https://api.example.com", }; }, }), ],});I nomi degli strumenti sono l'API stabile. Scegli nomi univoci, in minuscolo e abbastanza specifici da evitare collisioni con gli strumenti core o altri Plugin.
Strumenti opzionali e factory
Imposta optional: true quando gli utenti devono inserire esplicitamente lo strumento in allowlist prima che venga
inviato a un modello:
tool({ name: "workflow_run", description: "Run an external workflow.", parameters: Type.Object({ goal: Type.String() }), optional: true, execute: ({ goal }) => ({ queued: true, goal }),});openclaw plugins build scrive la voce di manifesto toolMetadata.<tool>.optional
corrispondente, così OpenClaw può rilevare lo strumento senza caricare il codice di
runtime del Plugin.
Usa factory quando uno strumento ha bisogno del contesto degli strumenti di runtime prima di poter essere
creato. La factory mantiene statici i metadati consentendo allo strumento di escludersi da
una run specifica, ispezionare lo stato della sandbox o collegare helper di runtime.
tool({ name: "local_workflow", description: "Run a local workflow outside sandboxed sessions.", parameters: Type.Object({ goal: Type.String() }), optional: true, factory({ api, toolContext }) { if (toolContext.sandboxed) { return null; } return createLocalWorkflowTool(api); },});Le factory servono comunque per nomi di strumenti fissi. Usa direttamente definePluginEntry quando
il Plugin calcola dinamicamente i nomi degli strumenti o combina strumenti con hook,
servizi, provider, comandi o altre superfici di runtime.
Valori restituiti
defineToolPlugin incapsula i valori restituiti semplici nel formato di risultato degli strumenti di OpenClaw:
- Restituisci una stringa quando il modello deve vedere esattamente quel testo.
- Restituisci un valore compatibile con JSON quando vuoi che il modello veda JSON formattato
e che OpenClaw mantenga il valore originale in
details.
tool({ name: "echo_text", description: "Echo input text.", parameters: Type.Object({ input: Type.String(), }), execute: ({ input }) => input,});tool({ name: "echo_json", description: "Echo input as structured JSON.", parameters: Type.Object({ input: Type.String(), }), execute: ({ input }) => ({ input, length: input.length }),});Usa uno strumento factory quando devi restituire un AgentToolResult personalizzato o riutilizzare
un'implementazione api.registerTool esistente. Usa definePluginEntry invece
di defineToolPlugin quando ti servono strumenti completamente dinamici o funzionalità
di Plugin miste.
Configurazione
configSchema è opzionale. Se lo ometti, OpenClaw usa uno schema a oggetto vuoto rigido
e il manifesto generato include comunque configSchema.
export default defineToolPlugin({ id: "no-config-tools", name: "No Config Tools", description: "Adds tools that do not need configuration.", tools: () => [],});Quando includi configSchema, il secondo argomento di execute è tipizzato dallo
schema:
const configSchema = Type.Object({ apiKey: Type.String(),}); export default defineToolPlugin({ id: "configured-tools", name: "Configured Tools", description: "Adds configured tools.", configSchema, tools: (tool) => [ tool({ name: "configured_ping", description: "Check whether configuration is available.", parameters: Type.Object({}), execute: (_params, config) => ({ hasKey: config.apiKey.length > 0 }), }), ],});OpenClaw legge la configurazione del Plugin dalla voce del Plugin nella configurazione del Gateway. Non inserire segreti hardcoded nel sorgente o negli esempi della documentazione. Usa la configurazione, le variabili di ambiente o SecretRefs in base al modello di sicurezza del Plugin.
Metadati generati
OpenClaw rileva i Plugin installati dai metadati a freddo. Deve poter leggere
il manifesto del Plugin prima di importare il codice di runtime del Plugin. defineToolPlugin
espone quindi metadati statici e openclaw plugins build scrive quei
metadati nel pacchetto.
Esegui il generatore dopo aver modificato ID, nome, descrizione, schema di configurazione, attivazione o nomi degli strumenti del Plugin:
npm run buildopenclaw plugins build --entry ./dist/index.jsPer un Plugin con un solo strumento, il manifesto generato appare così:
{ "id": "stock-quotes", "name": "Stock Quotes", "description": "Fetch stock quote snapshots.", "version": "0.1.0", "configSchema": { "type": "object", "additionalProperties": false, "properties": {} }, "activation": { "onStartup": true }, "contracts": { "tools": ["stock_quote"] }}contracts.tools è il contratto di rilevamento importante. Indica a OpenClaw quale
Plugin possiede ogni strumento senza caricare il runtime di ogni Plugin installato. Se il
manifesto non è aggiornato, lo strumento potrebbe mancare dal rilevamento o il Plugin sbagliato
potrebbe essere indicato come responsabile di un errore di registrazione.
Metadati del pacchetto
Per il flusso semplice dei Plugin di strumenti, openclaw plugins build allinea
package.json alla singola voce di runtime selezionata:
{ "type": "module", "files": ["dist", "openclaw.plugin.json", "README.md"], "dependencies": { "typebox": "^1.1.38" }, "peerDependencies": { "openclaw": ">=2026.5.17" }, "openclaw": { "extensions": ["./dist/index.js"] }}Usa JavaScript compilato come ./dist/index.js per i pacchetti installati. Le voci
sorgente sono utili nello sviluppo in workspace, ma i pacchetti pubblicati non dovrebbero
dipendere dal caricamento runtime di TypeScript.
Validare in CI
Usa plugins build --check per far fallire la CI quando i metadati generati non sono aggiornati senza
riscrivere file:
npm run buildopenclaw plugins build --entry ./dist/index.js --checkopenclaw plugins validate --entry ./dist/index.jsnpm testplugins validate controlla che:
openclaw.plugin.jsonesista e superi il normale loader del manifesto.- La voce corrente esporti metadati
defineToolPlugin. - I campi del manifesto generato corrispondano ai metadati della voce.
contracts.toolscorrisponda ai nomi degli strumenti dichiarati.package.jsonpuntiopenclaw.extensionsalla voce di runtime selezionata.
Installare e ispezionare localmente
Da un checkout OpenClaw separato o da una CLI installata, installa il percorso del pacchetto:
openclaw plugins install ./stock-quotesopenclaw plugins inspect stock-quotes --runtimePer uno smoke del pacchetto, crea prima il pacchetto e installa il tarball:
npm packopenclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgzopenclaw plugins inspect stock-quotes --runtime --jsonDopo l'installazione, avvia o riavvia il Gateway e chiedi all'agente di usare lo strumento. Se stai eseguendo il debug della visibilità degli strumenti, ispeziona il runtime del Plugin e il catalogo degli strumenti effettivo prima di modificare il codice.
Pubblicare
Pubblica tramite ClawHub quando il pacchetto è pronto:
clawhub package publish your-org/stock-quotes --dry-runclawhub package publish your-org/stock-quotesInstalla con un locator ClawHub esplicito:
openclaw plugins install clawhub:your-org/stock-quotesLe specifiche nude dei pacchetti npm rimangono supportate durante il passaggio di lancio, ma ClawHub è la superficie preferita di rilevamento e distribuzione per i Plugin OpenClaw.
Risoluzione dei problemi
plugin entry not found: ./dist/index.js
Il file della voce selezionata non esiste. Esegui npm run build, quindi riesegui
openclaw plugins build --entry ./dist/index.js o
openclaw plugins validate --entry ./dist/index.js.
plugin entry does not expose defineToolPlugin metadata
La voce non ha esportato un valore creato da defineToolPlugin. Controlla che l'export
predefinito del modulo sia il risultato di defineToolPlugin(...), oppure passa la voce corretta
con --entry.
openclaw.plugin.json generated metadata is stale
Il manifesto non corrisponde più ai metadati della voce. Esegui:
npm run buildopenclaw plugins build --entry ./dist/index.jsCommitta sia le modifiche a openclaw.plugin.json sia quelle a package.json.
package.json openclaw.extensions must include ./dist/index.js
I metadati del pacchetto puntano a una voce di runtime diversa. Esegui
openclaw plugins build --entry ./dist/index.js così il generatore allinea i
metadati del pacchetto con la voce che intendi distribuire.
Cannot find package 'typebox'
Il Plugin compilato importa typebox a runtime. Mantieni typebox in
dependencies, reinstalla le dipendenze del pacchetto, ricompila e riesegui la validazione.
Lo strumento non appare dopo l'installazione
Controlla questi elementi in ordine:
openclaw plugins inspect <plugin-id> --runtimeopenclaw plugins validate --root <plugin-root> --entry ./dist/index.jsopenclaw.plugin.jsoncontienecontracts.toolscon i nomi degli strumenti previsti.package.jsoncontieneopenclaw.extensions: ["./dist/index.js"].- Il Gateway è stato riavviato o ricaricato dopo l'installazione del Plugin.