Building plugins
工具外掛
defineToolPlugin 會建置一個只新增代理可呼叫工具的外掛:沒有
頻道、模型提供者、hook、服務或設定後端。它會產生 OpenClaw 需要的
manifest metadata,以便在不載入外掛執行階段程式碼的情況下探索工具。
若是提供者、頻道、hook、服務或混合能力外掛,請改從 建置外掛、頻道外掛, 或提供者外掛開始。
需求
- 節點 22.19+、節點 23.11+,或節點 24+。
- TypeScript ESM 套件輸出。
dependencies中有typebox(不只是devDependencies- 產生的 外掛會在執行階段匯入它)。openclaw >=2026.5.17,第一個匯出openclaw/plugin-sdk/tool-plugin的版本。- 一個會發布
dist/、openclaw.plugin.json和package.json的套件根目錄。
快速開始
openclaw plugins init stock-quotes --name "Stock Quotes"cd stock-quotesnpm installnpm run plugin:buildnpm run plugin:validatenpm testplugins init 會建立:
| 檔案 | 用途 |
|---|---|
src/index.ts |
含有一個 echo 工具的 defineToolPlugin 入口 |
src/index.test.ts |
斷言工具清單的 metadata 測試 |
tsconfig.json |
NodeNext TypeScript 輸出到 dist/ |
vitest.config.ts |
用於 src/**/*.test.ts 的 Vitest 設定 |
package.json |
腳本、執行階段相依套件、openclaw.extensions: ["./dist/index.js"] |
openclaw.plugin.json |
為初始工具產生的 manifest metadata |
npm run plugin:build 會執行 npm run build (tsc),然後執行
openclaw plugins build --entry ./dist/index.js。npm run plugin:validate
會重新建置並執行 openclaw plugins validate --entry ./dist/index.js。
驗證成功會印出:
Plugin stock-quotes is valid.openclaw plugins init <id> 選項:
| 旗標 | 預設值 | 效果 |
|---|---|---|
--directory <path> |
<id> |
輸出目錄 |
--name <name> |
標題式大小寫的 <id> |
顯示名稱 |
--type <type> |
tool |
建立類型:tool 或 provider |
--force |
關閉 | 覆寫既有的輸出目錄 |
撰寫工具
defineToolPlugin 會接收外掛身分、選用的設定 schema,以及
靜態工具清單。參數與設定型別會從 TypeBox schema 推斷。
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", }; }, }), ],});工具名稱是穩定的 API。請選擇唯一、小寫,且足夠具體的名稱, 以避免與核心工具或其他外掛衝突。
選用與 factory 工具
當使用者應該在工具傳送給模型前明確加入允許清單時,設定 optional: true。
openclaw plugins build 會寫入對應的
toolMetadata.<tool>.optional manifest 項目,因此 OpenClaw 可以在不載入
外掛執行階段程式碼的情況下知道該工具是選用的。
tool({ name: "workflow_run", description: "Run an external workflow.", parameters: Type.Object({ goal: Type.String() }), optional: true, execute: ({ goal }) => ({ queued: true, goal }),});當工具需要執行階段工具內容才能建立時,使用 factory - 例如針對特定執行
選擇退出、檢查沙盒狀態,或繫結執行階段 helper。即使具體工具是在
執行階段建置,metadata 仍會保持靜態。
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); },});Factory 仍會預先宣告固定的工具名稱。當外掛會動態計算工具名稱,或將工具
與 hook、服務、提供者或命令結合時,請直接使用 definePluginEntry。
回傳值
defineToolPlugin 會將一般回傳值包裝成 OpenClaw 工具結果格式:
- 當模型應該看到完全相同的文字時,回傳字串。
- 當你希望模型看到格式化 JSON,且希望 OpenClaw 將原始值保留在
details中時,回傳 JSON 相容值。
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 }),});當你需要自訂 AgentToolResult,或想重用既有的
api.registerTool 實作時,請使用 factory 工具。
設定
configSchema 是選用的。省略它時,OpenClaw 會套用嚴格的空物件
schema;產生的 manifest 仍會包含 configSchema。
export default defineToolPlugin({ id: "no-config-tools", name: "No Config Tools", description: "Adds tools that do not need configuration.", tools: () => [],});有 configSchema 時,第二個 execute 引數會依據它取得型別:
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 會從閘道設定中的外掛項目讀取外掛設定。不要在來源或文件範例中 硬編碼密鑰;請依照外掛的安全模型使用設定、環境變數或 SecretRefs。
產生的 metadata
OpenClaw 必須在匯入外掛執行階段程式碼之前讀取外掛 manifest。
defineToolPlugin 會為此公開靜態 metadata,而
openclaw plugins build 會將其寫入套件。在變更外掛 id、名稱、描述、
設定 schema、啟用方式或工具名稱後,請重新執行產生器:
npm run buildopenclaw plugins build --entry ./dist/index.js單一工具外掛產生的 manifest:
{ "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 是重要的探索合約:它會告訴 OpenClaw 每個工具由哪個
外掛擁有,而不需要載入每個已安裝外掛的執行階段。過期的 manifest 可能
導致工具從探索中消失,或讓註冊錯誤被歸咎於錯誤的外掛。
套件 metadata
openclaw plugins build 也會將 package.json 對齊所選的執行階段
入口:
{ "type": "module", "files": ["dist", "openclaw.plugin.json", "README.md"], "dependencies": { "typebox": "^1.1.38" }, "peerDependencies": { "openclaw": ">=2026.5.17" }, "openclaw": { "extensions": ["./dist/index.js"] }}發布已建置的 JavaScript (./dist/index.js),而不是 TypeScript 來源入口。
來源入口只適用於工作區本機開發。
在 CI 中驗證
plugins build --check 會在產生的 metadata 過期時失敗,且不會重寫檔案:
npm run buildopenclaw plugins build --entry ./dist/index.js --checkopenclaw plugins validate --entry ./dist/index.jsnpm testplugins validate 會檢查:
openclaw.plugin.json存在,且可通過一般 manifest loader。- 目前入口會匯出
defineToolPluginmetadata。 - 產生的 manifest 欄位符合入口 metadata。
contracts.tools符合宣告的工具名稱。package.json會將openclaw.extensions指向所選的執行階段入口。
在本機安裝與檢查
從另一個 OpenClaw checkout 或已安裝的命令列介面,安裝套件路徑:
openclaw plugins install ./stock-quotesopenclaw plugins inspect stock-quotes --runtime若要進行封裝後的 smoke test,請先打包再安裝 tarball:
npm packopenclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgzopenclaw plugins inspect stock-quotes --runtime --json安裝後,重新啟動或重新載入閘道,並請代理使用該工具。如果工具不可見, 請先檢查外掛執行階段和有效的工具目錄,再變更程式碼 (請參閱疑難排解)。
發布
套件準備就緒後,透過 ClawHub 發布。clawhub package publish 會接收
來源:本機資料夾、GitHub repo (owner/repo[@ref]),或 tarball URL。
clawhub package publish ./stock-quotes --dry-runclawhub package publish ./stock-quotes使用明確的 ClawHub locator 安裝:
openclaw plugins install clawhub:your-org/stock-quotes在啟動切換期間,裸 npm 套件 spec 仍會從 npm 安裝,但 ClawHub 是 OpenClaw 外掛偏好的探索與發行介面。請參閱 ClawHub 發布 以了解 owner scope 與發布審查。
疑難排解
plugin entry not found: ./dist/index.js
所選入口檔案不存在。執行 npm run build,然後重新執行
openclaw plugins build --entry ./dist/index.js 或
openclaw plugins validate --entry ./dist/index.js。
plugin entry does not expose defineToolPlugin metadata
入口未匯出由 defineToolPlugin 建立的值。確認模組的 default export 是
defineToolPlugin(...) 結果,或使用 --entry 傳入正確入口。
openclaw.plugin.json generated metadata is stale
manifest 不再符合入口 metadata。執行:
npm run buildopenclaw plugins build --entry ./dist/index.js提交 openclaw.plugin.json 和 package.json 兩者的變更。
package.json openclaw.extensions must include ./dist/index.js
套件 metadata 指向不同的執行階段入口。執行
openclaw plugins build --entry ./dist/index.js,讓產生器將套件 metadata
對齊你打算發布的入口。
Cannot find package 'typebox'
已建置的外掛會在執行階段匯入 typebox。請將它保留在 dependencies 中,
重新安裝、重新建置,並重新執行驗證。
安裝後工具未出現
依序檢查以下項目:
openclaw plugins inspect <plugin-id> --runtimeopenclaw plugins validate --root <plugin-root> --entry ./dist/index.jsopenclaw.plugin.json具有包含預期工具名稱的contracts.tools。package.json具有openclaw.extensions: ["./dist/index.js"]。- 安裝外掛後,已重新啟動或重新載入閘道。