Building plugins
Plugins для инструментов
Плагины инструментов добавляют в OpenClaw инструменты, вызываемые агентом, без добавления канала,
поставщика модели, hook, сервиса или backend настройки. Используйте defineToolPlugin, когда
плагин владеет фиксированным списком инструментов и вы хотите, чтобы OpenClaw сгенерировал
метаданные манифеста, которые сохраняют эти инструменты доступными для обнаружения без загрузки runtime-кода.
Рекомендуемый процесс:
- Создайте каркас пакета с помощью
openclaw plugins init. - Напишите инструменты с
defineToolPlugin. - Соберите JavaScript.
- Сгенерируйте метаданные
openclaw.plugin.jsonиpackage.jsonс помощьюopenclaw plugins build. - Проверьте сгенерированные метаданные перед публикацией или установкой.
Для плагинов поставщиков, каналов, hook, сервисов или плагинов со смешанными возможностями начните с Создание плагинов, Плагины каналов или Плагины поставщиков.
Требования
- Node >= 22.
- Вывод пакета TypeScript ESM.
typeboxдля схем конфигурации и параметров инструментов.openclaw >=2026.5.17, первая версия OpenClaw, которая экспортируетopenclaw/plugin-sdk/tool-plugin.- Корень пакета, который может поставлять
dist/,openclaw.plugin.jsonиpackage.json.
Сгенерированный плагин импортирует typebox во время выполнения, поэтому держите typebox в
dependencies, а не только в devDependencies.
Быстрый старт
Создайте новый пакет плагина:
openclaw plugins init stock-quotes --name "Stock Quotes"cd stock-quotesnpm installnpm run plugin:buildnpm run plugin:validatenpm testКаркас создает:
src/index.ts: entrydefineToolPluginс инструментомecho.src/index.test.ts: небольшой тест метаданных.tsconfig.json: вывод TypeScript NodeNext вdist/.package.json: скрипты, runtime-зависимости иopenclaw.extensions: ["./dist/index.js"].openclaw.plugin.json: сгенерированные метаданные манифеста для начального инструмента.
Ожидаемый вывод проверки:
Plugin stock-quotes is valid.Написание инструмента
defineToolPlugin принимает идентификацию плагина, необязательную схему конфигурации и
статический список инструментов. Типы параметров и конфигурации выводятся из схем 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 или другими плагинами.
Необязательные и фабричные инструменты
Установите 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 записывает соответствующую запись манифеста toolMetadata.<tool>.optional,
чтобы OpenClaw мог обнаружить инструмент без загрузки runtime-кода плагина.
Используйте factory, когда инструменту нужен runtime-контекст инструмента, прежде чем его можно будет
создать. Фабрика сохраняет метаданные статическими, позволяя инструменту отказаться от конкретного запуска,
проверить состояние sandbox или привязать 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); },});Фабрики по-прежнему предназначены для фиксированных имен инструментов. Используйте definePluginEntry напрямую, когда
плагин вычисляет имена инструментов динамически или объединяет инструменты с hook,
сервисами, поставщиками, командами или другими runtime-поверхностями.
Возвращаемые значения
defineToolPlugin оборачивает простые возвращаемые значения в формат результата инструмента 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 }),});Используйте фабричный инструмент, когда нужно вернуть собственный 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 типизируется на основе
схемы:
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 обнаруживает установленные плагины по холодным метаданным. Он должен уметь читать
манифест плагина до импорта runtime-кода плагина. Поэтому defineToolPlugin
предоставляет статические метаданные, а openclaw plugins build записывает эти
метаданные в пакет.
Запускайте генератор после изменения id, имени, описания, схемы конфигурации, активации или имен инструментов плагина:
npm run buildopenclaw 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.tools — важный контракт обнаружения. Он сообщает OpenClaw, какой
плагин владеет каждым инструментом, без загрузки runtime-кода каждого установленного плагина. Если
манифест устарел, инструмент может отсутствовать при обнаружении или неправильный плагин
может быть указан как причина ошибки регистрации.
Метаданные пакета
Для простого процесса 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, для установленных пакетов. Исходные
entry полезны при разработке в workspace, но опубликованные пакеты не должны
зависеть от runtime-загрузки TypeScript.
Проверка в CI
Используйте plugins build --check, чтобы CI падал, когда сгенерированные метаданные устарели, без
перезаписи файлов:
npm run buildopenclaw plugins build --entry ./dist/index.js --checkopenclaw plugins validate --entry ./dist/index.jsnpm testplugins validate проверяет, что:
openclaw.plugin.jsonсуществует и проходит обычный загрузчик манифеста.- Текущая entry экспортирует метаданные
defineToolPlugin. - Сгенерированные поля манифеста соответствуют метаданным entry.
contracts.toolsсоответствует объявленным именам инструментов.package.jsonуказываетopenclaw.extensionsна выбранную runtime-entry.
Локальная установка и проверка
Из отдельного checkout OpenClaw или установленного CLI установите путь пакета:
openclaw plugins install ./stock-quotesopenclaw plugins inspect stock-quotes --runtimeДля пакетного smoke сначала упакуйте и установите tarball:
npm packopenclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgzopenclaw plugins inspect stock-quotes --runtime --jsonПосле установки запустите или перезапустите Gateway и попросите агента использовать инструмент. Если вы отлаживаете видимость инструмента, проверьте runtime плагина и эффективный каталог инструментов перед изменением кода.
Публикация
Публикуйте через ClawHub, когда пакет готов:
clawhub package publish your-org/stock-quotes --dry-runclawhub package publish your-org/stock-quotesУстановите с явным локатором ClawHub:
openclaw plugins install clawhub:your-org/stock-quotesПростые npm package specs остаются поддерживаемыми во время перехода при запуске, но ClawHub является предпочтительной поверхностью обнаружения и распространения для плагинов OpenClaw.
Устранение неполадок
plugin entry not found: ./dist/index.js
Выбранный entry-файл не существует. Запустите 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
Манифест больше не соответствует метаданным entry. Запустите:
npm run buildopenclaw plugins build --entry ./dist/index.jsЗакоммитьте изменения как openclaw.plugin.json, так и package.json.
package.json openclaw.extensions must include ./dist/index.js
Метаданные пакета указывают на другую runtime-entry. Запустите
openclaw plugins build --entry ./dist/index.js, чтобы генератор выровнял
метаданные пакета с entry, которую вы собираетесь поставлять.
Cannot find package 'typebox'
Собранный плагин импортирует typebox во время выполнения. Держите typebox в
dependencies, переустановите зависимости пакета, пересоберите и повторно выполните проверку.
Инструмент не появляется после установки
Проверьте следующее по порядку:
openclaw plugins inspect <plugin-id> --runtimeopenclaw plugins validate --root <plugin-root> --entry ./dist/index.js- В
openclaw.plugin.jsonестьcontracts.toolsс ожидаемыми именами инструментов. - В
package.jsonестьopenclaw.extensions: ["./dist/index.js"]. - Gateway был перезапущен или перезагружен после установки плагина.