Plugins (Extensiones)¶
Inicio rápido (¿nuevo en plugins?)¶
Un plugin es simplemente un pequeño módulo de código que amplía OpenClaw con funciones adicionales (comandos, herramientas y RPC del Gateway).
La mayoría de las veces, usará plugins cuando quiera una función que aún no está integrada en el núcleo de OpenClaw (o cuando quiera mantener funciones opcionales fuera de su instalación principal).
Ruta rápida:
- Vea qué ya está cargado:
openclaw plugins list
- Instale un plugin oficial (ejemplo: Voice Call):
openclaw plugins install @openclaw/voice-call
- Reinicie el Gateway y luego configure en
plugins.entries.<id>.config.
Consulte Voice Call para un ejemplo concreto de plugin.
Plugins disponibles (oficiales)¶
- Microsoft Teams es solo por plugin desde 2026.1.15; instale
@openclaw/msteamssi usa Teams. - Memory (Core) — plugin de búsqueda de memoria incluido (habilitado de forma predeterminada mediante
plugins.slots.memory) - Memory (LanceDB) — plugin de memoria a largo plazo incluido (auto‑recuperación/captura; configure
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 (auth de proveedor) — incluido como
google-antigravity-auth(deshabilitado de forma predeterminada) - Gemini CLI OAuth (auth de proveedor) — incluido como
google-gemini-cli-auth(deshabilitado de forma predeterminada) - Qwen OAuth (auth de proveedor) — incluido como
qwen-portal-auth(deshabilitado de forma predeterminada) - Copilot Proxy (auth de proveedor) — puente local de VS Code Copilot Proxy; distinto del inicio de sesión del dispositivo
github-copilotintegrado (incluido, deshabilitado de forma predeterminada)
Los plugins de OpenClaw son módulos TypeScript cargados en tiempo de ejecución mediante jiti. La validación de configuración no ejecuta código del plugin; utiliza el manifiesto del plugin y JSON Schema. Consulte Plugin manifest.
Los plugins pueden registrar:
- Métodos RPC del Gateway
- Manejadores HTTP del Gateway
- Herramientas del agente
- Comandos de la CLI
- Servicios en segundo plano
- Validación de configuración opcional
- Skills (enumerando directorios
skillsen el manifiesto del plugin) - Comandos de respuesta automática (se ejecutan sin invocar al agente de IA)
Los plugins se ejecutan en el mismo proceso que el Gateway, así que trátelos como código de confianza. Guía de creación de herramientas: Plugin agent tools.
Ayudantes de tiempo de ejecución¶
Los plugins pueden acceder a ayudantes principales seleccionados mediante api.runtime. Para TTS de telefonía:
const result = await api.runtime.tts.textToSpeechTelephony({
text: "Hello from OpenClaw",
cfg: api.config,
});
Notas:
- Usa la configuración principal
messages.tts(OpenAI o ElevenLabs). - Devuelve un búfer de audio PCM + frecuencia de muestreo. Los plugins deben remuestrear/codificar para los proveedores.
- Edge TTS no es compatible con telefonía.
Descubrimiento y precedencia¶
OpenClaw escanea, en orden:
- Rutas de configuración
plugins.load.paths(archivo o directorio)
- Extensiones del espacio de trabajo
<workspace>/.openclaw/extensions/*.ts<workspace>/.openclaw/extensions/*/index.ts
- Extensiones globales
~/.openclaw/extensions/*.ts~/.openclaw/extensions/*/index.ts
- Extensiones incluidas (enviadas con OpenClaw, deshabilitadas de forma predeterminada)
<openclaw>/extensions/*
Los plugins incluidos deben habilitarse explícitamente mediante plugins.entries.<id>.enabled
o openclaw plugins enable <id>. Los plugins instalados están habilitados de forma predeterminada,
pero pueden deshabilitarse del mismo modo.
Cada plugin debe incluir un archivo openclaw.plugin.json en su raíz. Si una ruta
apunta a un archivo, la raíz del plugin es el directorio del archivo y debe contener el
manifiesto.
Si varios plugins se resuelven al mismo id, gana la primera coincidencia en el orden anterior y las copias de menor precedencia se ignoran.
Paquetes de paquetes¶
Un directorio de plugin puede incluir un package.json con openclaw.extensions:
{
"name": "my-pack",
"openclaw": {
"extensions": ["./src/safety.ts", "./src/tools.ts"]
}
}
Cada entrada se convierte en un plugin. Si el paquete enumera múltiples extensiones, el id del plugin
pasa a ser name/<fileBase>.
Si su plugin importa dependencias npm, instálelas en ese directorio para que
node_modules esté disponible (npm install / pnpm install).
Metadatos del catálogo de canales¶
Los plugins de canal pueden anunciar metadatos de incorporación mediante openclaw.channel y
pistas de instalación mediante openclaw.install. Esto mantiene los datos del catálogo principal sin datos.
Ejemplo:
{
"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"
}
}
}
OpenClaw también puede fusionar catálogos de canales externos (por ejemplo, una exportación de registro MPM). Coloque un archivo JSON en uno de:
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
O apunte OPENCLAW_PLUGIN_CATALOG_PATHS (o OPENCLAW_MPM_CATALOG_PATHS) a
uno o más archivos JSON (delimitados por coma/punto y coma/PATH). Cada archivo debe
contener { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }.
IDs de plugins¶
IDs de plugin predeterminados:
- Paquetes de paquetes:
package.jsonname - Archivo independiente: nombre base del archivo (
~/.../voice-call.ts→voice-call)
Si un plugin exporta id, OpenClaw lo usa pero advierte cuando no coincide con el
id configurado.
Configuración¶
{
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: interruptor maestro (predeterminado: true)allow: lista de permitidos (opcional)deny: lista de denegados (opcional; la denegación gana)load.paths: archivos/directorios adicionales del pluginentries.<id>: interruptores por plugin + configuración
Los cambios de configuración requieren reiniciar el Gateway.
Reglas de validación (estrictas):
- IDs de plugin desconocidos en
entries,allow,denyoslotsson errores. - Claves
channels.<id>desconocidas son errores a menos que un manifiesto del plugin declare el id del canal. - La configuración del plugin se valida usando el JSON Schema incrustado en
openclaw.plugin.json(configSchema). - Si un plugin está deshabilitado, su configuración se conserva y se emite una advertencia.
Ranuras de plugins (categorías exclusivas)¶
Algunas categorías de plugins son exclusivas (solo una activa a la vez). Use
plugins.slots para seleccionar qué plugin posee la ranura:
{
plugins: {
slots: {
memory: "memory-core", // or "none" to disable memory plugins
},
},
}
Si varios plugins declaran kind: "memory", solo se carga el seleccionado. Los demás
se deshabilitan con diagnósticos.
UI de control (schema + etiquetas)¶
La UI de Control usa config.schema (JSON Schema + uiHints) para renderizar mejores formularios.
OpenClaw amplía uiHints en tiempo de ejecución según los plugins descubiertos:
- Agrega etiquetas por plugin para
plugins.entries.<id>/.enabled/.config - Fusiona pistas de campos de configuración opcionales proporcionadas por plugins bajo:
plugins.entries.<id>.config.<field>
Si desea que los campos de configuración de su plugin muestren buenas etiquetas/marcadores de posición (y marcar secretos como sensibles),
proporcione uiHints junto con su JSON Schema en el manifiesto del plugin.
Ejemplo:
{
"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 solo funciona para instalaciones npm registradas bajo plugins.installs.
Los plugins también pueden registrar sus propios comandos de nivel superior (ejemplo: openclaw voicecall).
API de plugins (resumen)¶
Los plugins exportan cualquiera de:
- Una función:
(api) => { ... } - Un objeto:
{ id, name, configSchema, register(api) { ... } }
Hooks de plugins¶
Los plugins pueden incluir hooks y registrarlos en tiempo de ejecución. Esto permite que un plugin agrupe automatización basada en eventos sin una instalación separada de paquetes de hooks.
Ejemplo¶
import { registerPluginHooksFromDir } from "openclaw/plugin-sdk";
export default function register(api) {
registerPluginHooksFromDir(api, "./hooks");
}
Notas:
- Los directorios de hooks siguen la estructura normal de hooks (
HOOK.md+handler.ts). - Las reglas de elegibilidad de hooks aún aplican (SO/binarios/variables de entorno/requisitos de configuración).
- Los hooks administrados por plugins aparecen en
openclaw hooks listconplugin:<id>. - No puede habilitar/deshabilitar hooks administrados por plugins mediante
openclaw hooks; habilite/deshabilite el plugin en su lugar.
Plugins de proveedor (auth de modelo)¶
Los plugins pueden registrar flujos de auth de proveedor de modelo para que los usuarios puedan ejecutar OAuth o configuración de clave de API dentro de OpenClaw (no se necesitan scripts externos).
Registre un proveedor mediante api.registerProvider(...). Cada proveedor expone uno
o más métodos de autenticación (OAuth, clave de API, código de dispositivo, etc.). Estos métodos alimentan:
openclaw models auth login --provider <id> [--method <id>]
Ejemplo:
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:
runrecibe unProviderAuthContextcon ayudantesprompter,runtime,openUrlyoauth.createVpsAwareHandlers.- Devuelva
configPatchcuando necesite agregar modelos predeterminados o configuración del proveedor. - Devuelva
defaultModelpara que--set-defaultpueda actualizar los valores predeterminados del agente.
Registrar un canal de mensajería¶
Los plugins pueden registrar plugins de canal que se comportan como canales integrados
(WhatsApp, Telegram, etc.). La configuración del canal vive bajo channels.<id> y es
validada por el código de su 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 la configuración bajo
channels.<id>(noplugins.entries). meta.labelse usa para etiquetas en listas de CLI/UI.meta.aliasesagrega ids alternativos para normalización y entradas de la CLI.meta.preferOverenumera ids de canal para omitir la habilitación automática cuando ambos están configurados.meta.detailLabelymeta.systemImagepermiten que las UIs muestren etiquetas/iconos de canal más ricos.
Escribir un nuevo canal de mensajería (paso a paso)¶
Use esto cuando quiera una nueva superficie de chat (un “canal de mensajería”), no un proveedor de modelos.
La documentación de proveedores de modelos vive bajo /providers/*.
- Elija un id + forma de configuración
- Toda la configuración del canal vive bajo
channels.<id>. - Prefiera
channels.<id>.accounts.<accountId>para configuraciones de múltiples cuentas.
- Defina los metadatos del canal
meta.label,meta.selectionLabel,meta.docsPath,meta.blurbcontrolan listas de CLI/UI.meta.docsPathdebería apuntar a una página de documentación como/channels/<id>.meta.preferOverpermite que un plugin reemplace otro canal (la habilitación automática lo prefiere).meta.detailLabelymeta.systemImageson usados por las UIs para texto/iconos de detalle.
- Implemente los adaptadores requeridos
config.listAccountIds+config.resolveAccountcapabilities(tipos de chat, medios, hilos, etc.)outbound.deliveryMode+outbound.sendText(para envío básico)
- Agregue adaptadores opcionales según sea necesario
setup(asistente),security(política de DM),status(salud/diagnósticos)gateway(inicio/detención/inicio de sesión),mentions,threading,streamingactions(acciones de mensaje),commands(comportamiento de comandos nativos)
- Registre el canal en su plugin
api.registerChannel({ plugin })
Ejemplo mínimo de configuración:
{
channels: {
acmechat: {
accounts: {
default: { token: "ACME_TOKEN", enabled: true },
},
},
},
}
Plugin de canal mínimo (solo salida):
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 });
}
Cargue el plugin (directorio de extensiones o plugins.load.paths), reinicie el gateway,
luego configure channels.<id> en su configuración.
Herramientas del agente¶
Consulte la guía dedicada: Plugin agent tools.
Registrar un método RPC del gateway¶
export default function (api) {
api.registerGatewayMethod("myplugin.status", ({ respond }) => {
respond(true, { ok: true });
});
}
Registrar comandos de la CLI¶
export default function (api) {
api.registerCli(
({ program }) => {
program.command("mycmd").action(() => {
console.log("Hello");
});
},
{ commands: ["mycmd"] },
);
}
Registrar comandos de respuesta automática¶
Los plugins pueden registrar comandos de barra personalizados que se ejecutan sin invocar al agente de IA. Esto es útil para comandos de alternancia, verificaciones de estado o acciones rápidas que no necesitan procesamiento de LLM.
export default function (api) {
api.registerCommand({
name: "mystatus",
description: "Show plugin status",
handler: (ctx) => ({
text: `Plugin is running! Channel: ${ctx.channel}`,
}),
});
}
Contexto del manejador de comandos:
senderId: El ID del remitente (si está disponible)channel: El canal donde se envió el comandoisAuthorizedSender: Si el remitente es un usuario autorizadoargs: Argumentos pasados después del comando (siacceptsArgs: true)commandBody: El texto completo del comandoconfig: La configuración actual de OpenClaw
Opciones del comando:
name: Nombre del comando (sin el/inicial)description: Texto de ayuda mostrado en listas de comandosacceptsArgs: Si el comando acepta argumentos (predeterminado: false). Si es false y se proporcionan argumentos, el comando no coincidirá y el mensaje pasará a otros manejadoresrequireAuth: Si requiere remitente autorizado (predeterminado: true)handler: Función que devuelve{ text: string }(puede ser async)
Ejemplo con autorización y 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:
- Los comandos de plugins se procesan antes de los comandos integrados y del agente de IA
- Los comandos se registran globalmente y funcionan en todos los canales
- Los nombres de comandos no distinguen mayúsculas/minúsculas (
/MyStatuscoincide con/mystatus) - Los nombres de comandos deben comenzar con una letra y contener solo letras, números, guiones y guiones bajos
- Los nombres de comandos reservados (como
help,status,reset, etc.) no pueden ser reemplazados por plugins - El registro duplicado de comandos entre plugins fallará con un error de diagnóstico
Registrar servicios en segundo plano¶
export default function (api) {
api.registerService({
id: "my-service",
start: () => api.logger.info("ready"),
stop: () => api.logger.info("bye"),
});
}
Convenciones de nombres¶
- Métodos del Gateway:
pluginId.action(ejemplo:voicecall.status) - Herramientas:
snake_case(ejemplo:voice_call) - Comandos de la CLI: kebab o camel, pero evite colisiones con comandos principales
Skills¶
Los plugins pueden incluir una skill en el repositorio (skills/<name>/SKILL.md).
Habilítela con plugins.entries.<id>.enabled (u otras puertas de configuración) y asegúrese de que
esté presente en las ubicaciones de skills de su espacio de trabajo/administradas.
Distribución (npm)¶
Empaquetado recomendado:
- Paquete principal:
openclaw(este repositorio) - Plugins: paquetes npm separados bajo
@openclaw/*(ejemplo:@openclaw/voice-call)
Contrato de publicación:
- El
package.jsondel plugin debe incluiropenclaw.extensionscon uno o más archivos de entrada. - Los archivos de entrada pueden ser
.jso.ts(jiti carga TS en tiempo de ejecución). openclaw plugins install <npm-spec>usanpm pack, extrae en~/.openclaw/extensions/<id>/y lo habilita en la configuración.- Estabilidad de claves de configuración: los paquetes con ámbito se normalizan al id sin ámbito para
plugins.entries.*.
Ejemplo de plugin: Voice Call¶
Este repositorio incluye un plugin de llamadas de voz (Twilio o respaldo de registro):
- Código fuente:
extensions/voice-call - Skill:
skills/voice-call - CLI:
openclaw voicecall start|status - Herramienta:
voice_call - RPC:
voicecall.start,voicecall.status - Configuración (twilio):
provider: "twilio"+twilio.accountSid/authToken/from(opcionalstatusCallbackUrl,twimlUrl) - Configuración (dev):
provider: "log"(sin red)
Consulte Voice Call y extensions/voice-call/README.md para configuración y uso.
Notas de seguridad¶
Los plugins se ejecutan en el mismo proceso que el Gateway. Trátelos como código de confianza:
- Instale solo plugins en los que confíe.
- Prefiera listas de permitidos
plugins.allow. - Reinicie el Gateway después de los cambios.
Pruebas de plugins¶
Los plugins pueden (y deben) incluir pruebas:
- Los plugins en el repositorio pueden mantener pruebas de Vitest bajo
src/**(ejemplo:src/plugins/voice-call.plugin.test.ts). - Los plugins publicados por separado deben ejecutar su propio CI (lint/build/test) y validar que
openclaw.extensionsapunte al punto de entrada compilado (dist/index.js).