Building plugins
Plugins de ferramentas
defineToolPlugin cria um plugin que adiciona apenas ferramentas que podem ser chamadas pelo agente: sem
canal, provedor de modelo, hook, serviço ou backend de configuração. Ele gera os
metadados do manifesto necessários para que o OpenClaw descubra ferramentas sem carregar o código
de runtime do plugin.
Para plugins de provedor, canal, hook, serviço ou com recursos mistos, comece por Criação de plugins, Plugins de canal ou Plugins de provedor.
Requisitos
- Node 22.19+, Node 23.11+ ou Node 24+.
- Saída de pacote TypeScript ESM.
typeboxemdependencies(não apenas emdevDependencies— o plugin gerado o importa em runtime).openclaw >=2026.5.17, a primeira versão que exportaopenclaw/plugin-sdk/tool-plugin.- Uma raiz de pacote que distribua
dist/,openclaw.plugin.jsonepackage.json.
Início rápido
openclaw plugins init stock-quotes --name "Stock Quotes"cd stock-quotesnpm installnpm run plugin:buildnpm run plugin:validatenpm testplugins init cria a estrutura básica:
| Arquivo | Finalidade |
|---|---|
src/index.ts |
Entrada de defineToolPlugin com uma ferramenta echo |
src/index.test.ts |
Teste de metadados que verifica a lista de ferramentas |
tsconfig.json |
Saída TypeScript NodeNext para dist/ |
vitest.config.ts |
Configuração do Vitest para src/**/*.test.ts |
package.json |
Scripts, dependências de runtime, openclaw.extensions: ["./dist/index.js"] |
openclaw.plugin.json |
Metadados de manifesto gerados para a ferramenta inicial |
npm run plugin:build executa npm run build (tsc) e depois
openclaw plugins build --entry ./dist/index.js. npm run plugin:validate
recompila e executa openclaw plugins validate --entry ./dist/index.js.
Uma validação bem-sucedida exibe:
Plugin stock-quotes is valid.Opções de openclaw plugins init <id>:
| Flag | Padrão | Efeito |
|---|---|---|
--directory <path> |
<id> |
Diretório de saída |
--name <name> |
<id> com iniciais maiúsculas |
Nome de exibição |
--type <type> |
tool |
Tipo de estrutura: tool ou provider |
--force |
desativado | Sobrescreve um diretório de saída existente |
Escrever uma ferramenta
defineToolPlugin recebe a identidade do plugin, um schema de configuração opcional e uma
lista estática de ferramentas. Os tipos dos parâmetros e da configuração são inferidos dos
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", }; }, }), ],});Os nomes das ferramentas constituem a API estável. Escolha nomes exclusivos, em letras minúsculas e específicos o suficiente para evitar colisões com ferramentas do núcleo ou de outros plugins.
Ferramentas opcionais e baseadas em fábrica
Defina optional: true quando os usuários precisarem adicionar explicitamente a ferramenta à lista de permissões antes que ela
seja enviada a um modelo. openclaw plugins build grava a entrada de manifesto
toolMetadata.<tool>.optional correspondente, permitindo que o OpenClaw identifique que a
ferramenta é opcional sem carregar o código de runtime do plugin.
tool({ name: "workflow_run", description: "Run an external workflow.", parameters: Type.Object({ goal: Type.String() }), optional: true, execute: ({ goal }) => ({ queued: true, goal }),});Use factory quando uma ferramenta precisar do contexto de ferramentas do runtime antes que possa ser
criada — para não participar de uma execução específica, inspecionar o estado do sandbox ou vincular
helpers do runtime. Os metadados permanecem estáticos, mesmo que a ferramenta concreta seja criada
em 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); },});As fábricas ainda declaram antecipadamente um nome fixo de ferramenta. Use definePluginEntry
diretamente quando o plugin calcular nomes de ferramentas dinamicamente ou combinar ferramentas
com hooks, serviços, provedores ou comandos.
Valores de retorno
defineToolPlugin encapsula valores de retorno simples no formato de resultado de ferramenta
do OpenClaw:
- Retorne uma string quando o modelo precisar ver exatamente esse texto.
- Retorne um valor compatível com JSON quando quiser que o modelo veja JSON formatado
e que o OpenClaw mantenha o valor original em
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 }),});Use uma ferramenta baseada em fábrica quando precisar de um AgentToolResult personalizado ou quiser reutilizar uma
implementação existente de api.registerTool.
Configuração
configSchema é opcional. Omita-o e o OpenClaw aplicará um schema estrito de objeto vazio;
o manifesto gerado ainda incluirá configSchema.
export default defineToolPlugin({ id: "no-config-tools", name: "No Config Tools", description: "Adds tools that do not need configuration.", tools: () => [],});Com um configSchema, o segundo argumento de execute é tipado a partir dele:
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 }), }), ],});O OpenClaw lê a configuração do plugin na entrada correspondente ao plugin na configuração do Gateway. Não grave segredos diretamente no código-fonte nem em exemplos da documentação; use configuração, variáveis de ambiente ou SecretRefs conforme o modelo de segurança do plugin.
Metadados gerados
O OpenClaw precisa ler o manifesto do plugin antes de importar o código de runtime do plugin.
defineToolPlugin expõe metadados estáticos para isso, e
openclaw plugins build os grava no pacote. Execute novamente o gerador após
alterar o ID, o nome, a descrição, o schema de configuração, a ativação ou os nomes das
ferramentas do plugin:
npm run buildopenclaw plugins build --entry ./dist/index.jsManifesto gerado para um plugin com uma ferramenta:
{ "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 é o contrato de descoberta importante: ele informa ao OpenClaw qual
plugin é proprietário de cada ferramenta sem carregar o runtime de todos os plugins instalados. Um
manifesto desatualizado pode fazer com que uma ferramenta não seja encontrada na descoberta ou que um erro de registro
seja atribuído ao plugin errado.
Metadados do pacote
openclaw plugins build também alinha o package.json à entrada de runtime
selecionada:
{ "type": "module", "files": ["dist", "openclaw.plugin.json", "README.md"], "dependencies": { "typebox": "^1.1.38" }, "peerDependencies": { "openclaw": ">=2026.5.17" }, "openclaw": { "extensions": ["./dist/index.js"] }}Distribua o JavaScript compilado (./dist/index.js), não uma entrada de código-fonte TypeScript.
Entradas de código-fonte funcionam apenas para desenvolvimento local no workspace.
Validar na CI
plugins build --check falha sem reescrever arquivos quando os metadados gerados
estão desatualizados:
npm run buildopenclaw plugins build --entry ./dist/index.js --checkopenclaw plugins validate --entry ./dist/index.jsnpm testplugins validate verifica se:
openclaw.plugin.jsonexiste e passa pelo carregador normal de manifestos.- A entrada atual exporta metadados de
defineToolPlugin. - Os campos gerados do manifesto correspondem aos metadados da entrada.
contracts.toolscorresponde aos nomes declarados das ferramentas.package.jsonapontaopenclaw.extensionspara a entrada de runtime selecionada.
Instalar e inspecionar localmente
Em outro checkout do OpenClaw ou em uma CLI instalada, instale o caminho do pacote:
openclaw plugins install ./stock-quotesopenclaw plugins inspect stock-quotes --runtimePara um teste rápido do pacote, primeiro gere o pacote e instale o tarball:
npm packopenclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgzopenclaw plugins inspect stock-quotes --runtime --jsonApós a instalação, reinicie ou recarregue o Gateway e peça ao agente para usar a ferramenta. Se a ferramenta não estiver visível, inspecione o runtime do plugin e o catálogo efetivo de ferramentas antes de alterar o código (consulte Solução de problemas).
Publicar
Publique pelo ClawHub quando o pacote estiver pronto. clawhub package publish
recebe uma origem: uma pasta local, um repositório do GitHub (owner/repo[@ref]) ou uma
URL de tarball.
clawhub package publish ./stock-quotes --dry-runclawhub package publish ./stock-quotesInstale com um localizador explícito do ClawHub:
openclaw plugins install clawhub:your-org/stock-quotesEspecificações simples de pacotes npm ainda são instaladas pelo npm durante a transição do lançamento, mas o ClawHub é a superfície preferencial de descoberta e distribuição para plugins do OpenClaw. Consulte Publicação no ClawHub para informações sobre o escopo do proprietário e a revisão da versão.
Solução de problemas
plugin entry not found: ./dist/index.js
O arquivo de entrada selecionado não existe. Execute npm run build e depois execute novamente
openclaw plugins build --entry ./dist/index.js ou
openclaw plugins validate --entry ./dist/index.js.
plugin entry does not expose defineToolPlugin metadata
A entrada não exportou um valor criado por defineToolPlugin. Confirme se a
exportação padrão do módulo é o resultado de defineToolPlugin(...) ou forneça a
entrada correta com --entry.
openclaw.plugin.json generated metadata is stale
O manifesto não corresponde mais aos metadados da entrada. Execute:
npm run buildopenclaw plugins build --entry ./dist/index.jsInclua no commit as alterações em openclaw.plugin.json e package.json.
package.json openclaw.extensions must include ./dist/index.js
Os metadados do pacote apontam para uma entrada de runtime diferente. Execute
openclaw plugins build --entry ./dist/index.js para que o gerador alinhe
os metadados do pacote à entrada que você pretende distribuir.
Cannot find package 'typebox'
O plugin compilado importa typebox em runtime. Mantenha-o em dependencies,
reinstale, recompile e execute novamente a validação.
A ferramenta não aparece após a instalação
Verifique estes itens na ordem:
openclaw plugins inspect <plugin-id> --runtimeopenclaw plugins validate --root <plugin-root> --entry ./dist/index.jsopenclaw.plugin.jsoncontémcontracts.toolscom os nomes de ferramentas esperados.package.jsoncontémopenclaw.extensions: ["./dist/index.js"].- O Gateway foi reiniciado ou recarregado após a instalação do Plugin.