Appearance
OpenClaw 工具插件用于向智能体添加可调用函数,无需实现渠道、模型提供商或其他后端。使用 defineToolPlugin 定义固定工具列表,OpenClaw 自动生成清单元数据,使工具可被发现但不加载运行时代码。推荐流程:openclaw plugins init 脚手架 → 编写工具 → openclaw plugins build 生成元数据 → openclaw plugins validate 验证。要求 Node >= 22、TypeScript ESM 输出、typebox 在 runtime dependencies,并且 openclaw >=2026.5.17。验证通过后可通过 ClawHub 发布或在本地安装。
OpenClaw 工具插件配置与 defineToolPlugin 使用指南
工具插件为 OpenClaw 添加智能体可调用的工具,不加渠道、模型提供商、钩子、服务或设置后端。当插件拥有固定工具列表,且希望 OpenClaw 在不加载运行时代码的情况下生成元数据使工具被发现时,使用 defineToolPlugin。
推荐流程:
- 用
openclaw plugins init脚手架创建包。 - 用
defineToolPlugin编写工具。 - 构建 JavaScript。
- 用
openclaw plugins build生成openclaw.plugin.json和package.json元数据。 - 在发布或安装前验证生成的元数据。
如需实现提供商、渠道、钩子、服务或混合能力插件,请参考 构建插件、渠道插件 或 提供商插件。
要求
- Node >= 22
- TypeScript ESM 包输出
typebox用于配置和工具参数 schemaopenclaw >=2026.5.17(首个导出openclaw/plugin-sdk/tool-plugin的版本)- 包根目录必须能部署
dist/、openclaw.plugin.json和package.json
生成的插件在运行时导入 typebox,因此 typebox 必须置于 dependencies,不能仅在 devDependencies。
快速开始
创建新插件包:
bash
openclaw plugins init stock-quotes --name "Stock Quotes"
cd stock-quotes
npm install
npm run plugin:build
npm run plugin:validate
npm test脚手架创建的内容:
src/index.ts:一个包含echo工具的defineToolPlugin入口。src/index.test.ts:小型元数据测试。tsconfig.json:NodeNext TypeScript 输出到dist/。package.json:脚本、运行时依赖和openclaw.extensions: ["./dist/index.js"]。openclaw.plugin.json:初始工具生成的清单元数据。
验证预期输出:
text
Plugin stock-quotes is valid.编写工具
defineToolPlugin 接受插件标识、可选配置 schema 和静态工具列表。参数和配置类型从 TypeBox schema 推断。
typescript
import { Type } from "typebox";
import { defineToolPlugin } from "openclaw/plugin-sdk/tool-plugin";
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。选择唯一、小写、足够具体的名称,避免与核心工具或其他插件冲突。
可选工具与工厂工具
可选工具
设置 optional: true,用户必须显式允许列表后才发送给模型:
typescript
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 会写入匹配的 toolMetadata.<tool>.optional 清单条目,OpenClaw 无需加载插件运行时即可发现该工具。
工厂工具
当工具需要运行时环境才能创建时使用 factory。工厂保持元数据静态,同时让工具根据运行环境选择退出、检查沙箱状态或绑定运行时辅助。
typescript
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);
},
});工厂仍用于固定工具名。如需动态计算工具名或将工具与钩子、服务、提供商、命令或其他运行时面组合,应直接使用 definePluginEntry。
返回值
defineToolPlugin 将简单返回值包装为 OpenClaw 工具结果格式:
- 返回字符串:模型看到该文本。
- 返回 JSON 兼容值:模型看到格式化 JSON,OpenClaw 在
details中保留原始值。
typescript
tool({
name: "echo_text",
description: "Echo input text.",
parameters: Type.Object({
input: Type.String(),
}),
execute: ({ input }) => input,
});typescript
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 实现,请使用工厂工具。需要完全动态工具或混合插件能力时,使用 definePluginEntry 替代 defineToolPlugin。
配置
configSchema 可选。如果省略,OpenClaw 使用严格空对象 schema,生成的清单仍包含 configSchema。
typescript
export default defineToolPlugin({
id: "no-config-tools",
name: "No Config Tools",
description: "Adds tools that do not need configuration.",
tools: () => [],
});包含 configSchema 时,第二个 execute 参数类型从 schema 推断:
typescript
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 从 Gateway 配置中的插件条目读取插件配置。不要在源码或文档示例中硬编码密钥。根据插件安全模型使用配置、环境变量或 SecretRef。
生成的元数据
OpenClaw 从冷元数据发现已安装插件,必须在导入插件运行时代码前读取插件清单。因此 defineToolPlugin 暴露静态元数据,openclaw plugins build 将元数据写入包。
更改插件 id、name、description、配置 schema、activation 或工具名后运行生成器:
bash
npm run build
openclaw plugins build --entry ./dist/index.js单工具插件的生成清单示例:
json
{
"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 每个工具所属的插件,无需加载每个已安装插件的运行时。如果清单过时,工具可能缺失或注册错误归咎到错误插件。
包元数据
对于简单的工具插件工作流,openclaw plugins build 将 package.json 对齐到选定的单一运行时入口:
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 让 CI 在生成元数据过时时失败,不重写文件:
bash
npm run build
openclaw plugins build --entry ./dist/index.js --check
openclaw plugins validate --entry ./dist/index.js
npm testplugins validate 检查:
openclaw.plugin.json存在且通过常规清单加载器。- 当前入口导出
defineToolPlugin元数据。 - 生成的清单字段与入口元数据匹配。
contracts.tools与声明的工具名一致。package.json的openclaw.extensions指向所选运行时入口。
本地安装与检查
从其他 OpenClaw 检出或已安装的 CLI 中安装包路径:
bash
openclaw plugins install ./stock-quotes
openclaw plugins inspect stock-quotes --runtime进行打包冒烟测试,先 pack 再安装 tarball:
bash
npm pack
openclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgz
openclaw plugins inspect stock-quotes --runtime --json安装后,启动或重启 Gateway 并要求智能体使用工具。如果调试工具可见性,在修改代码前检查插件运行时和有效工具目录。
发布
当包就绪后通过 ClawHub 发布:
bash
clawhub package publish your-org/stock-quotes --dry-run
clawhub package publish your-org/stock-quotes使用显式 ClawHub 定位器安装:
bash
openclaw plugins install clawhub:your-org/stock-quotes裸 npm 包规范在过渡期间仍然支持,但 ClawHub 是 OpenClaw 插件首选的发现和分发表面。
常见问题排查
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 创建的值。检查模块默认导出是否为 defineToolPlugin(...) 结果,或通过 --entry 传递正确的入口文件。
openclaw.plugin.json generated metadata is stale 怎么更新?
清单不再与入口元数据匹配。运行:
bash
npm run build
openclaw plugins build --entry ./dist/index.js提交 openclaw.plugin.json 和 package.json 的更改。
package.json openclaw.extensions must include ./dist/index.js 错误如何修复?
包元数据指向了不同的运行时入口。运行 openclaw plugins build --entry ./dist/index.js 使生成器将包元数据对齐到你打算发布的入口。
Cannot find package 'typebox' 怎么办?
构建的插件在运行时导入 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"]。- 安装插件后是否重启或重载了 Gateway。
常见问题
如何区分 defineToolPlugin 和工厂工具?
defineToolPlugin 用于固定工具列表。工厂工具(factory)用于需要运行时信息(如沙箱状态)才能决定是否创建工具的场景。如果工具名是动态的,或需要混合其他插件能力,应使用 definePluginEntry。
为什么工具安装后智能体无法调用?
先确认插件已验证通过(openclaw plugins validate),然后重启 Gateway。使用 openclaw plugins inspect 检查工具是否已注册,并检查 Gateway 日志中是否有工具调用错误。如果工具标记为 optional,还需用户在渠道或工作区配置中显式启用。
typebox 版本不兼容导致构建失败怎么办?
确保 typebox 版本与 openclaw 要求匹配(package.json 中的 peerDependencies)。建议锁定 typebox 为 ^1.1.38(OpenClaw >=2026.5.17 的兼容版本)。如果仍出错,运行 npm dedupe 或删除 node_modules 和 package-lock.json 后重新安装。