Saltar para o conteúdo principal

Plugins (Extensões)

Início rápido (novo em plugins?)

Um plugin é apenas um pequeno módulo de código que estende o OpenClaw com recursos extras (comandos, ferramentas e RPC do Gateway). Na maioria das vezes, você usará plugins quando quiser um recurso que ainda não está embutido no OpenClaw principal (ou quando quiser manter recursos opcionais fora da sua instalação principal). Caminho rápido:
  1. Veja o que já está carregado:
openclaw plugins list
  1. Instale um plugin oficial (exemplo: Voice Call):
openclaw plugins install @openclaw/voice-call
Especificações npm são apenas do registry (nome do pacote + versão/tag opcional). Especificações de Git/URL/arquivo são rejeitadas.
  1. Reinicie o Gateway e depois configure em plugins.entries.<id>.config.
Veja Voice Call para um exemplo concreto de plugin.

Plugins disponíveis (oficiais)

  • Microsoft Teams é apenas via plugin a partir de 2026.1.15; instale @openclaw/msteams se você usa Teams.
  • Memory (Core) — plugin de busca de memória empacotado (habilitado por padrão via plugins.slots.memory)
  • Memory (LanceDB) — plugin de memória de longo prazo empacotado (auto-recall/capture; defina plugins.slots.memory = "memory-lancedb")
  • Voice Call@openclaw/voice-call
  • Zalo Personal@openclaw/zalouser
  • Matrix@openclaw/matrix
  • Nostr@openclaw/nostr
  • Zalo@openclaw/zalo
  • Microsoft Teams@openclaw/msteams
  • Google Antigravity OAuth (autenticação de provedor) — empacotado como google-antigravity-auth (desabilitado por padrão)
  • Gemini CLI OAuth (autenticação de provedor) — empacotado como google-gemini-cli-auth (desabilitado por padrão)
  • Qwen OAuth (autenticação de provedor) — empacotado como qwen-portal-auth (desabilitado por padrão)
  • Copilot Proxy (autenticação de provedor) — ponte local do VS Code Copilot Proxy; distinto do login de dispositivo embutido github-copilot (empacotado, desabilitado por padrão)
Os plugins do OpenClaw são módulos TypeScript carregados em tempo de execução via jiti. A validação de configuração não executa código do plugin; ela usa o manifesto do plugin e o JSON Schema. Veja Plugin manifest. Os plugins podem registrar:
  • Métodos de RPC do Gateway
  • Handlers HTTP do Gateway
  • Ferramentas de agente
  • Comandos de CLI
  • Serviços em segundo plano
  • Validação opcional de configuração
  • Skills (listando diretórios skills no manifesto do plugin)
  • Comandos de resposta automática (executam sem invocar o agente de IA)
Os plugins rodam no mesmo processo do Gateway, portanto trate-os como código confiável. Guia de criação de ferramentas: Plugin agent tools.

Ajudantes de runtime

Os plugins podem acessar ajudantes principais selecionados via api.runtime. Para TTS de telefonia:
const result = await api.runtime.tts.textToSpeechTelephony({
  text: "Hello from OpenClaw",
  cfg: api.config,
});
Notas:
  • Usa a configuração principal messages.tts (OpenAI ou ElevenLabs).
  • Retorna buffer de áudio PCM + taxa de amostragem. Os plugins devem reamostrar/codificar para os provedores.
  • Edge TTS não é suportado para telefonia.

Descoberta e precedência

