Internos de plugins
Esta es la referencia de arquitectura profunda. Para guías prácticas, consulta:
- Instalar y usar plugins — guía de usuario
- Primeros pasos — primer tutorial de plugins
- Plugins de canal — crea un canal de mensajería
- Plugins de proveedor — crea un proveedor de modelos
- Descripción general del SDK — mapa de importaciones y API de registro
Modelo público de capacidades
Las capacidades son el modelo público de plugins nativos dentro de OpenClaw. Cada plugin nativo de OpenClaw se registra en uno o más tipos de capacidad:| Capacidad | Método de registro | Plugins de ejemplo |
|---|---|---|
| Inferencia de texto | api.registerProvider(...) | openai, anthropic |
| Backend de inferencia de CLI | api.registerCliBackend(...) | openai, anthropic |
| Voz | api.registerSpeechProvider(...) | elevenlabs, microsoft |
| Transcripción en tiempo real | api.registerRealtimeTranscriptionProvider(...) | openai |
| Voz en tiempo real | api.registerRealtimeVoiceProvider(...) | openai |
| Comprensión de medios | api.registerMediaUnderstandingProvider(...) | openai, google |
| Generación de imágenes | api.registerImageGenerationProvider(...) | openai, google, fal, minimax |
| Generación de música | api.registerMusicGenerationProvider(...) | google, minimax |
| Generación de video | api.registerVideoGenerationProvider(...) | qwen |
| Obtención web | api.registerWebFetchProvider(...) | firecrawl |
| Búsqueda web | api.registerWebSearchProvider(...) | google |
| Canal / mensajería | api.registerChannel(...) | msteams, matrix |
Postura de compatibilidad externa
El modelo de capacidades ya está incorporado en el core y es usado por plugins agrupados/nativos hoy en día, pero la compatibilidad de los plugins externos aún necesita un criterio más estricto que “está exportado, por lo tanto está congelado”. Guía actual:- plugins externos existentes: mantén funcionando las integraciones basadas en hooks; trátalo como la línea base de compatibilidad
- nuevos plugins agrupados/nativos: prefiere el registro explícito de capacidades en lugar de accesos específicos de proveedor o nuevos diseños solo de hooks
- plugins externos que adopten el registro de capacidades: está permitido, pero trata las superficies auxiliares específicas de capacidades como evolutivas, a menos que la documentación marque explícitamente un contrato como estable
- las API de registro de capacidades son la dirección prevista
- los hooks heredados siguen siendo la ruta más segura para evitar incompatibilidades para los plugins externos durante la transición
- no todos los subpaths auxiliares exportados son iguales; prefiere el contrato documentado y acotado, no exportaciones auxiliares incidentales
Formas de plugins
OpenClaw clasifica cada plugin cargado en una forma según su comportamiento real de registro (no solo según metadatos estáticos):- plain-capability — registra exactamente un tipo de capacidad (por ejemplo, un
plugin solo de proveedor como
mistral) - hybrid-capability — registra múltiples tipos de capacidad (por ejemplo,
openaies propietario de la inferencia de texto, voz, comprensión de medios y generación de imágenes) - hook-only — registra solo hooks (tipados o personalizados), sin capacidades, herramientas, comandos ni servicios
- non-capability — registra herramientas, comandos, servicios o rutas, pero no capacidades
openclaw plugins inspect <id> para ver la forma y el desglose de capacidades
de un plugin. Consulta la referencia de CLI para más detalles.
Hooks heredados
El hookbefore_agent_start sigue siendo compatible como ruta de compatibilidad para
plugins solo de hooks. Los plugins heredados del mundo real siguen dependiendo de él.
Dirección:
- mantenerlo funcionando
- documentarlo como heredado
- preferir
before_model_resolvepara trabajo de reemplazo de modelo/proveedor - preferir
before_prompt_buildpara trabajo de mutación de prompts - eliminarlo solo después de que baje el uso real y la cobertura de fixtures demuestre la seguridad de la migración
Señales de compatibilidad
Cuando ejecutasopenclaw doctor o openclaw plugins inspect <id>, puedes ver
una de estas etiquetas:
| Señal | Significado |
|---|---|
| config valid | La configuración se analiza correctamente y los plugins se resuelven |
| compatibility advisory | El plugin usa un patrón compatible pero antiguo (p. ej., hook-only) |
| legacy warning | El plugin usa before_agent_start, que está obsoleto |
| hard error | La configuración no es válida o el plugin no pudo cargarse |
hook-only ni before_agent_start romperán tu plugin hoy —
hook-only es informativo, y before_agent_start solo activa una advertencia. Estas
señales también aparecen en openclaw status --all y openclaw plugins doctor.
Descripción general de la arquitectura
El sistema de plugins de OpenClaw tiene cuatro capas:- Manifest + descubrimiento
OpenClaw encuentra plugins candidatos a partir de rutas configuradas, raíces del workspace,
raíces globales de extensiones y extensiones agrupadas. El descubrimiento lee primero los manifests nativos
openclaw.plugin.jsonjunto con los manifests de bundles compatibles. - Habilitación + validación El core decide si un plugin descubierto está habilitado, deshabilitado, bloqueado o seleccionado para un slot exclusivo como memory.
- Carga en tiempo de ejecución Los plugins nativos de OpenClaw se cargan dentro del proceso mediante jiti y registran capacidades en un registro central. Los bundles compatibles se normalizan en registros del registro sin importar código de tiempo de ejecución.
- Consumo de superficies El resto de OpenClaw lee el registro para exponer herramientas, canales, configuración de proveedor, hooks, rutas HTTP, comandos de CLI y servicios.
- los metadatos en tiempo de análisis provienen de
registerCli(..., { descriptors: [...] }) - el módulo real de la CLI del plugin puede permanecer diferido y registrarse en la primera invocación
- el descubrimiento y la validación de configuración deben funcionar a partir de metadatos de manifest/esquema sin ejecutar código del plugin
- el comportamiento nativo en tiempo de ejecución proviene de la ruta
register(api)del módulo del plugin
Plugins de canal y la herramienta de mensajes compartida
Los plugins de canal no necesitan registrar una herramienta separada de enviar/editar/reaccionar para acciones normales de chat. OpenClaw mantiene una única herramientamessage compartida en el core, y
los plugins de canal son propietarios del descubrimiento y la ejecución específicos del canal detrás de ella.
El límite actual es:
- el core es propietario del host de la herramienta
messagecompartida, la integración con prompts, el mantenimiento de sesiones/hilos y el despacho de ejecución - los plugins de canal son propietarios del descubrimiento de acciones por alcance, el descubrimiento de capacidades y cualquier fragmento de esquema específico del canal
- los plugins de canal son propietarios de la gramática de conversación de sesión específica del proveedor, como cómo los ID de conversación codifican los ID de hilo o heredan de conversaciones padre
- los plugins de canal ejecutan la acción final a través de su adaptador de acciones
ChannelMessageActionAdapter.describeMessageTool(...). Esa llamada de descubrimiento unificada
permite que un plugin devuelva juntas sus acciones visibles, capacidades y contribuciones de esquema
para que esas piezas no se desincronicen.
El core pasa el alcance de tiempo de ejecución a ese paso de descubrimiento. Los campos importantes incluyen:
accountIdcurrentChannelIdcurrentThreadTscurrentMessageIdsessionKeysessionIdagentIdrequesterSenderIdentrante de confianza
message del
core.
Por eso los cambios de enrutamiento del embedded-runner siguen siendo trabajo del plugin: el runner es
responsable de reenviar la identidad actual del chat/sesión al límite de descubrimiento del plugin para que la
herramienta message compartida exponga la superficie propiedad del canal correcta para el turno actual.
Para los asistentes de ejecución propiedad del canal, los plugins agrupados deben mantener el tiempo de ejecución
de ejecución dentro de sus propios módulos de extensión. El core ya no es propietario de los
tiempos de ejecución de acciones de mensaje de Discord, Slack, Telegram o WhatsApp en src/agents/tools.
No publicamos subpaths separados plugin-sdk/*-action-runtime, y los plugins agrupados
deben importar directamente su propio código de tiempo de ejecución local desde sus
módulos propiedad de la extensión.
El mismo límite se aplica a los seams del SDK con nombre de proveedor en general: el core no
debe importar barriles de conveniencia específicos del canal para Slack, Discord, Signal,
WhatsApp o extensiones similares. Si el core necesita un comportamiento, debe consumir el
propio barril api.ts / runtime-api.ts del plugin agrupado o promover esa necesidad
a una capacidad genérica y acotada en el SDK compartido.
Específicamente para las encuestas, hay dos rutas de ejecución:
outbound.sendPolles la base compartida para canales que encajan en el modelo común de encuestasactions.handleAction("poll")es la ruta preferida para la semántica de encuestas específica del canal o parámetros adicionales de encuestas
Modelo de propiedad de capacidades
OpenClaw trata un plugin nativo como el límite de propiedad de una empresa o una función, no como un conjunto de integraciones no relacionadas. Eso significa:- un plugin de empresa normalmente debe ser propietario de todas las superficies de OpenClaw orientadas a esa empresa
- un plugin de función normalmente debe ser propietario de la superficie completa de la función que introduce
- los canales deben consumir capacidades compartidas del core en lugar de volver a implementar comportamiento de proveedor de forma ad hoc
- el plugin agrupado
openaies propietario del comportamiento del proveedor de modelos de OpenAI y del comportamiento de OpenAI de voz + voz en tiempo real + comprensión de medios + generación de imágenes - el plugin agrupado
elevenlabses propietario del comportamiento de voz de ElevenLabs - el plugin agrupado
microsoftes propietario del comportamiento de voz de Microsoft - el plugin agrupado
googlees propietario del comportamiento del proveedor de modelos de Google más el comportamiento de Google de comprensión de medios + generación de imágenes + búsqueda web - el plugin agrupado
firecrawles propietario del comportamiento de obtención web de Firecrawl - los plugins agrupados
minimax,mistral,moonshotyzaison propietarios de sus backends de comprensión de medios - el plugin agrupado
qwenes propietario del comportamiento del proveedor de texto de Qwen más el comportamiento de comprensión de medios y generación de video - el plugin
voice-calles un plugin de función: es propietario del transporte de llamadas, herramientas, CLI, rutas y el puente de flujo de medios de Twilio, pero consume capacidades compartidas de voz más transcripción en tiempo real y voz en tiempo real en lugar de importar directamente plugins de proveedor
- OpenAI vive en un solo plugin aunque abarque modelos de texto, voz, imágenes y video futuro
- otro proveedor puede hacer lo mismo para su propia área de superficie
- los canales no se preocupan por qué plugin del proveedor es propietario del proveedor; consumen el contrato de capacidad compartida expuesto por el core
- plugin = límite de propiedad
- capacidad = contrato del core que múltiples plugins pueden implementar o consumir
- definir la capacidad faltante en el core
- exponerla a través de la API/tiempo de ejecución del plugin de forma tipada
- conectar canales/funciones a esa capacidad
- dejar que los plugins de proveedor registren implementaciones
Capas de capacidades
Usa este modelo mental al decidir dónde debe estar el código:- capa de capacidades del core: orquestación compartida, política, fallback, reglas de combinación de configuración, semántica de entrega y contratos tipados
- capa de plugins de proveedor: APIs específicas del proveedor, autenticación, catálogos de modelos, síntesis de voz, generación de imágenes, futuros backends de video, endpoints de uso
- capa de plugins de canal/función: integración con Slack/Discord/voice-call/etc. que consume capacidades del core y las presenta en una superficie
- el core es propietario de la política de TTS en el momento de la respuesta, el orden de fallback, las preferencias y la entrega por canal
openai,elevenlabsymicrosoftson propietarios de las implementaciones de síntesisvoice-callconsume el asistente de tiempo de ejecución de TTS para telefonía
Ejemplo de plugin de empresa con múltiples capacidades
Un plugin de empresa debe sentirse cohesivo desde fuera. Si OpenClaw tiene contratos compartidos para modelos, voz, transcripción en tiempo real, voz en tiempo real, comprensión de medios, generación de imágenes, generación de video, obtención web y búsqueda web, un proveedor puede ser propietario de todas sus superficies en un solo lugar:- un solo plugin es propietario de la superficie del proveedor
- el core sigue siendo propietario de los contratos de capacidad
- los plugins de canal y de función consumen asistentes
api.runtime.*, no código del proveedor - las pruebas de contrato pueden afirmar que el plugin registró las capacidades de las que dice ser propietario
Ejemplo de capacidad: comprensión de video
OpenClaw ya trata la comprensión de imagen/audio/video como una capacidad compartida. El mismo modelo de propiedad se aplica ahí:- el core define el contrato de comprensión de medios
- los plugins de proveedor registran
describeImage,transcribeAudioydescribeVideosegún corresponda - los plugins de canal y de función consumen el comportamiento compartido del core en lugar de conectarse directamente al código del proveedor
api.registerVideoGenerationProvider(...) en él.
¿Necesitas una lista de despliegue concreta? Consulta
Recetario de capacidades.
Contratos y cumplimiento
La superficie de la API de plugins es intencionadamente tipada y centralizada enOpenClawPluginApi. Ese contrato define los puntos de registro compatibles y
los asistentes de tiempo de ejecución en los que un plugin puede apoyarse.
Por qué importa esto:
- los autores de plugins obtienen un estándar interno estable
- el core puede rechazar propiedad duplicada, como dos plugins que registran el mismo id de proveedor
- el inicio puede mostrar diagnósticos accionables para registros malformados
- las pruebas de contrato pueden aplicar la propiedad de plugins agrupados y evitar desvíos silenciosos
- cumplimiento de registro en tiempo de ejecución El registro de plugins valida los registros a medida que se cargan los plugins. Ejemplos: id de proveedor duplicados, id de proveedor de voz duplicados y registros malformados producen diagnósticos de plugin en lugar de comportamiento indefinido.
- pruebas de contrato Los plugins agrupados se capturan en registros de contrato durante las ejecuciones de prueba para que OpenClaw pueda afirmar explícitamente la propiedad. Hoy esto se usa para proveedores de modelos, proveedores de voz, proveedores de búsqueda web y propiedad de registro agrupado.
Qué pertenece a un contrato
Los buenos contratos de plugins son:- tipados
- pequeños
- específicos de capacidades
- propiedad del core
- reutilizables por múltiples plugins
- consumibles por canales/funciones sin conocimiento del proveedor
- política específica del proveedor oculta en el core
- vías de escape puntuales de plugins que evitan el registro
- código de canal que entra directamente en una implementación del proveedor
- objetos ad hoc de tiempo de ejecución que no forman parte de
OpenClawPluginApini deapi.runtime
Modelo de ejecución
Los plugins nativos de OpenClaw se ejecutan dentro del proceso con el Gateway. No están aislados. Un plugin nativo cargado tiene el mismo límite de confianza a nivel de proceso que el código del core. Implicaciones:- un plugin nativo puede registrar herramientas, controladores de red, hooks y servicios
- un error en un plugin nativo puede bloquear o desestabilizar el gateway
- un plugin nativo malicioso equivale a ejecución arbitraria de código dentro del proceso de OpenClaw
@openclaw/<id> de forma predeterminada, o un sufijo tipado aprobado como
-provider, -plugin, -speech, -sandbox o -media-understanding cuando
el paquete expone intencionadamente un rol de plugin más acotado.
Nota importante sobre confianza:
plugins.allowconfía en ids de plugin, no en la procedencia del origen.- Un plugin del workspace con el mismo id que un plugin agrupado sombrea intencionadamente la copia agrupada cuando ese plugin del workspace está habilitado/en la allowlist.
- Esto es normal y útil para desarrollo local, pruebas de parches y hotfixes.
Límite de exportación
OpenClaw exporta capacidades, no conveniencias de implementación. Mantén público el registro de capacidades. Recorta las exportaciones auxiliares que no sean contratos:- subpaths auxiliares específicos de plugins agrupados
- subpaths de plomería de tiempo de ejecución no pensados como API pública
- asistentes de conveniencia específicos del proveedor
- asistentes de configuración/incorporación que son detalles de implementación
plugin-sdk/feishu, plugin-sdk/feishu-setup, plugin-sdk/zalo,
plugin-sdk/zalo-setup y varios seams plugin-sdk/matrix*. Trátalos como
exportaciones reservadas de detalle de implementación, no como el patrón de SDK recomendado para
nuevos plugins de terceros.
Canalización de carga
Al iniciar, OpenClaw hace aproximadamente esto:- descubre raíces candidatas de plugins
- lee manifests nativos o de bundles compatibles y metadatos de paquetes
- rechaza candidatos inseguros
- normaliza la configuración de plugins (
plugins.enabled,allow,deny,entries,slots,load.paths) - decide la habilitación de cada candidato
- carga módulos nativos habilitados mediante jiti
- llama a los hooks nativos
register(api)(oactivate(api)— un alias heredado) y recopila los registros en el registro de plugins - expone el registro a las superficies de comandos/tiempo de ejecución
activate es un alias heredado de register: el cargador resuelve el que esté presente (def.register ?? def.activate) y lo llama en el mismo punto. Todos los plugins agrupados usan register; prefiere register para plugins nuevos.Comportamiento centrado en el manifest
El manifest es la fuente de verdad del plano de control. OpenClaw lo usa para:- identificar el plugin
- descubrir canales/Skills/esquema de configuración declarados o capacidades del bundle
- validar
plugins.entries.<id>.config - ampliar etiquetas/placeholders de Control UI
- mostrar metadatos de instalación/catálogo
- preservar descriptores económicos de activación y configuración sin cargar el tiempo de ejecución del plugin
activation y setup del manifest permanecen en el plano de control.
Son descriptores solo de metadatos para la planificación de activación y el descubrimiento de configuración;
no reemplazan el registro en tiempo de ejecución, register(...) ni setupEntry.
El descubrimiento de configuración ahora prefiere ids propiedad del descriptor como setup.providers y
setup.cliBackends para acotar plugins candidatos antes de volver a setup-api para plugins que aún necesitan hooks de tiempo de ejecución en configuración. Si más de
un plugin descubierto reclama el mismo id normalizado de proveedor de configuración o backend de CLI, la búsqueda de configuración rechaza al propietario ambiguo en lugar de depender del orden de descubrimiento.
Qué almacena en caché el cargador
OpenClaw mantiene cachés cortas dentro del proceso para:- resultados de descubrimiento
- datos del registro de manifests
- registros de plugins cargados
- Establece
OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1oOPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1para desactivar estas cachés. - Ajusta las ventanas de caché con
OPENCLAW_PLUGIN_DISCOVERY_CACHE_MSyOPENCLAW_PLUGIN_MANIFEST_CACHE_MS.
Modelo de registro
Los plugins cargados no mutan directamente globals aleatorios del core. Se registran en un registro central de plugins. El registro rastrea:- registros de plugins (identidad, origen, procedencia, estado, diagnósticos)
- herramientas
- hooks heredados y hooks tipados
- canales
- proveedores
- controladores RPC del gateway
- rutas HTTP
- registradores de CLI
- servicios en segundo plano
- comandos propiedad del plugin
- módulo del plugin -> registro en el registro
- tiempo de ejecución del core -> consumo del registro
Callbacks de asociación de conversaciones
Los plugins que asocian una conversación pueden reaccionar cuando se resuelve una aprobación. Usaapi.onConversationBindingResolved(...) para recibir un callback después de que una solicitud de asociación sea aprobada o denegada:
status:"approved"o"denied"decision:"allow-once","allow-always"o"deny"binding: la asociación resuelta para solicitudes aprobadasrequest: el resumen de la solicitud original, sugerencia de desvinculación, id del remitente y metadatos de la conversación
Hooks de tiempo de ejecución del proveedor
Los plugins de proveedor ahora tienen dos capas:- metadatos del manifest:
providerAuthEnvVarspara búsquedas económicas de autenticación del proveedor mediante variables de entorno antes de cargar el tiempo de ejecución,providerAuthAliasespara variantes de proveedor que comparten autenticación,channelEnvVarspara búsquedas económicas de entorno/configuración del canal antes de la carga del tiempo de ejecución, además deproviderAuthChoicespara etiquetas económicas de incorporación/opciones de autenticación y metadatos de flags de CLI antes de cargar el tiempo de ejecución - hooks en tiempo de configuración:
catalog/discoveryheredado másapplyConfigDefaults - hooks de tiempo de ejecución:
normalizeModelId,normalizeTransport,normalizeConfig,applyNativeStreamingUsageCompat,resolveConfigApiKey,resolveSyntheticAuth,resolveExternalAuthProfiles,shouldDeferSyntheticProfileAuth,resolveDynamicModel,prepareDynamicModel,normalizeResolvedModel,contributeResolvedModelCompat,capabilities,normalizeToolSchemas,inspectToolSchemas,resolveReasoningOutputMode,prepareExtraParams,createStreamFn,wrapStreamFn,resolveTransportTurnState,resolveWebSocketSessionPolicy,formatApiKey,refreshOAuth,buildAuthDoctorHint,matchesContextOverflowError,classifyFailoverReason,isCacheTtlEligible,buildMissingAuthMessage,suppressBuiltInModel,augmentModelCatalog,isBinaryThinking,supportsXHighThinking,resolveDefaultThinkingLevel,isModernModelRef,prepareRuntimeAuth,resolveUsageAuth,fetchUsageSnapshot,createEmbeddingProvider,buildReplayPolicy,sanitizeReplayHistory,validateReplayTurns,onModelSelected
providerAuthEnvVars cuando el proveedor tenga credenciales basadas en variables de entorno
que las rutas genéricas de autenticación/estado/selector de modelos deban ver sin cargar el tiempo de ejecución del plugin.
Usa el manifest providerAuthAliases cuando un id de proveedor deba reutilizar
las variables de entorno, perfiles de autenticación, autenticación respaldada por configuración y la opción de incorporación con clave API
de otro id de proveedor. Usa el manifest providerAuthChoices cuando las
superficies de CLI de incorporación/opción de autenticación deban conocer el id de opción del proveedor, las etiquetas de grupo y la lógica
simple de autenticación con un solo flag sin cargar el tiempo de ejecución del proveedor. Mantén envVars del tiempo de ejecución del proveedor para sugerencias orientadas al operador, como etiquetas de incorporación o variables de
configuración de client-id/client-secret de OAuth.
Usa el manifest channelEnvVars cuando un canal tenga autenticación o configuración impulsada por variables de entorno que
los mecanismos genéricos de fallback del entorno de shell, verificaciones de config/status o prompts de configuración deban ver
sin cargar el tiempo de ejecución del canal.
Orden y uso de hooks
Para plugins de modelo/proveedor, OpenClaw llama a los hooks aproximadamente en este orden. La columna “Cuándo usar” es la guía rápida de decisión.| # | Hook | Qué hace | Cuándo usarlo |
|---|---|---|---|
| 1 | catalog | Publica la configuración del proveedor en models.providers durante la generación de models.json | El proveedor es propietario de un catálogo o de valores predeterminados de URL base |
| 2 | applyConfigDefaults | Aplica valores predeterminados globales de configuración propiedad del proveedor durante la materialización de la configuración | Los valores predeterminados dependen del modo de autenticación, del entorno o de la semántica de la familia de modelos del proveedor |
| — | (búsqueda de modelos integrados) | OpenClaw prueba primero la ruta normal de registro/catálogo | (no es un hook de plugin) |
| 3 | normalizeModelId | Normaliza aliases heredados o de vista previa de id de modelo antes de la búsqueda | El proveedor es propietario de la limpieza de aliases antes de la resolución canónica del modelo |
| 4 | normalizeTransport | Normaliza api / baseUrl de la familia del proveedor antes del ensamblado genérico del modelo | El proveedor es propietario de la limpieza del transporte para ids de proveedor personalizados dentro de la misma familia de transporte |
| 5 | normalizeConfig | Normaliza models.providers.<id> antes de la resolución del proveedor/en tiempo de ejecución | El proveedor necesita una limpieza de configuración que deba vivir con el plugin; los asistentes agrupados de la familia Google también respaldan las entradas compatibles de configuración de Google |
| 6 | applyNativeStreamingUsageCompat | Aplica reescrituras de compatibilidad de uso de streaming nativo a los proveedores de configuración | El proveedor necesita correcciones de metadatos de uso de streaming nativo basadas en endpoints |
| 7 | resolveConfigApiKey | Resuelve autenticación por marcador de entorno para proveedores de configuración antes de cargar la autenticación en tiempo de ejecución | El proveedor tiene resolución de clave API por marcador de entorno propiedad del proveedor; amazon-bedrock también tiene aquí un resolvedor integrado de marcador de entorno de AWS |
| 8 | resolveSyntheticAuth | Expone autenticación local/alojada por uno mismo o respaldada por configuración sin persistir texto sin formato | El proveedor puede operar con un marcador de credencial sintética/local |
| 9 | resolveExternalAuthProfiles | Superpone perfiles de autenticación externa propiedad del proveedor; el valor predeterminado de persistence es runtime-only para credenciales propiedad de CLI/app | El proveedor reutiliza credenciales de autenticación externas sin persistir tokens de actualización copiados |
| 10 | shouldDeferSyntheticProfileAuth | Hace que los marcadores de posición de perfiles sintéticos almacenados queden por detrás de la autenticación respaldada por entorno/configuración | El proveedor almacena perfiles de marcador de posición sintéticos que no deberían tener precedencia |
| 11 | resolveDynamicModel | Fallback síncrono para ids de modelo propiedad del proveedor que todavía no están en el registro local | El proveedor acepta ids de modelo arbitrarios del upstream |
| 12 | prepareDynamicModel | Calentamiento asíncrono; luego resolveDynamicModel se ejecuta de nuevo | El proveedor necesita metadatos de red antes de resolver ids desconocidos |
| 13 | normalizeResolvedModel | Reescritura final antes de que el embedded runner use el modelo resuelto | El proveedor necesita reescrituras de transporte pero sigue usando un transporte del core |
| 14 | contributeResolvedModelCompat | Aporta flags de compatibilidad para modelos del proveedor detrás de otro transporte compatible | El proveedor reconoce sus propios modelos en transportes proxy sin asumir la propiedad del proveedor |
| 15 | capabilities | Metadatos de transcripción/herramientas propiedad del proveedor usados por la lógica compartida del core | El proveedor necesita particularidades de transcripción/familia de proveedor |
| 16 | normalizeToolSchemas | Normaliza esquemas de herramientas antes de que el embedded runner los vea | El proveedor necesita limpieza de esquemas de la familia de transporte |
| 17 | inspectToolSchemas | Expone diagnósticos de esquema propiedad del proveedor después de la normalización | El proveedor quiere advertencias de palabras clave sin enseñar al core reglas específicas del proveedor |
| 18 | resolveReasoningOutputMode | Selecciona el contrato de salida de razonamiento nativo frente al etiquetado | El proveedor necesita salida final/de razonamiento etiquetada en lugar de campos nativos |
| 19 | prepareExtraParams | Normalización de parámetros de solicitud antes de los wrappers genéricos de opciones de stream | El proveedor necesita parámetros de solicitud predeterminados o limpieza de parámetros por proveedor |
| 20 | createStreamFn | Reemplaza por completo la ruta normal de stream con un transporte personalizado | El proveedor necesita un protocolo de cable personalizado, no solo un wrapper |
| 21 | wrapStreamFn | Wrapper de stream después de aplicar los wrappers genéricos | El proveedor necesita wrappers de compatibilidad de encabezados/cuerpo/modelo de solicitud sin un transporte personalizado |
| 22 | resolveTransportTurnState | Adjunta encabezados o metadatos nativos por turno del transporte | El proveedor quiere que los transportes genéricos envíen identidad de turno nativa del proveedor |
| 23 | resolveWebSocketSessionPolicy | Adjunta encabezados nativos de WebSocket o política de enfriamiento de sesión | El proveedor quiere que los transportes genéricos de WS ajusten los encabezados de sesión o la política de fallback |
| 24 | formatApiKey | Formateador de perfil de autenticación: el perfil almacenado se convierte en la cadena apiKey del tiempo de ejecución | El proveedor almacena metadatos adicionales de autenticación y necesita una forma personalizada del token en tiempo de ejecución |
| 25 | refreshOAuth | Reemplazo de actualización de OAuth para endpoints de actualización personalizados o política de fallo de actualización | El proveedor no encaja en los refrescadores compartidos pi-ai |
| 26 | buildAuthDoctorHint | Sugerencia de reparación agregada cuando falla la actualización de OAuth | El proveedor necesita orientación de reparación de autenticación propiedad del proveedor tras un fallo de actualización |
| 27 | matchesContextOverflowError | Comparador de desbordamiento de ventana de contexto propiedad del proveedor | El proveedor tiene errores de desbordamiento sin procesar que las heurísticas genéricas no detectarían |
| 28 | classifyFailoverReason | Clasificación de razones de failover propiedad del proveedor | El proveedor puede mapear errores sin procesar de API/transporte a límite de tasa, sobrecarga, etc. |
| 29 | isCacheTtlEligible | Política de caché de prompts para proveedores proxy/backhaul | El proveedor necesita control de TTL de caché específico de proxy |
| 30 | buildMissingAuthMessage | Reemplazo del mensaje genérico de recuperación por falta de autenticación | El proveedor necesita una sugerencia de recuperación por falta de autenticación específica del proveedor |
| 31 | suppressBuiltInModel | Supresión de modelos upstream obsoletos más sugerencia opcional de error orientada al usuario | El proveedor necesita ocultar filas upstream obsoletas o reemplazarlas con una sugerencia del proveedor |
| 32 | augmentModelCatalog | Filas sintéticas/finales de catálogo agregadas después del descubrimiento | El proveedor necesita filas sintéticas de compatibilidad futura en models list y selectores |
| 33 | isBinaryThinking | Alternancia de razonamiento activado/desactivado para proveedores de razonamiento binario | El proveedor expone solo razonamiento binario activado/desactivado |
| 34 | supportsXHighThinking | Compatibilidad con razonamiento xhigh para modelos seleccionados | El proveedor quiere xhigh solo en un subconjunto de modelos |
| 35 | resolveDefaultThinkingLevel | Nivel predeterminado de /think para una familia de modelos específica | El proveedor es propietario de la política predeterminada de /think para una familia de modelos |
| 36 | isModernModelRef | Comparador de modelos modernos para filtros de perfiles en vivo y selección de smoke | El proveedor es propietario de la coincidencia de modelos preferidos para pruebas en vivo/smoke |
| 37 | prepareRuntimeAuth | Intercambia una credencial configurada por el token/clave real del tiempo de ejecución justo antes de la inferencia | El proveedor necesita un intercambio de token o una credencial de solicitud de corta duración |
| 38 | resolveUsageAuth | Resuelve credenciales de uso/facturación para /usage y superficies de estado relacionadas | El proveedor necesita análisis personalizado de tokens de uso/cuota o una credencial de uso diferente |
| 39 | fetchUsageSnapshot | Obtiene y normaliza snapshots de uso/cuota específicos del proveedor después de resolver la autenticación | El proveedor necesita un endpoint de uso específico del proveedor o un analizador de carga útil |
| 40 | createEmbeddingProvider | Construye un adaptador de embeddings propiedad del proveedor para memory/search | El comportamiento de embeddings de memory pertenece al plugin del proveedor |
| 41 | buildReplayPolicy | Devuelve una política de replay que controla el manejo de transcripciones para el proveedor | El proveedor necesita una política de transcripción personalizada (por ejemplo, eliminación de bloques de razonamiento) |
| 42 | sanitizeReplayHistory | Reescribe el historial de replay después de la limpieza genérica de transcripciones | El proveedor necesita reescrituras específicas del proveedor para replay más allá de los asistentes compartidos de compactación |
| 43 | validateReplayTurns | Validación final o remodelado de turnos de replay antes del embedded runner | El transporte del proveedor necesita una validación de turnos más estricta después de la sanitización genérica |
| 44 | onModelSelected | Ejecuta efectos secundarios posteriores a la selección propiedad del proveedor | El proveedor necesita telemetría o estado propiedad del proveedor cuando un modelo pasa a estar activo |
normalizeModelId, normalizeTransport y normalizeConfig primero comprueban el
plugin de proveedor coincidente y luego recorren el resto de plugins de proveedor con capacidad de hooks
hasta que uno realmente cambia el id del modelo o el transporte/configuración. Eso mantiene
funcionando los shims de alias/proveedor de compatibilidad sin exigir que quien llama sepa qué
plugin agrupado es propietario de la reescritura. Si ningún hook de proveedor reescribe una entrada de configuración compatible
de la familia Google, el normalizador de configuración agrupado de Google sigue aplicando
esa limpieza de compatibilidad.
Si el proveedor necesita un protocolo de cable totalmente personalizado o un ejecutor de solicitudes personalizado,
esa es una clase distinta de extensión. Estos hooks son para comportamiento de proveedor
que sigue ejecutándose en el bucle de inferencia normal de OpenClaw.
Ejemplo de proveedor
Ejemplos integrados
- Anthropic usa
resolveDynamicModel,capabilities,buildAuthDoctorHint,resolveUsageAuth,fetchUsageSnapshot,isCacheTtlEligible,resolveDefaultThinkingLevel,applyConfigDefaults,isModernModelRefywrapStreamFnporque es propietario de la compatibilidad futura de Claude 4.6, de las sugerencias de familia de proveedor, de la guía de reparación de autenticación, de la integración del endpoint de uso, de la elegibilidad de caché de prompts, de los valores predeterminados de configuración conscientes de autenticación, de la política predeterminada/adaptativa de pensamiento de Claude y del modelado de stream específico de Anthropic para encabezados beta,/fast/serviceTierycontext1m. - Los asistentes de stream específicos de Claude de Anthropic permanecen por ahora en el
seam público propio
api.ts/contract-api.tsdel plugin agrupado. Esa superficie del paquete exportawrapAnthropicProviderStream,resolveAnthropicBetas,resolveAnthropicFastMode,resolveAnthropicServiceTiery los builders de wrappers de Anthropic de más bajo nivel en lugar de ampliar el SDK genérico en torno a las reglas de encabezados beta de un solo proveedor. - OpenAI usa
resolveDynamicModel,normalizeResolvedModelycapabilities, además debuildMissingAuthMessage,suppressBuiltInModel,augmentModelCatalog,supportsXHighThinkingeisModernModelRefporque es propietario de la compatibilidad futura de GPT-5.4, de la normalización directa de OpenAIopenai-completions->openai-responses, de las sugerencias de autenticación conscientes de Codex, de la supresión de Spark, de las filas sintéticas de lista de OpenAI y de la política de pensamiento/modelo en vivo de GPT-5; la familia de streamsopenai-responses-defaultses propietaria de los wrappers compartidos nativos de OpenAI Responses para encabezados de atribución,/fast/serviceTier, verbosidad de texto, búsqueda web nativa de Codex, modelado de carga útil compatible con razonamiento y gestión del contexto de Responses. - OpenRouter usa
catalog, además deresolveDynamicModelyprepareDynamicModel, porque el proveedor es de paso y puede exponer nuevos ids de modelo antes de que se actualice el catálogo estático de OpenClaw; también usacapabilities,wrapStreamFneisCacheTtlEligiblepara mantener fuera del core los encabezados de solicitud específicos del proveedor, los metadatos de enrutamiento, los parches de razonamiento y la política de caché de prompts. Su política de replay proviene de la familiapassthrough-gemini, mientras que la familia de streamsopenrouter-thinkinges propietaria de la inyección de razonamiento proxy y de las omisiones de modelos no compatibles /auto. - GitHub Copilot usa
catalog,auth,resolveDynamicModelycapabilities, además deprepareRuntimeAuthyfetchUsageSnapshot, porque necesita inicio de sesión de dispositivo propiedad del proveedor, comportamiento de fallback de modelo, particularidades de transcripción de Claude, un intercambio de token de GitHub -> token de Copilot y un endpoint de uso propiedad del proveedor. - OpenAI Codex usa
catalog,resolveDynamicModel,normalizeResolvedModel,refreshOAuthyaugmentModelCatalog, además deprepareExtraParams,resolveUsageAuthyfetchUsageSnapshot, porque sigue ejecutándose sobre los transportes centrales de OpenAI, pero es propietario de su normalización de transporte/base URL, de la política de fallback de actualización de OAuth, de la elección de transporte predeterminada, de las filas sintéticas de catálogo de Codex y de la integración del endpoint de uso de ChatGPT; comparte la misma familia de streamsopenai-responses-defaultsque OpenAI directo. - Google AI Studio y Gemini CLI OAuth usan
resolveDynamicModel,buildReplayPolicy,sanitizeReplayHistory,resolveReasoningOutputMode,wrapStreamFneisModernModelRefporque la familia de replaygoogle-geminies propietaria del fallback de compatibilidad futura de Gemini 3.1, de la validación nativa de replay de Gemini, de la sanitización de replay de bootstrap, del modo de salida de razonamiento etiquetado y de la coincidencia de modelos modernos, mientras que la familia de streamsgoogle-thinkinges propietaria de la normalización de la carga útil de pensamiento de Gemini; Gemini CLI OAuth también usaformatApiKey,resolveUsageAuthyfetchUsageSnapshotpara el formateo de tokens, el análisis de tokens y la conexión del endpoint de cuota. - Anthropic Vertex usa
buildReplayPolicya través de la familia de replayanthropic-by-modelpara que la limpieza de replay específica de Claude quede acotada a ids de Claude en lugar de a cada transporteanthropic-messages. - Amazon Bedrock usa
buildReplayPolicy,matchesContextOverflowError,classifyFailoverReasonyresolveDefaultThinkingLevelporque es propietario de la clasificación de errores específicos de Bedrock de limitación/no listo/desbordamiento de contexto para tráfico Anthropic-on-Bedrock; su política de replay sigue compartiendo la misma protección solo para Claudeanthropic-by-model. - OpenRouter, Kilocode, Opencode y Opencode Go usan
buildReplayPolicya través de la familia de replaypassthrough-geminiporque hacen proxy de modelos Gemini mediante transportes compatibles con OpenAI y necesitan sanitización de firmas de pensamiento de Gemini sin validación nativa de replay de Gemini ni reescrituras de bootstrap. - MiniMax usa
buildReplayPolicya través de la familia de replayhybrid-anthropic-openaiporque un solo proveedor es propietario tanto de semántica de mensajes Anthropic como de compatibilidad con OpenAI; mantiene la eliminación de bloques de pensamiento exclusivos de Claude en el lado Anthropic mientras reemplaza el modo de salida de razonamiento de vuelta a nativo, y la familia de streamsminimax-fast-modees propietaria de las reescrituras de modelos de modo rápido en la ruta de stream compartida. - Moonshot usa
catalog, además dewrapStreamFn, porque sigue usando el transporte compartido de OpenAI pero necesita normalización de carga útil de pensamiento propiedad del proveedor; la familia de streamsmoonshot-thinkingasigna config más estado/thinka su carga útil nativa de pensamiento binario. - Kilocode usa
catalog,capabilities,wrapStreamFneisCacheTtlEligibleporque necesita encabezados de solicitud propiedad del proveedor, normalización de carga útil de razonamiento, sugerencias de transcripción de Gemini y control de TTL de caché de Anthropic; la familia de streamskilocode-thinkingmantiene la inyección de pensamiento de Kilo en la ruta de stream proxy compartida mientras omitekilo/autoy otros ids de modelo proxy que no admiten cargas útiles explícitas de razonamiento. - Z.AI usa
resolveDynamicModel,prepareExtraParams,wrapStreamFn,isCacheTtlEligible,isBinaryThinking,isModernModelRef,resolveUsageAuthyfetchUsageSnapshotporque es propietario del fallback de GLM-5, de los valores predeterminados detool_stream, de la UX de pensamiento binario, de la coincidencia de modelos modernos y tanto de la autenticación de uso como de la obtención de cuota; la familia de streamstool-stream-default-onmantiene el wrapper predeterminado activadotool_streamfuera del pegamento manuscrito por proveedor. - xAI usa
normalizeResolvedModel,normalizeTransport,contributeResolvedModelCompat,prepareExtraParams,wrapStreamFn,resolveSyntheticAuth,resolveDynamicModeleisModernModelRefporque es propietario de la normalización nativa de transporte xAI Responses, de las reescrituras de alias de modo rápido de Grok, del valor predeterminadotool_stream, de la limpieza estricta de herramientas / carga útil de razonamiento, de la reutilización de autenticación de fallback para herramientas propiedad del plugin, de la resolución de modelos Grok con compatibilidad futura y de parches de compatibilidad propiedad del proveedor, como el perfil de esquema de herramientas de xAI, palabras clave de esquema no compatibles,web_searchnativo y la decodificación de argumentos de llamadas a herramientas con entidades HTML. - Mistral, OpenCode Zen y OpenCode Go usan solo
capabilitiespara mantener fuera del core las particularidades de transcripción/herramientas. - Los proveedores agrupados solo de catálogo como
byteplus,cloudflare-ai-gateway,huggingface,kimi-coding,nvidia,qianfan,synthetic,together,venice,vercel-ai-gatewayyvolcengineusan solocatalog. - Qwen usa
catalogpara su proveedor de texto, además de registros compartidos de comprensión de medios y generación de video para sus superficies multimodales. - MiniMax y Xiaomi usan
catalog, además de hooks de uso, porque su comportamiento/usagees propiedad del plugin aunque la inferencia siga ejecutándose a través de los transportes compartidos.
Asistentes de tiempo de ejecución
Los plugins pueden acceder a asistentes seleccionados del core medianteapi.runtime. Para TTS:
textToSpeechdevuelve la carga útil de salida TTS normal del core para superficies de archivo/nota de voz.- Usa la configuración del core
messages.ttsy la selección de proveedor. - Devuelve buffer de audio PCM + frecuencia de muestreo. Los plugins deben remuestrear/codificar para los proveedores.
listVoiceses opcional por proveedor. Úsalo para selectores de voz o flujos de configuración propiedad del proveedor.- Los listados de voces pueden incluir metadatos más ricos como configuración regional, género y etiquetas de personalidad para selectores conscientes del proveedor.
- OpenAI y ElevenLabs admiten telefonía hoy. Microsoft no.
api.registerSpeechProvider(...).
- Mantén la política de TTS, el fallback y la entrega de respuestas en el core.
- Usa proveedores de voz para comportamiento de síntesis propiedad del proveedor.
- La entrada heredada
edgede Microsoft se normaliza al id de proveedormicrosoft. - El modelo de propiedad preferido está orientado por empresa: un solo plugin de proveedor puede ser propietario de texto, voz, imagen y futuros proveedores de medios a medida que OpenClaw agregue esos contratos de capacidad.
- Mantén la orquestación, el fallback, la configuración y la conexión con canales en el core.
- Mantén el comportamiento del proveedor en el plugin del proveedor.
- La expansión aditiva debe seguir siendo tipada: nuevos métodos opcionales, nuevos campos opcionales de resultado, nuevas capacidades opcionales.
- La generación de video ya sigue el mismo patrón:
- el core es propietario del contrato de capacidad y del asistente de tiempo de ejecución
- los plugins de proveedor registran
api.registerVideoGenerationProvider(...) - los plugins de función/canal consumen
api.runtime.videoGeneration.*
api.runtime.mediaUnderstanding.*es la superficie compartida preferida para comprensión de imagen/audio/video.- Usa la configuración de audio de comprensión de medios del core (
tools.media.audio) y el orden de fallback del proveedor. - Devuelve
{ text: undefined }cuando no se produce salida de transcripción (por ejemplo, entrada omitida/no compatible). api.runtime.stt.transcribeAudioFile(...)permanece como alias de compatibilidad.
api.runtime.subagent:
providerymodelson reemplazos opcionales por ejecución, no cambios persistentes de sesión.- OpenClaw solo respeta esos campos de reemplazo para llamadores de confianza.
- Para ejecuciones de fallback propiedad del plugin, los operadores deben habilitarlo explícitamente con
plugins.entries.<id>.subagent.allowModelOverride: true. - Usa
plugins.entries.<id>.subagent.allowedModelspara restringir los plugins de confianza a objetivos canónicos específicosprovider/model, o"*"para permitir explícitamente cualquier objetivo. - Las ejecuciones de subagentes de plugins no confiables siguen funcionando, pero las solicitudes de reemplazo se rechazan en lugar de recurrir silenciosamente al fallback.
api.registerWebSearchProvider(...).
Notas:
- Mantén en el core la selección de proveedor, la resolución de credenciales y la semántica compartida de solicitudes.
- Usa proveedores de búsqueda web para transportes de búsqueda específicos del proveedor.
api.runtime.webSearch.*es la superficie compartida preferida para plugins de función/canal que necesitan comportamiento de búsqueda sin depender del wrapper de la herramienta del agente.
api.runtime.imageGeneration
generate(...): genera una imagen usando la cadena configurada de proveedores de generación de imágenes.listProviders(...): enumera los proveedores de generación de imágenes disponibles y sus capacidades.
Rutas HTTP del Gateway
Los plugins pueden exponer endpoints HTTP conapi.registerHttpRoute(...).
path: ruta bajo el servidor HTTP del gateway.auth: obligatorio. Usa"gateway"para requerir autenticación normal del gateway, o"plugin"para autenticación/verificación de webhook administrada por el plugin.match: opcional."exact"(predeterminado) o"prefix".replaceExisting: opcional. Permite que el mismo plugin reemplace su propio registro de ruta existente.handler: devuelvetruecuando la ruta manejó la solicitud.
api.registerHttpHandler(...)fue eliminado y causará un error de carga del plugin. Usaapi.registerHttpRoute(...)en su lugar.- Las rutas de plugins deben declarar
authexplícitamente. - Los conflictos exactos de
path + matchse rechazan salvo quereplaceExisting: true, y un plugin no puede reemplazar la ruta de otro plugin. - Las rutas superpuestas con diferentes niveles de
authse rechazan. Mantén las cadenas de continuidadexact/prefixsolo en el mismo nivel de autenticación. - Las rutas
auth: "plugin"no reciben automáticamente ámbitos de tiempo de ejecución del operador. Son para webhooks/verificación de firmas administrados por el plugin, no para llamadas auxiliares privilegiadas del Gateway. - Las rutas
auth: "gateway"se ejecutan dentro de un ámbito de tiempo de ejecución de solicitud del Gateway, pero ese ámbito es intencionalmente conservador:- la autenticación bearer de secreto compartido (
gateway.auth.mode = "token"/"password") mantiene los ámbitos de tiempo de ejecución de rutas de plugin fijados enoperator.write, incluso si quien llama envíax-openclaw-scopes - los modos HTTP confiables con identidad (por ejemplo
trusted-proxyogateway.auth.mode = "none"en un ingreso privado) respetanx-openclaw-scopessolo cuando el encabezado está presente explícitamente - si
x-openclaw-scopesno está presente en esas solicitudes de ruta de plugin con identidad, el ámbito de tiempo de ejecución vuelve aoperator.write
- la autenticación bearer de secreto compartido (
- Regla práctica: no asumas que una ruta de plugin con autenticación de gateway es implícitamente una superficie de administrador. Si tu ruta necesita comportamiento exclusivo de administrador, exige un modo de autenticación con identidad y documenta el contrato explícito del encabezado
x-openclaw-scopes.
Rutas de importación del SDK de plugins
Usa subpaths del SDK en lugar de la importación monolíticaopenclaw/plugin-sdk al
desarrollar plugins:
openclaw/plugin-sdk/plugin-entrypara primitivas de registro de plugins.openclaw/plugin-sdk/corepara el contrato genérico compartido orientado a plugins.openclaw/plugin-sdk/config-schemapara la exportación del esquema Zod raíz deopenclaw.json(OpenClawSchema).- Primitivas estables de canal como
openclaw/plugin-sdk/channel-setup,openclaw/plugin-sdk/setup-runtime,openclaw/plugin-sdk/setup-adapter-runtime,openclaw/plugin-sdk/setup-tools,openclaw/plugin-sdk/channel-pairing,openclaw/plugin-sdk/channel-contract,openclaw/plugin-sdk/channel-feedback,openclaw/plugin-sdk/channel-inbound,openclaw/plugin-sdk/channel-lifecycle,openclaw/plugin-sdk/channel-reply-pipeline,openclaw/plugin-sdk/command-auth,openclaw/plugin-sdk/secret-inputyopenclaw/plugin-sdk/webhook-ingresspara la integración compartida de configuración/autenticación/respuesta/webhook.channel-inboundes el hogar compartido para debounce, coincidencia de menciones, asistentes de política de menciones entrantes, formato de sobres y asistentes de contexto de sobres entrantes.channel-setupes el seam acotado de configuración de instalación opcional.setup-runtimees la superficie de configuración segura en tiempo de ejecución usada porsetupEntry/ inicio diferido, incluidos los adaptadores de parche de configuración seguros para importación.setup-adapter-runtimees el seam de adaptador de configuración de cuentas sensible al entorno.setup-toolses el seam pequeño de asistentes de CLI/archivo/docs (formatCliCommand,detectBinary,extractArchive,resolveBrewExecutable,formatDocsLink,CONFIG_DIR). - Subpaths de dominio como
openclaw/plugin-sdk/channel-config-helpers,openclaw/plugin-sdk/allow-from,openclaw/plugin-sdk/channel-config-schema,openclaw/plugin-sdk/telegram-command-config,openclaw/plugin-sdk/channel-policy,openclaw/plugin-sdk/approval-gateway-runtime,openclaw/plugin-sdk/approval-handler-adapter-runtime,openclaw/plugin-sdk/approval-handler-runtime,openclaw/plugin-sdk/approval-runtime,openclaw/plugin-sdk/config-runtime,openclaw/plugin-sdk/infra-runtime,openclaw/plugin-sdk/agent-runtime,openclaw/plugin-sdk/lazy-runtime,openclaw/plugin-sdk/reply-history,openclaw/plugin-sdk/routing,openclaw/plugin-sdk/status-helpers,openclaw/plugin-sdk/text-runtime,openclaw/plugin-sdk/runtime-storeyopenclaw/plugin-sdk/directory-runtimepara asistentes compartidos de tiempo de ejecución/configuración.telegram-command-configes el seam público acotado para la normalización/validación de comandos personalizados de Telegram y sigue disponible aunque la superficie de contrato agrupada de Telegram no esté disponible temporalmente.text-runtimees el seam compartido de texto/markdown/logging, que incluye eliminación de texto visible para el asistente, asistentes de renderizado/fragmentación de markdown, asistentes de redacción, asistentes de etiquetas de directivas y utilidades de texto seguro. - Los seams de canal específicos de aprobación deben preferir un único contrato
approvalCapabilityen el plugin. Luego el core lee autenticación, entrega, renderizado, enrutamiento nativo y comportamiento diferido del controlador nativo a través de esa única capacidad en lugar de mezclar comportamiento de aprobación en campos no relacionados del plugin. openclaw/plugin-sdk/channel-runtimeestá obsoleto y permanece solo como un shim de compatibilidad para plugins antiguos. El código nuevo debe importar las primitivas genéricas más acotadas en su lugar, y el código del repo no debe agregar nuevas importaciones del shim.- Los internos de extensiones agrupadas siguen siendo privados. Los plugins externos deben usar solo
subpaths
openclaw/plugin-sdk/*. El código core/de prueba de OpenClaw puede usar los puntos de entrada públicos del repo bajo la raíz de un paquete de plugin comoindex.js,api.js,runtime-api.js,setup-entry.jsy archivos de alcance reducido comologin-qr-api.js. Nunca importessrc/*de un paquete de plugin desde el core ni desde otra extensión. - División de puntos de entrada del repo:
<plugin-package-root>/api.jses el barril de asistentes/tipos,<plugin-package-root>/runtime-api.jses el barril solo de tiempo de ejecución,<plugin-package-root>/index.jses el punto de entrada del plugin agrupado, y<plugin-package-root>/setup-entry.jses el punto de entrada del plugin de configuración. - Ejemplos actuales de proveedores agrupados:
- Anthropic usa
api.js/contract-api.jspara asistentes de stream de Claude comowrapAnthropicProviderStream, asistentes de encabezados beta y análisis deservice_tier. - OpenAI usa
api.jspara builders de proveedores, asistentes de modelo predeterminado y builders de proveedores en tiempo real. - OpenRouter usa
api.jspara su builder de proveedor más asistentes de incorporación/configuración, mientrasregister.runtime.jspuede seguir reexportando asistentes genéricosplugin-sdk/provider-streampara uso local del repo.
- Anthropic usa
- Los puntos de entrada públicos cargados por fachada prefieren la instantánea de configuración activa de tiempo de ejecución cuando existe una; luego recurren al archivo de configuración resuelto en disco cuando OpenClaw aún no está sirviendo una instantánea de tiempo de ejecución.
- Las primitivas genéricas compartidas siguen siendo el contrato público preferido del SDK. Aún existe
un pequeño conjunto de compatibilidad reservado de seams auxiliares de canal con marca agrupada. Trátalos como seams de mantenimiento/compatibilidad agrupados, no como nuevos objetivos de importación para terceros; los nuevos contratos entre canales deben seguir llegando a subpaths genéricos
plugin-sdk/*o a los barriles locales del pluginapi.js/runtime-api.js.
- Evita el barril raíz
openclaw/plugin-sdken código nuevo. - Prefiere primero las primitivas estables y acotadas. Los subpaths más recientes de configuración/asociación/respuesta/
feedback/contrato/entrada/hilos/comando/secret-input/webhook/infra/
allowlist/status/message-tool son el contrato previsto para trabajo nuevo con
plugins agrupados y externos.
El análisis/coincidencia de objetivos pertenece a
openclaw/plugin-sdk/channel-targets. Las compuertas de acciones de mensajes y los asistentes de id de mensaje para reacciones pertenecen aopenclaw/plugin-sdk/channel-actions. - Los barriles auxiliares específicos de extensiones agrupadas no son estables de forma predeterminada. Si un
asistente solo lo necesita una extensión agrupada, mantenlo detrás del seam
local
api.jsoruntime-api.jsde la extensión en lugar de promoverlo aopenclaw/plugin-sdk/<extension>. - Los nuevos seams de asistentes compartidos deben ser genéricos, no de marca de canal. El análisis compartido de
objetivos pertenece a
openclaw/plugin-sdk/channel-targets; los internos específicos del canal permanecen detrás del seam localapi.jsoruntime-api.jsdel plugin propietario. - Subpaths específicos de capacidades como
image-generation,media-understandingyspeechexisten porque los plugins agrupados/nativos los usan hoy. Su presencia no significa por sí sola que cada asistente exportado sea un contrato externo congelado a largo plazo.
Esquemas de la herramienta de mensajes
Los plugins deben ser propietarios de las contribuciones de esquema específicas del canal paradescribeMessageTool(...). Mantén los campos específicos del proveedor en el plugin, no en el core compartido.
Para fragmentos de esquema portables compartidos, reutiliza los asistentes genéricos exportados a través de
openclaw/plugin-sdk/channel-actions:
createMessageToolButtonsSchema()para cargas útiles de estilo cuadrícula de botonescreateMessageToolCardSchema()para cargas útiles de tarjeta estructurada
Resolución de objetivos de canal
Los plugins de canal deben ser propietarios de la semántica de objetivos específica del canal. Mantén genérico el host de salida compartido y usa la superficie del adaptador de mensajería para las reglas del proveedor:messaging.inferTargetChatType({ to })decide si un objetivo normalizado debe tratarse comodirect,groupochannelantes de la búsqueda en directorio.messaging.targetResolver.looksLikeId(raw, normalized)le dice al core si una entrada debe ir directamente a resolución tipo id en lugar de búsqueda en directorio.messaging.targetResolver.resolveTarget(...)es el fallback del plugin cuando el core necesita una resolución final propiedad del proveedor tras la normalización o tras un fallo en el directorio.messaging.resolveOutboundSessionRoute(...)es propietario de la construcción específica del proveedor de rutas de sesión de salida una vez que se resuelve un objetivo.
- Usa
inferTargetChatTypepara decisiones de categoría que deban ocurrir antes de buscar pares/grupos. - Usa
looksLikeIdpara comprobaciones de “tratar esto como un id de objetivo explícito/nativo”. - Usa
resolveTargetpara fallback de normalización específico del proveedor, no para búsqueda amplia en directorio. - Mantén ids nativos del proveedor como ids de chat, ids de hilo, JID, handles e ids de sala
dentro de valores
targeto parámetros específicos del proveedor, no en campos genéricos del SDK.
Directorios respaldados por configuración
Los plugins que derivan entradas de directorio a partir de la configuración deben mantener esa lógica en el plugin y reutilizar los asistentes compartidos deopenclaw/plugin-sdk/directory-runtime.
Usa esto cuando un canal necesite pares/grupos respaldados por configuración, como:
- pares de DM controlados por allowlist
- mapas configurados de canal/grupo
- fallbacks estáticos de directorio con alcance por cuenta
directory-runtime solo manejan operaciones genéricas:
- filtrado de consultas
- aplicación de límites
- asistentes de deduplicación/normalización
- construcción de
ChannelDirectoryEntry[]
Catálogos de proveedores
Los plugins de proveedor pueden definir catálogos de modelos para inferencia conregisterProvider({ catalog: { run(...) { ... } } }).
catalog.run(...) devuelve la misma forma que OpenClaw escribe en
models.providers:
{ provider }para una entrada de proveedor{ providers }para múltiples entradas de proveedor
catalog cuando el plugin sea propietario de ids de modelo específicos del proveedor, valores predeterminados de URL base o metadatos de modelos condicionados por autenticación.
catalog.order controla cuándo se fusiona el catálogo de un plugin en relación con los
proveedores implícitos integrados de OpenClaw:
simple: proveedores simples con clave API o impulsados por entornoprofile: proveedores que aparecen cuando existen perfiles de autenticaciónpaired: proveedores que sintetizan múltiples entradas de proveedor relacionadaslate: pasada final, después de otros proveedores implícitos
discoverysigue funcionando como alias heredado- si se registran
catalogydiscovery, OpenClaw usacatalog
Inspección de canal de solo lectura
Si tu plugin registra un canal, prefiere implementarplugin.config.inspectAccount(cfg, accountId) junto con resolveAccount(...).
Por qué:
resolveAccount(...)es la ruta de tiempo de ejecución. Puede asumir que las credenciales están completamente materializadas y puede fallar rápidamente cuando faltan secretos requeridos.- Las rutas de comandos de solo lectura como
openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolvey los flujos de doctor/reparación de configuración no deberían necesitar materializar credenciales de tiempo de ejecución solo para describir la configuración.
inspectAccount(...):
- Devuelve solo el estado descriptivo de la cuenta.
- Conserva
enabledyconfigured. - Incluye campos de origen/estado de credenciales cuando sea relevante, como:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- No necesitas devolver valores de token sin procesar solo para informar disponibilidad de solo lectura. Devolver
tokenStatus: "available"(y el campo de origen correspondiente) es suficiente para comandos de tipo estado. - Usa
configured_unavailablecuando una credencial esté configurada mediante SecretRef pero no disponible en la ruta actual del comando.
Paquetes agrupadores
Un directorio de plugin puede incluir unpackage.json con openclaw.extensions:
name/<fileBase>.
Si tu plugin importa dependencias npm, instálalas en ese directorio para que
node_modules esté disponible (npm install / pnpm install).
Barandilla de seguridad: cada entrada de openclaw.extensions debe permanecer dentro del directorio del plugin
después de resolver symlinks. Las entradas que escapan del directorio del paquete se
rechazan.
Nota de seguridad: openclaw plugins install instala dependencias de plugins con
npm install --omit=dev --ignore-scripts (sin scripts de ciclo de vida, sin dependencias de desarrollo en tiempo de ejecución). Mantén los árboles de dependencias de plugins en “JS/TS puro” y evita paquetes que requieran compilaciones en postinstall.
Opcional: openclaw.setupEntry puede apuntar a un módulo ligero solo de configuración.
Cuando OpenClaw necesita superficies de configuración para un plugin de canal deshabilitado, o
cuando un plugin de canal está habilitado pero sigue sin configurarse, carga setupEntry
en lugar del punto de entrada completo del plugin. Esto hace que el inicio y la configuración sean más ligeros
cuando el punto de entrada principal del plugin también conecta herramientas, hooks u otro código
solo de tiempo de ejecución.
Opcional: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
puede hacer que un plugin de canal opte por esa misma ruta setupEntry durante la
fase de inicio previa a listen del gateway, incluso cuando el canal ya está configurado.
Usa esto solo cuando setupEntry cubra completamente la superficie de inicio que debe existir
antes de que el gateway empiece a escuchar. En la práctica, eso significa que la entrada de configuración
debe registrar todas las capacidades propiedad del canal de las que dependa el inicio, como:
- el propio registro del canal
- cualquier ruta HTTP que deba estar disponible antes de que el gateway empiece a escuchar
- cualquier método, herramienta o servicio del gateway que deba existir durante esa misma ventana
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* sin cargar el punto de entrada completo del plugin.
Matrix es el ejemplo agrupado actual: mueve solo claves de autenticación/bootstrap a una
cuenta promovida con nombre cuando ya existen cuentas con nombre, y puede preservar una
clave predeterminada configurada no canónica en lugar de crear siempre
accounts.default.
Esos adaptadores de parche de configuración mantienen perezoso el descubrimiento de la superficie de contrato agrupada. El tiempo
de importación sigue siendo ligero; la superficie de promoción se carga solo en el primer uso en lugar de
reingresar al inicio del canal agrupado al importar el módulo.
Cuando esas superficies de inicio incluyen métodos RPC del gateway, mantenlos en un
prefijo específico del plugin. Los espacios de nombres administrativos del core (config.*,
exec.approvals.*, wizard.*, update.*) permanecen reservados y siempre se resuelven
a operator.admin, incluso si un plugin solicita un ámbito más acotado.
Ejemplo:
Metadatos del catálogo de canales
Los plugins de canal pueden anunciar metadatos de configuración/descubrimiento medianteopenclaw.channel y
sugerencias de instalación mediante openclaw.install. Esto mantiene el catálogo del core libre de datos.
Ejemplo:
openclaw.channel además del ejemplo mínimo:
detailLabel: etiqueta secundaria para superficies más ricas de catálogo/estadodocsLabel: reemplaza el texto del enlace para el enlace de documentaciónpreferOver: ids de plugin/canal de menor prioridad que esta entrada de catálogo debe superarselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: controles de texto para superficies de selecciónmarkdownCapable: marca el canal como compatible con markdown para decisiones de formato de salidaexposure.configured: oculta el canal de las superficies de listado de canales configurados cuando se establece enfalseexposure.setup: oculta el canal de los selectores interactivos de configuración cuando se establece enfalseexposure.docs: marca el canal como interno/privado para superficies de navegación de documentaciónshowConfigured/showInSetup: alias heredados aún aceptados por compatibilidad; prefiereexposurequickstartAllowFrom: hace que el canal participe en el flujo estándar de quickstartallowFromforceAccountBinding: requiere asociación explícita de cuenta incluso cuando solo existe una cuentapreferSessionLookupForAnnounceTarget: prefiere la búsqueda de sesión al resolver objetivos de anuncio
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
OPENCLAW_PLUGIN_CATALOG_PATHS (o OPENCLAW_MPM_CATALOG_PATHS) apunte 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": {...} } } ] }. El analizador también acepta "packages" o "plugins" como aliases heredados para la clave "entries".
Plugins del motor de contexto
Los plugins del motor de contexto son propietarios de la orquestación del contexto de sesión para ingesta, ensamblado y compactación. Regístralos desde tu plugin conapi.registerContextEngine(id, factory) y luego selecciona el motor activo con
plugins.slots.contextEngine.
Usa esto cuando tu plugin necesite reemplazar o extender la canalización de contexto predeterminada en lugar de solo agregar búsqueda en memory o hooks.
compact()
implementado y delega explícitamente en él:
Agregar una nueva capacidad
Cuando un plugin necesite un comportamiento que no encaje en la API actual, no evites el sistema de plugins con un acceso privado. Agrega la capacidad que falta. Secuencia recomendada:- definir el contrato del core Decide qué comportamiento compartido debe ser propiedad del core: política, fallback, combinación de configuración, ciclo de vida, semántica orientada al canal y forma del asistente de tiempo de ejecución.
- agregar superficies tipadas de registro/tiempo de ejecución para plugins
Extiende
OpenClawPluginApiy/oapi.runtimecon la superficie tipada de capacidad más pequeña que sea útil. - conectar consumidores del core y de canal/función Los canales y plugins de función deben consumir la nueva capacidad a través del core, no importando directamente una implementación del proveedor.
- registrar implementaciones del proveedor Los plugins de proveedor registran entonces sus backends en la capacidad.
- agregar cobertura de contrato Agrega pruebas para que la propiedad y la forma del registro sigan siendo explícitas con el tiempo.
Lista de verificación de capacidades
Cuando agregues una nueva capacidad, la implementación normalmente debería tocar estas superficies en conjunto:- tipos de contrato del core en
src/<capability>/types.ts - runner/asistente de tiempo de ejecución del core en
src/<capability>/runtime.ts - superficie de registro de la API de plugins en
src/plugins/types.ts - conexión del registro de plugins en
src/plugins/registry.ts - exposición del tiempo de ejecución del plugin en
src/plugins/runtime/*cuando los plugins de función/canal necesiten consumirlo - asistentes de captura/prueba en
src/test-utils/plugin-registration.ts - aserciones de propiedad/contrato en
src/plugins/contracts/registry.ts - documentación para operadores/plugins en
docs/
Plantilla de capacidad
Patrón mínimo:- el core es propietario del contrato de capacidad y de la orquestación
- los plugins de proveedor son propietarios de las implementaciones del proveedor
- los plugins de función/canal consumen asistentes de tiempo de ejecución
- las pruebas de contrato mantienen explícita la propiedad