Building plugins
Plugin інструментів
Tool plugins додають до OpenClaw інструменти, які може викликати агент, без додавання каналу,
постачальника моделей, hook, сервісу або setup-бекенду. Використовуйте defineToolPlugin, коли
plugin володіє фіксованим списком інструментів і ви хочете, щоб OpenClaw згенерував manifest
metadata, яка зберігає ці інструменти доступними для виявлення без завантаження runtime-коду.
Рекомендований процес:
- Створіть каркас пакета за допомогою
openclaw plugins init. - Напишіть інструменти з
defineToolPlugin. - Зберіть JavaScript.
- Згенеруйте metadata
openclaw.plugin.jsonіpackage.jsonза допомогоюopenclaw plugins build. - Перевірте згенеровану metadata перед публікацією або встановленням.
Для plugin-ів постачальників, каналів, hook-ів, сервісів або зі змішаними можливостями натомість почніть із Побудова plugin-ів, Channel Plugins або Provider Plugins.
Вимоги
- Node >= 22.
- Вивід пакета TypeScript ESM.
typeboxдля schemas конфігурації та параметрів інструментів.openclaw >=2026.5.17, перша версія OpenClaw, яка експортуєopenclaw/plugin-sdk/tool-plugin.- Корінь пакета, який може постачати
dist/,openclaw.plugin.jsonіpackage.json.
Згенерований plugin імпортує typebox під час runtime, тому тримайте typebox у
dependencies, а не лише в devDependencies.
Швидкий старт
Створіть новий пакет plugin:
openclaw plugins init stock-quotes --name "Stock Quotes"cd stock-quotesnpm installnpm run plugin:buildnpm run plugin:validatenpm testКаркас створює:
src/index.ts: вхідdefineToolPluginз інструментомecho.src/index.test.ts: невеликий тест metadata.tsconfig.json: вивід TypeScript NodeNext уdist/.package.json: scripts, runtime dependencies іopenclaw.extensions: ["./dist/index.js"].openclaw.plugin.json: згенерована manifest metadata для початкового інструмента.
Очікуваний вивід перевірки:
Plugin stock-quotes is valid.Напишіть інструмент
defineToolPlugin приймає ідентичність plugin, необов’язкову schema конфігурації та
статичний список інструментів. Типи параметрів і конфігурації виводяться зі schemas 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", }; }, }), ],});Назви інструментів є стабільним API. Обирайте назви, які є унікальними, написані малими літерами та достатньо конкретні, щоб уникати конфліктів із core-інструментами або іншими plugin-ами.
Необов’язкові інструменти та factory-інструменти
Установіть optional: true, коли користувачі мають явно додати інструмент до allowlist перед тим, як його
буде надіслано моделі:
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 записує відповідний запис manifest toolMetadata.<tool>.optional,
щоб OpenClaw міг виявити інструмент без завантаження runtime-коду plugin.
Використовуйте factory, коли інструменту потрібен runtime-контекст інструмента, перш ніж його можна
створити. Factory зберігає metadata статичною, водночас дозволяючи інструменту відмовитися для
конкретного запуску, перевірити стан sandbox або прив’язати runtime helpers.
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); },});Factories усе ще призначені для фіксованих назв інструментів. Використовуйте definePluginEntry напряму, коли
plugin обчислює назви інструментів динамічно або поєднує інструменти з hooks,
сервісами, постачальниками, командами чи іншими runtime-поверхнями.
Значення повернення
defineToolPlugin обгортає звичайні значення повернення у формат tool-result OpenClaw:
- Поверніть рядок, коли модель має побачити саме цей текст.
- Поверніть JSON-сумісне значення, коли ви хочете, щоб модель побачила відформатований JSON,
а OpenClaw зберіг початкове значення в
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 }),});Використовуйте factory-інструмент, коли потрібно повернути власний AgentToolResult або повторно використати
наявну реалізацію api.registerTool. Використовуйте definePluginEntry замість
defineToolPlugin, коли потрібні повністю динамічні інструменти або змішані можливості plugin.
Конфігурація
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 типізується зі
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 читає конфігурацію plugin із запису plugin у конфігурації Gateway. Не вшивайте секрети в source або приклади в документації. Використовуйте конфігурацію, змінні середовища або SecretRefs відповідно до моделі безпеки plugin.
Згенерована metadata
OpenClaw виявляє встановлені plugin-и з cold metadata. Він має бути здатен прочитати
manifest plugin перед імпортом runtime-коду plugin. Тому defineToolPlugin
надає статичну metadata, а openclaw plugins build записує цю
metadata у пакет.
Запускайте генератор після зміни id, name, description, config schema, activation або назв інструментів plugin:
npm run buildopenclaw plugins build --entry ./dist/index.jsДля plugin з одним інструментом згенерований 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, який
plugin володіє кожним інструментом, без завантаження runtime кожного встановленого plugin. Якщо
manifest застарів, інструмент може бути відсутній у виявленні або за помилку реєстрації
може бути помилково звинувачено не той plugin.
Metadata пакета
Для простого процесу tool-plugin openclaw plugins build узгоджує
package.json з вибраним єдиним runtime-входом:
{ "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, для встановлених пакетів. Source
entries корисні під час розробки в workspace, але опубліковані пакети не повинні
залежати від runtime-завантаження TypeScript.
Перевірка в CI
Використовуйте plugins build --check, щоб CI падав, коли згенерована metadata застаріла, без
перезапису файлів:
npm run buildopenclaw plugins build --entry ./dist/index.js --checkopenclaw plugins validate --entry ./dist/index.jsnpm testplugins validate перевіряє, що:
openclaw.plugin.jsonіснує та проходить звичайний manifest loader.- Поточний entry експортує metadata
defineToolPlugin. - Згенеровані поля manifest збігаються з entry metadata.
contracts.toolsзбігається з оголошеними назвами інструментів.package.jsonспрямовуєopenclaw.extensionsна вибраний runtime entry.
Локальне встановлення та перевірка
З окремого checkout OpenClaw або встановленого CLI встановіть шлях пакета:
openclaw plugins install ./stock-quotesopenclaw plugins inspect stock-quotes --runtimeДля packaged smoke спершу запакуйте, а потім встановіть tarball:
npm packopenclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgzopenclaw plugins inspect stock-quotes --runtime --jsonПісля встановлення запустіть або перезапустіть Gateway і попросіть агента використати інструмент. Якщо ви налагоджуєте видимість інструментів, перевірте runtime plugin і ефективний каталог інструментів перед зміною коду.
Публікація
Публікуйте через ClawHub, коли пакет готовий:
clawhub package publish your-org/stock-quotes --dry-runclawhub package publish your-org/stock-quotesВстановлюйте з явним локатором ClawHub:
openclaw plugins install clawhub:your-org/stock-quotesBare npm package specs залишаються підтримуваними під час launch cutover, але ClawHub є пріоритетною поверхнею виявлення та розповсюдження для plugin-ів OpenClaw.
Усунення несправностей
plugin entry not found: ./dist/index.js
Вибраний entry file не існує. Запустіть npm run build, потім повторно запустіть
openclaw plugins build --entry ./dist/index.js або
openclaw plugins validate --entry ./dist/index.js.
plugin entry does not expose defineToolPlugin metadata
Entry не експортував значення, створене defineToolPlugin. Перевірте, що
default export модуля є результатом defineToolPlugin(...), або передайте правильний
entry за допомогою --entry.
openclaw.plugin.json generated metadata is stale
Manifest більше не збігається з entry 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 пакета вказує на інший runtime entry. Запустіть
openclaw plugins build --entry ./dist/index.js, щоб генератор узгодив
metadata пакета з entry, який ви маєте намір постачати.
Cannot find package 'typebox'
Зібраний plugin імпортує typebox під час runtime. Тримайте 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 було перезапущено або перезавантажено після встановлення plugin.