O OpenClaw varre, em ordem:
  1. Caminhos de configuração
  • plugins.load.paths (arquivo ou diretório)
  1. Extensões do workspace
  • <workspace>/.openclaw/extensions/*.ts
  • <workspace>/.openclaw/extensions/*/index.ts
  1. Extensões globais
  • ~/.openclaw/extensions/*.ts
  • ~/.openclaw/extensions/*/index.ts
  1. Extensões empacotadas (enviadas com o OpenClaw, desabilitadas por padrão)
  • <openclaw>/extensions/*
Plugins empacotados devem ser habilitados explicitamente via plugins.entries.<id>.enabled ou openclaw plugins enable <id>. Plugins instalados são habilitados por padrão, mas podem ser desabilitados da mesma forma. Cada plugin deve incluir um arquivo openclaw.plugin.json em sua raiz. Se um caminho apontar para um arquivo, a raiz do plugin é o diretório do arquivo e deve conter o manifesto. Se vários plugins resolverem para o mesmo id, a primeira correspondência na ordem acima vence e as cópias de menor precedência são ignoradas.

Pacotes de pacotes

Um diretório de plugin pode incluir um package.json com openclaw.extensions:
{
  "name": "my-pack",
  "openclaw": {
    "extensions": ["./src/safety.ts", "./src/tools.ts"]
  }
}
Cada entrada se torna um plugin. Se o pacote listar várias extensões, o id do plugin se torna name/<fileBase>. Se o seu plugin importar dependências npm, instale-as nesse diretório para que node_modules esteja disponível (npm install / pnpm install). Nota de segurança: openclaw plugins install instala dependências de plugins com npm install --ignore-scripts (sem scripts de ciclo de vida). Mantenha as árvores de dependência dos plugins “pure JS/TS” e evite pacotes que exijam builds em postinstall.

Metadados do catálogo de canais

Plugins de canal podem anunciar metadados de integração inicial via openclaw.channel e dicas de instalação via openclaw.install. Isso mantém o catálogo principal livre de dados. Exemplo:
{
  "name": "@openclaw/nextcloud-talk",
  "openclaw": {
    "extensions": ["./index.ts"],
    "channel": {
      "id": "nextcloud-talk",
      "label": "Nextcloud Talk",
      "selectionLabel": "Nextcloud Talk (self-hosted)",
      "docsPath": "/channels/nextcloud-talk",
      "docsLabel": "nextcloud-talk",
      "blurb": "Self-hosted chat via Nextcloud Talk webhook bots.",
      "order": 65,
      "aliases": ["nc-talk", "nc"]
    },
    "install": {
      "npmSpec": "@openclaw/nextcloud-talk",
      "localPath": "extensions/nextcloud-talk",
      "defaultChoice": "npm"
    }
  }
}
O OpenClaw também pode mesclar catálogos de canais externos (por exemplo, uma exportação de registro MPM). Coloque um arquivo JSON em um dos seguintes caminhos:
  • ~/.openclaw/mpm/plugins.json
  • ~/.openclaw/mpm/catalog.json
  • ~/.openclaw/plugins/catalog.json
Ou aponte OPENCLAW_PLUGIN_CATALOG_PATHS (ou OPENCLAW_MPM_CATALOG_PATHS) para um ou mais arquivos JSON (delimitados por vírgula/ponto e vírgula/PATH). Cada arquivo deve conter { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }.

IDs de plugin

IDs de plugin padrão:
  • Pacotes de pacotes: package.json name
  • Arquivo standalone: nome base do arquivo (~/.../voice-call.tsvoice-call)
Se um plugin exportar id, o OpenClaw o usa, mas avisa quando não corresponde ao id configurado.

Configuração

{
  plugins: {
    enabled: true,
    allow: ["voice-call"],
    deny: ["untrusted-plugin"],
    load: { paths: ["~/Projects/oss/voice-call-extension"] },
    entries: {
      "voice-call": { enabled: true, config: { provider: "twilio" } },
    },
  },
}
Campos:
  • enabled: alternância mestre (padrão: true)
  • allow: lista de permissões (opcional)
  • deny: lista de negação (opcional; a negação vence)
  • load.paths: arquivos/diretórios extras de plugin
  • entries.<id>: alternâncias por plugin + configuração
Alterações de configuração exigem reinício do gateway. Regras de validação (estritas):
  • IDs de plugin desconhecidos em entries, allow, deny ou slots são erros.
  • Chaves channels.<id> desconhecidas são erros, a menos que um manifesto de plugin declare o id do canal.
  • A configuração do plugin é validada usando o JSON Schema incorporado em openclaw.plugin.json (configSchema).
  • Se um plugin estiver desabilitado, sua configuração é preservada e um aviso é emitido.

Slots de plugin (categorias exclusivas)

Algumas categorias de plugin são exclusivas (apenas uma ativa por vez). Use plugins.slots para selecionar qual plugin é dono do slot:
{
  plugins: {
    slots: {
      memory: "memory-core", // or "none" to disable memory plugins
    },
  },
}
Se vários plugins declararem kind: "memory", apenas o selecionado carrega. Os outros são desabilitados com diagnósticos.

UI de controle (schema + rótulos)

A UI de Controle usa config.schema (JSON Schema + uiHints) para renderizar formulários melhores. O OpenClaw amplia uiHints em tempo de execução com base nos plugins descobertos:
  • Adiciona rótulos por plugin para plugins.entries.<id> / .enabled / .config
  • Mescla dicas opcionais de campos de configuração fornecidas pelo plugin em: plugins.entries.<id>.config.<field>
Se você quiser que os campos de configuração do seu plugin exibam bons rótulos/placeholders (e marquem segredos como sensíveis), forneça uiHints junto com seu JSON Schema no manifesto do plugin. Exemplo:
{
  "id": "my-plugin",
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "apiKey": { "type": "string" },
      "region": { "type": "string" }
    }
  },
  "uiHints": {
    "apiKey": { "label": "API Key", "sensitive": true },
    "region": { "label": "Region", "placeholder": "us-east-1" }
  }
}

CLI

openclaw plugins list
openclaw plugins info <id>
openclaw plugins install <path>                 # copy a local file/dir into ~/.openclaw/extensions/<id>
openclaw plugins install ./extensions/voice-call # relative path ok
openclaw plugins install ./plugin.tgz           # install from a local tarball
openclaw plugins install ./plugin.zip           # install from a local zip
openclaw plugins install -l ./extensions/voice-call # link (no copy) for dev
openclaw plugins install @openclaw/voice-call # install from npm
openclaw plugins update <id>
openclaw plugins update --all
openclaw plugins enable <id>
openclaw plugins disable <id>
openclaw plugins doctor
plugins update funciona apenas para instalações npm rastreadas em plugins.installs. Os plugins também podem registrar seus próprios comandos de nível superior (exemplo: openclaw voicecall).

API de Plugin (visão geral)

Os plugins exportam um de:
  • Uma função: (api) => { ... }
  • Um objeto: { id, name, configSchema, register(api) { ... } }

Hooks de plugin

Os plugins podem enviar hooks e registrá-los em tempo de execução. Os plugins podem incluir hooks e registrá-los em tempo de execução. Isso permite que um plugin empacote automação orientada a eventos sem uma instalação separada de pacote de hooks.

Exemplo

import { registerPluginHooksFromDir } from "openclaw/plugin-sdk";

export default function register(api) {
  registerPluginHooksFromDir(api, "./hooks");
}
Notas:
  • Diretórios de hooks seguem a estrutura normal de hooks (HOOK.md + handler.ts).
  • As regras de elegibilidade de hooks ainda se aplicam (requisitos de SO/bins/env/config).
  • Hooks gerenciados por plugin aparecem em openclaw hooks list com plugin:<id>.
  • Você não pode habilitar/desabilitar hooks gerenciados por plugin via openclaw hooks; habilite/desabilite o plugin em vez disso.

Plugins de provedor (autenticação de modelo)

Os plugins podem registrar fluxos de autenticação de provedor de modelo para que os usuários possam executar OAuth ou configuração de chave de API dentro do OpenClaw (sem scripts externos). Registre um provedor via api.registerProvider(...). Cada provedor expõe um ou mais métodos de autenticação (OAuth, chave de API, código de dispositivo etc.). Esses métodos alimentam:
  • openclaw models auth login --provider <id> [--method <id>]
Exemplo:
api.registerProvider({
  id: "acme",
  label: "AcmeAI",
  auth: [
    {
      id: "oauth",
      label: "OAuth",
      kind: "oauth",
      run: async (ctx) => {
        // Run OAuth flow and return auth profiles.
        return {
          profiles: [
            {
              profileId: "acme:default",
              credential: {
                type: "oauth",
                provider: "acme",
                access: "...",
                refresh: "...",
                expires: Date.now() + 3600 * 1000,
              },
            },
          ],
          defaultModel: "acme/opus-1",
        };
      },
    },
  ],
});
Notas:
  • run recebe um ProviderAuthContext com ajudantes prompter, runtime, openUrl e oauth.createVpsAwareHandlers.
  • Retorne configPatch quando você precisar adicionar modelos padrão ou configuração do provedor.
  • Retorne defaultModel para que --set-default possa atualizar os padrões do agente.

Registrar um canal de mensagens

Os plugins podem registrar plugins de canal que se comportam como canais embutidos (WhatsApp, Telegram etc.). A configuração do canal fica em channels.<id> e é validada pelo código do seu plugin de canal.
const myChannel = {
  id: "acmechat",
  meta: {
    id: "acmechat",
    label: "AcmeChat",
    selectionLabel: "AcmeChat (API)",
    docsPath: "/channels/acmechat",
    blurb: "demo channel plugin.",
    aliases: ["acme"],
  },
  capabilities: { chatTypes: ["direct"] },
  config: {
    listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
    resolveAccount: (cfg, accountId) =>
      cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
        accountId,
      },
  },
  outbound: {
    deliveryMode: "direct",
    sendText: async () => ({ ok: true }),
  },
};

export default function (api) {
  api.registerChannel({ plugin: myChannel });
}
Notas:
  • Coloque a configuração em channels.<id> (não em plugins.entries).
  • meta.label é usado para rótulos em listas da CLI/UI.
  • meta.aliases adiciona ids alternativos para normalização e entradas da CLI.
  • meta.preferOver lista ids de canal para pular auto-habilitação quando ambos estiverem configurados.
  • meta.detailLabel e meta.systemImage permitem que UIs mostrem rótulos/ícones de canal mais ricos.

Escrever um novo canal de mensagens (passo a passo)

Use isto quando quiser uma nova superfície de chat (um “canal de mensagens”), não um provedor de modelo. A documentação de provedores de modelo fica em /providers/*.
  1. Escolha um id + formato de configuração
  • Toda a configuração de canal fica em channels.<id>.
  • Prefira channels.<id>.accounts.<accountId> para configurações multi‑conta.
  1. Defina os metadados do canal
  • meta.label, meta.selectionLabel, meta.docsPath, meta.blurb controlam listas da CLI/UI.
  • meta.docsPath deve apontar para uma página de docs como /channels/<id>.
  • meta.preferOver permite que um plugin substitua outro canal (a auto-habilitação o prefere).
  • meta.detailLabel e meta.systemImage são usados pelas UIs para texto/ícones de detalhe.
  1. Adicione adaptadores opcionais conforme necessário
  • config.listAccountIds + config.resolveAccount
  • capabilities (tipos de chat, mídia, threads etc.)
  • outbound.deliveryMode + outbound.sendText (para envio básico)
  1. Implemente os adaptadores obrigatórios
  • setup (assistente), security (política de DM), status (saúde/diagnósticos)
  • gateway (start/stop/login), mentions, threading, streaming
  • actions (ações de mensagem), commands (comportamento de comando nativo)
  1. Registre o canal no seu plugin
  • api.registerChannel({ plugin })
Exemplo mínimo de configuração:
{
  channels: {
    acmechat: {
      accounts: {
        default: { token: "ACME_TOKEN", enabled: true },
      },
    },
  },
}
Plugin mínimo de canal (apenas saída):
const plugin = {
  id: "acmechat",
  meta: {
    id: "acmechat",
    label: "AcmeChat",
    selectionLabel: "AcmeChat (API)",
    docsPath: "/channels/acmechat",
    blurb: "AcmeChat messaging channel.",
    aliases: ["acme"],
  },
  capabilities: { chatTypes: ["direct"] },
  config: {
    listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
    resolveAccount: (cfg, accountId) =>
      cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
        accountId,
      },
  },
  outbound: {
    deliveryMode: "direct",
    sendText: async ({ text }) => {
      // deliver `text` to your channel here
      return { ok: true };
    },
  },
};

export default function (api) {
  api.registerChannel({ plugin });
}
Carregue o plugin (diretório de extensões ou plugins.load.paths), reinicie o gateway, depois configure channels.<id> na sua configuração.

Ferramentas de agente

Veja o guia dedicado: Plugin agent tools.

Registrar um método de RPC do gateway

export default function (api) {
  api.registerGatewayMethod("myplugin.status", ({ respond }) => {
    respond(true, { ok: true });
  });
}

Registrar comandos de CLI

export default function (api) {
  api.registerCli(
    ({ program }) => {
      program.command("mycmd").action(() => {
        console.log("Hello");
      });
    },
    { commands: ["mycmd"] },
  );
}

Registrar comandos de resposta automática

Os plugins podem registrar comandos personalizados de barra que executam sem invocar o agente de IA. Isso é útil para comandos de alternância, verificações de status ou ações rápidas que não precisam de processamento por LLM.
export default function (api) {
  api.registerCommand({
    name: "mystatus",
    description: "Show plugin status",
    handler: (ctx) => ({
      text: `Plugin is running! Channel: ${ctx.channel}`,
    }),
  });
}
Opções de comando:
  • senderId: O ID do remetente (se disponível)
  • channel: O canal onde o comando foi enviado
  • isAuthorizedSender: Se o remetente é um usuário autorizado
  • args: Argumentos passados após o comando (se acceptsArgs: true)
  • commandBody: O texto completo do comando
  • config: A configuração atual do OpenClaw
Opções de comando:
  • name: Nome do comando (sem o / inicial)
  • description: Texto de ajuda mostrado em listas de comandos
  • acceptsArgs: Se o comando aceita argumentos (padrão: false). Se false e argumentos forem fornecidos, o comando não corresponderá e a mensagem seguirá para outros manipuladores
  • requireAuth: Se deve exigir remetente autorizado (padrão: true)
  • handler: Função que retorna { text: string } (pode ser async)
Exemplo com autorização e argumentos:
api.registerCommand({
  name: "setmode",
  description: "Set plugin mode",
  acceptsArgs: true,
  requireAuth: true,
  handler: async (ctx) => {
    const mode = ctx.args?.trim() || "default";
    await saveMode(mode);
    return { text: `Mode set to: ${mode}` };
  },
});
Notas:
  • Comandos de plugin são processados antes dos comandos embutidos e do agente de IA
  • Os comandos são registrados globalmente e funcionam em todos os canais
  • Nomes de comando não diferenciam maiúsculas/minúsculas (/MyStatus corresponde a /mystatus)
  • Os nomes dos comandos devem começar com uma letra e conter apenas letras, números, hífens e sublinhados
  • Nomes de comando reservados (como help, status, reset, etc.) não podem ser sobrescritos por plugins
  • Registro duplicado de comandos entre plugins falhará com um erro de diagnóstico

Registrar serviços em segundo plano

export default function (api) {
  api.registerService({
    id: "my-service",
    start: () => api.logger.info("ready"),
    stop: () => api.logger.info("bye"),
  });
}

Convenções de nomenclatura

  • Métodos do Gateway: pluginId.action (exemplo: voicecall.status)
  • Ferramentas: snake_case (exemplo: voice_call)
  • Comandos de CLI: kebab ou camel, mas evite conflito com comandos principais

Skills

Os plugins podem incluir uma skill no repositório (skills/<name>/SKILL.md). Habilite-a com plugins.entries.<id>.enabled (ou outros controles de configuração) e garanta que ela esteja presente nos locais de skills do workspace/gerenciados.

Distribuição (npm)

Empacotamento recomendado:
  • Pacote principal: openclaw (este repositório)
  • Plugins: pacotes npm separados sob @openclaw/* (exemplo: @openclaw/voice-call)
Contrato de publicação:
  • O package.json do plugin deve incluir openclaw.extensions com um ou mais arquivos de entrada.
  • Os arquivos de entrada podem ser .js ou .ts (jiti carrega TS em tempo de execução).
  • openclaw plugins install <npm-spec> usa npm pack, extrai em ~/.openclaw/extensions/<id>/ e o habilita na configuração.
  • Estabilidade da chave de configuração: pacotes com escopo são normalizados para o id sem escopo em plugins.entries.*.

Plugin de exemplo: Voice Call

Este repositório inclui um plugin de chamada de voz (Twilio ou fallback de log):
  • Código-fonte: extensions/voice-call
  • Skill: skills/voice-call
  • CLI: openclaw voicecall start|status
  • Ferramenta: voice_call
  • RPC: voicecall.start, voicecall.status
  • Configuração (twilio): provider: "twilio" + twilio.accountSid/authToken/from (opcional statusCallbackUrl, twimlUrl)
  • Configuração (dev): provider: "log" (sem rede)
Veja Voice Call e extensions/voice-call/README.md para configuração e uso.

Notas de segurança

Os plugins rodam no mesmo processo do Gateway. Trate-os como código confiável:
  • Instale apenas plugins em que você confia.
  • Prefira listas de permissões plugins.allow.
  • Reinicie o Gateway após alterações.

Testando plugins

Os plugins podem (e devem) incluir testes:
  • Plugins no repositório podem manter testes Vitest em src/** (exemplo: src/plugins/voice-call.plugin.test.ts).
  • Plugins publicados separadamente devem executar sua própria CI (lint/build/test) e validar que openclaw.extensions aponta para o entrypoint compilado (dist/index.js).