跳转到内容

工具插件

工具插件向 OpenClaw 添加 agent 可调用的工具,而无需添加渠道、模型提供商、钩子、服务或设置后端。当插件拥有固定的工具列表,并且您希望 OpenClaw 生成清单元数据以使这些工具在无需加载运行时代码的情况下可被发现时,请使用 OpenClawdefineToolPluginOpenClaw。

推荐的流程如下:

  1. 使用 openclaw plugins init 搭建一个包。
  2. 使用 defineToolPlugin 编写工具。
  3. 构建 JavaScript。
  4. 使用 openclaw plugins build 生成 openclaw.plugin.jsonpackage.json 元数据。
  5. 在发布或安装之前验证生成的元数据。

对于提供商、渠道、钩子、服务或混合功能插件,请从 构建插件渠道插件提供商插件 开始。

  • Node >= 22。
  • TypeScript ESM 包输出。
  • 用于配置和工具参数架构的 typebox
  • openclaw >=2026.5.17OpenClaw,第一个导出 openclaw/plugin-sdk/tool-plugin 的 OpenClaw 版本。
  • 一个可以包含 dist/openclaw.plugin.jsonpackage.json 的包根目录。

生成的插件在运行时导入 typebox,因此请将 typebox 保留在 dependencies 中,而不仅仅是 devDependencies 中。

创建一个新的插件包:

Terminal window
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:输出到 dist/ 的 NodeNext TypeScript 输出。
  • package.json:脚本、运行时依赖项和 openclaw.extensions: ["./dist/index.js"]
  • openclaw.plugin.json:为初始工具生成的清单元数据。

预期的验证输出:

Plugin stock-quotes is valid.

defineToolPlugin 接受插件标识、可选的配置架构以及 静态工具列表。参数和配置类型从 TypeBox 架构推断。

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

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。工厂保持元数据静态,同时允许工具 针对特定运行退出、检查沙盒状态或绑定运行时辅助程序。

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 并且希望 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 实现时,请使用工厂工具。当您需要完全动态的工具或混合插件 功能时,请使用 definePluginEntry 代替 defineToolPlugin

configSchema 是可选的。如果省略它,OpenClaw 将使用严格的空对象 架构,且生成的清单仍包含 configSchema

export default defineToolPlugin({
id: "no-config-tools",
name: "No Config Tools",
description: "Adds tools that do not need configuration.",
tools: () => [],
});

当您包含 configSchema 时,第二个 execute 参数是根据 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 从 Gateway(网关) 配置中的插件条目读取插件配置。不要在源代码或文档示例中硬编码机密信息。根据插件的安全模型,使用配置、环境变量或 SecretRefs。

OpenClaw 从冷元数据中发现已安装的插件。它必须能够在导入插件运行时代码之前读取插件清单。OpenClawdefineToolPlugin 因此会公开静态元数据,而 openclaw plugins build 会将该元数据写入包中。

在更改插件 id、名称、描述、配置架构、激活或工具名称后,请运行生成器:

Terminal window
npm run build
openclaw plugins build --entry ./dist/index.js

对于单一工具插件,生成的清单如下所示:

{
"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.toolsOpenClaw 是重要的发现契约。它告诉 OpenClaw 哪个插件拥有每个工具,而无需加载每个已安装的插件运行时。如果清单过时,工具可能会在发现中丢失,或者注册错误可能会归咎于错误的插件。

对于简单的工具插件工作流,openclaw plugins buildpackage.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 运行时加载。

当生成的元数据过时,使用 plugins build --check 使 CI 失败而不重写文件:

Terminal window
npm run build
openclaw plugins build --entry ./dist/index.js --check
openclaw plugins validate --entry ./dist/index.js
npm test

plugins validate 检查以下内容:

  • openclaw.plugin.json 存在并通过正常的清单加载器。
  • 当前条目导出 defineToolPlugin 元数据。
  • 生成的清单字段与条目元数据匹配。
  • contracts.tools 与声明的工具名称匹配。
  • package.jsonopenclaw.extensions 指向选定的运行时条目。

从单独的 OpenClaw 检出或已安装的 CLI 中,安装包路径:

Terminal window
openclaw plugins install ./stock-quotes
openclaw plugins inspect stock-quotes --runtime

对于打包的 smoke 测试,请先打包并安装 tarball:

Terminal window
npm pack
openclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgz
openclaw plugins inspect stock-quotes --runtime --json

安装完成后,启动或重启 Gateway(网关) 并要求 agent 使用该工具。如果您正在调试工具可见性,请在更改代码之前检查插件运行时和有效工具目录。

当包准备就绪时,通过 ClawHub 发布:

Terminal window
clawhub package publish your-org/stock-quotes --dry-run
clawhub package publish your-org/stock-quotes

使用显式的 ClawHub 定位符安装:

Terminal window
openclaw plugins install clawhub:your-org/stock-quotes

在启动切换期间,仍然支持裸 npm 包规范,但 ClawHub 是 OpenClaw 插件的首选发现和分发平台。

所选入口文件不存在。运行 npm run build,然后重新运行 openclaw plugins build --entry ./dist/index.jsopenclaw plugins validate --entry ./dist/index.js

plugin entry does not expose defineToolPlugin metadata

Section titled “plugin entry does not expose defineToolPlugin metadata”

入口未导出由 defineToolPlugin 创建的值。请检查模块默认导出是否为 defineToolPlugin(...) 结果,或使用 --entry 传递正确的入口。

openclaw.plugin.json generated metadata is stale

Section titled “openclaw.plugin.json generated metadata is stale”

清单不再与入口元数据匹配。运行:

Terminal window
npm run build
openclaw plugins build --entry ./dist/index.js

提交 openclaw.plugin.jsonpackage.json 的更改。

package.json openclaw.extensions must include ./dist/index.js

Section titled “package.json openclaw.extensions must include ./dist/index.js”

包元数据指向不同的运行时入口。运行 openclaw plugins build --entry ./dist/index.js,以便生成器将包元数据与您打算发布的入口对齐。

构建的插件在运行时导入 typebox。请将 typebox 保留在 dependencies 中,重新安装包依赖项,重新构建,然后重新运行验证。

按顺序检查以下内容:

  1. openclaw plugins inspect <plugin-id> --runtime
  2. openclaw plugins validate --root <plugin-root> --entry ./dist/index.js
  3. openclaw.plugin.json 具有包含预期工具名称的 contracts.tools
  4. package.json 具有 openclaw.extensions: ["./dist/index.js"]
  5. 安装插件后,Gateway(网关) 已重新启动或重新加载。