Aspectos internos de plugins
Esta es la referencia profunda de arquitectura. Para guías prácticas, consulta:
- Install and use plugins — guía de usuario
- Getting Started — primer tutorial de plugins
- Channel Plugins — crea un canal de mensajería
- Provider Plugins — crea un proveedor de modelos
- SDK Overview — mapa de imports y API de registro
Modelo público de capacidades
Las capacidades son el modelo público de plugin nativo 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 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 multimedia | api.registerMediaUnderstandingProvider(...) | openai, google |
| Generación de imágenes | api.registerImageGenerationProvider(...) | openai, google, fal, 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á integrado en el núcleo y lo usan hoy los plugins nativos/incluidos, pero la compatibilidad de plugins externos aún necesita un listón más estricto que “si se exporta, entonces está congelado”. Guía actual:- plugins externos existentes: mantén funcionando las integraciones basadas en hooks; trátalo como la base de compatibilidad
- nuevos plugins nativos/incluidos: da preferencia al registro explícito de capacidades sobre accesos específicos de proveedor o nuevos diseños solo con hooks
- plugins externos que adoptan el registro de capacidades: permitido, pero trata las superficies helper específicas de capacidad como cambiantes, 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 rupturas en plugins externos durante la transición
- no todas las subrutas helper exportadas son iguales; da preferencia al contrato documentado y estrecho, no a exports helper incidentales
Formas de los 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 varios tipos de capacidad (por ejemplo
openaiposee inferencia de texto, voz, comprensión multimedia 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 de un plugin y el
desglose de capacidades. Consulta CLI reference para más detalles.
Hooks heredados
El hookbefore_agent_start sigue siendo compatible como ruta de compatibilidad para
plugins solo con hooks. Plugins heredados reales 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 del prompt - eliminarlo solo cuando el uso real caiga y la cobertura de fixtures demuestre la seguridad de la migración
Señales de compatibilidad
Cuando ejecutesopenclaw 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 más 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 se pudo cargar |
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
de espacio de trabajo, raíces globales de extensiones y extensiones incluidas. El descubrimiento lee primero
los manifests nativos
openclaw.plugin.jsonmás los manifests de bundles compatibles. - Habilitación + validación El núcleo decide si un plugin descubierto está habilitado, deshabilitado, bloqueado o seleccionado para una ranura exclusiva como memory.
- Carga en tiempo de ejecución Los plugins nativos de OpenClaw se cargan en 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 superficie El resto de OpenClaw lee el registro para exponer herramientas, canales, configuración de proveedores, hooks, rutas HTTP, comandos CLI y servicios.
- los metadatos en tiempo de análisis vienen de
registerCli(..., { descriptors: [...] }) - el módulo CLI real del plugin puede seguir siendo lazy y registrarse en la primera invocación
- el descubrimiento + la validación de configuración deben funcionar a partir de metadatos de manifest/schema sin ejecutar código del plugin
- el comportamiento nativo de tiempo de ejecución proviene de la ruta
register(api)del módulo del plugin
Plugins de canal y la herramienta compartida de mensajes
Los plugins de canal no necesitan registrar una herramienta independiente de send/edit/react para las acciones normales de chat. OpenClaw mantiene una herramienta compartidamessage en el núcleo, y
los plugins de canal poseen el descubrimiento y la ejecución específicos del canal detrás de ella.
El límite actual es:
- el núcleo posee el host de la herramienta compartida
message, el cableado del prompt, la contabilidad de sesiones/hilos y el despacho de ejecución - los plugins de canal poseen el descubrimiento de acciones con alcance, el descubrimiento de capacidades y cualquier fragmento de schema específico del canal
- los plugins de canal poseen la gramática de conversación de sesión específica del proveedor, como cómo los ids de conversación codifican ids 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 unificada de descubrimiento
permite que un plugin devuelva sus acciones visibles, capacidades y contribuciones al schema
juntas, para que esas piezas no se desalineen.
El núcleo pasa el alcance de tiempo de ejecución a ese paso de descubrimiento. Los campos importantes incluyen:
accountIdcurrentChannelIdcurrentThreadTscurrentMessageIdsessionKeysessionIdagentIdrequesterSenderIdentrante de confianza
message.
Por eso los cambios de enrutamiento del embedded-runner siguen siendo trabajo del plugin: el ejecutor es
responsable de reenviar la identidad actual del chat/sesión al límite de descubrimiento del plugin para que la herramienta compartida message exponga la superficie correcta,
propiedad del canal, para el turno actual.
Para helpers de ejecución propiedad del canal, los plugins incluidos deben mantener el tiempo de ejecución de ejecución
dentro de sus propios módulos de extensión. El núcleo ya no posee los tiempos de ejecución de acciones de mensaje de Discord,
Slack, Telegram o WhatsApp bajo src/agents/tools.
No publicamos subrutas separadas plugin-sdk/*-action-runtime, y los plugins incluidos
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 núcleo no
debe importar barrels de conveniencia específicos del canal para Slack, Discord, Signal,
WhatsApp o extensiones similares. Si el núcleo necesita un comportamiento, debe consumir el
barrel api.ts / runtime-api.ts del propio plugin incluido o promover la necesidad
a una capacidad genérica estrecha en el SDK compartido.
Para polls específicamente, hay dos rutas de ejecución:
outbound.sendPolles la base compartida para canales que encajan en el modelo común de pollactions.handleAction("poll")es la ruta preferida para semánticas de poll específicas del canal o parámetros extra de poll
Modelo de propiedad de capacidades
OpenClaw trata un plugin nativo como el límite de propiedad para una empresa o una función, no como una colección desordenada de integraciones no relacionadas. Eso significa:- un plugin de empresa normalmente debe poseer todas las superficies de OpenClaw de esa empresa
- un plugin de función normalmente debe poseer toda la superficie de la función que introduce
- los canales deben consumir capacidades compartidas del núcleo en lugar de volver a implementar comportamiento de proveedor de forma ad hoc
- el plugin incluido
openaiposee el comportamiento del proveedor de modelos OpenAI y el comportamiento de voz + realtime-voice + media-understanding + image-generation de OpenAI - el plugin incluido
elevenlabsposee el comportamiento de voz de ElevenLabs - el plugin incluido
microsoftposee el comportamiento de voz de Microsoft - el plugin incluido
googleposee el comportamiento del proveedor de modelos Google más el comportamiento de media-understanding + image-generation + web-search de Google - el plugin incluido
firecrawlposee el comportamiento de web-fetch de Firecrawl - los plugins incluidos
minimax,mistral,moonshotyzaiposeen sus backends de media-understanding - el plugin
voice-calles un plugin de función: posee transporte de llamadas, herramientas, CLI, rutas y el puente de media-stream de Twilio, pero consume capacidades compartidas de voz más realtime-transcription y realtime-voice en lugar de importar plugins de proveedor directamente
- OpenAI vive en un solo plugin aunque abarque modelos de texto, voz, imágenes y futuro video
- otro proveedor puede hacer lo mismo para su propia superficie
- los canales no se preocupan por qué plugin de proveedor posee el proveedor; consumen el contrato de capacidad compartida expuesto por el núcleo
- plugin = límite de propiedad
- capability = contrato central que varios plugins pueden implementar o consumir
- definir la capacidad faltante en el núcleo
- exponerla a través de la API/runtime del plugin de forma tipada
- conectar canales/funciones contra esa capacidad
- dejar que los plugins de proveedor registren implementaciones
Capas de capacidad
Usa este modelo mental al decidir dónde debe ir el código:- capa central de capacidad: orquestación compartida, política, respaldo, reglas de fusión de configuración, semántica de entrega y contratos tipados
- capa de plugin 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 plugin de canal/función: integración de Slack/Discord/voice-call/etc. que consume capacidades centrales y las presenta en una superficie
- el núcleo posee la política TTS en tiempo de respuesta, el orden de respaldo, preferencias y entrega por canal
openai,elevenlabsymicrosoftposeen las implementaciones de síntesisvoice-callconsume el helper de tiempo de ejecución TTS de telefonía
Ejemplo de plugin de empresa con varias 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 multimedia, generación de imágenes, generación de video, web fetch y web search, un proveedor puede poseer todas sus superficies en un solo lugar:- un plugin posee la superficie del proveedor
- el núcleo sigue poseyendo los contratos de capacidad
- los canales y plugins de función consumen helpers
api.runtime.*, no código del proveedor - las pruebas de contrato pueden afirmar que el plugin registró las capacidades que dice poseer
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 allí:- el núcleo define el contrato de media-understanding
- los plugins de proveedor registran
describeImage,transcribeAudioydescribeVideosegún corresponda - los plugins de canal y de función consumen el comportamiento compartido del núcleo en lugar de conectarse directamente al código del proveedor
api.registerVideoGenerationProvider(...) contra él.
¿Necesitas una lista concreta de despliegue? Consulta
Capability Cookbook.
Contratos y aplicación
La superficie de la API de plugins es intencionalmente tipada y centralizada enOpenClawPluginApi. Ese contrato define los puntos de registro compatibles y
los helpers de tiempo de ejecución de los que un plugin puede depender.
Por qué importa:
- los autores de plugins obtienen un estándar interno estable
- el núcleo puede rechazar propiedad duplicada como dos plugins que registren el mismo id de proveedor
- el inicio puede mostrar diagnósticos accionables para registros mal formados
- las pruebas de contrato pueden hacer cumplir la propiedad de plugins incluidos y evitar derivas silenciosas
- aplicación del registro en tiempo de ejecución El registro de plugins valida los registros a medida que se cargan los plugins. Ejemplos: ids de proveedor duplicados, ids de proveedor de voz duplicados y registros mal formados producen diagnósticos de plugins en lugar de comportamiento indefinido.
- pruebas de contrato Los plugins incluidos 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 incluida.
Qué pertenece a un contrato
Los buenos contratos de plugins son:- tipados
- pequeños
- específicos por capacidad
- propiedad del núcleo
- reutilizables por varios plugins
- consumibles por canales/funciones sin conocimiento del proveedor
- política específica del proveedor oculta en el núcleo
- escapes puntuales de plugin que omiten el registro
- código de canal que accede directamente a una implementación de 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 en 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 núcleo. Implicaciones:- un plugin nativo puede registrar herramientas, manejadores de red, hooks y servicios
- un error en un plugin nativo puede hacer caer o desestabilizar el gateway
- un plugin nativo malicioso equivale a ejecución de código arbitrario dentro del proceso de OpenClaw
@openclaw/<id> por defecto, o un sufijo tipado aprobado como
-provider, -plugin, -speech, -sandbox o -media-understanding cuando
el paquete expone intencionalmente un rol de plugin más estrecho.
Nota importante sobre confianza:
plugins.allowconfía en ids de plugin, no en la procedencia de la fuente.- Un plugin de espacio de trabajo con el mismo id que un plugin incluido oculta intencionalmente la copia incluida cuando ese plugin de espacio de trabajo está habilitado/en allowlist.
- Esto es normal y útil para desarrollo local, pruebas de parches y hotfixes.
Límite de exportación
OpenClaw exporta capacidades, no comodidad de implementación. Mantén público el registro de capacidades. Reduce exports helper que no formen parte del contrato:- subrutas helper específicas de plugins incluidos
- subrutas de plomería de tiempo de ejecución no pensadas como API pública
- helpers de conveniencia específicos del proveedor
- helpers de setup/onboarding 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
exports reservados de detalle de implementación, no como el patrón recomendado del SDK para
nuevos plugins de terceros.
Pipeline de carga
Al iniciar, OpenClaw hace aproximadamente esto:- descubrir raíces candidatas de plugins
- leer manifests nativos o compatibles de bundles y metadatos de paquetes
- rechazar candidatos inseguros
- normalizar la configuración de plugins (
plugins.enabled,allow,deny,entries,slots,load.paths) - decidir la habilitación para cada candidato
- cargar módulos nativos habilitados mediante jiti
- llamar a los hooks nativos
register(api)(oactivate(api)— un alias heredado) y recopilar registros en el registro de plugins - exponer el registro a superficies de comandos/runtime
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 incluidos usan register; prefiere register para plugins nuevos.Comportamiento manifest-first
El manifest es la fuente de verdad del plano de control. OpenClaw lo usa para:- identificar el plugin
- descubrir canales/skills/schema de configuración declarados o capacidades del bundle
- validar
plugins.entries.<id>.config - ampliar etiquetas/placeholders de la UI de control
- mostrar metadatos de instalación/catálogo
Qué almacena en caché el cargador
OpenClaw mantiene cachés cortas en proceso para:- resultados de descubrimiento
- datos del registro de manifests
- registros de plugins cargados
- Define
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 núcleo. Se registran en un registro central de plugins. El registro rastrea:- registros de plugins (identidad, fuente, origen, estado, diagnósticos)
- herramientas
- hooks heredados y hooks tipados
- canales
- proveedores
- manejadores RPC del gateway
- rutas HTTP
- registradores CLI
- servicios en segundo plano
- comandos propiedad del plugin
- módulo del plugin -> registro en el registro
- tiempo de ejecución del núcleo -> consumo del registro
Callbacks de binding de conversación
Los plugins que vinculan una conversación pueden reaccionar cuando se resuelve una aprobación. Usaapi.onConversationBindingResolved(...) para recibir un callback después de que una solicitud de binding sea aprobada o denegada:
status:"approved"o"denied"decision:"allow-once","allow-always"o"deny"binding: el binding resuelto para solicitudes aprobadasrequest: el resumen original de la solicitud, sugerencia de desacople, id del remitente y metadatos de conversación
Hooks de tiempo de ejecución del proveedor
Los plugins de proveedor ahora tienen dos capas:- metadatos del manifest:
providerAuthEnvVarspara búsqueda barata de auth por entorno antes de cargar el runtime, másproviderAuthChoicespara etiquetas baratas de onboarding/auth-choice y metadatos de flags CLI antes de cargar el runtime - hooks en tiempo de configuración:
catalog/ heredadodiscoverymásapplyConfigDefaults - hooks de tiempo de ejecución:
normalizeModelId,normalizeTransport,normalizeConfig,applyNativeStreamingUsageCompat,resolveConfigApiKey,resolveSyntheticAuth,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 entorno
que las rutas genéricas de auth/status/model-picker deban ver sin cargar el runtime del plugin.
Usa el manifest providerAuthChoices cuando las superficies CLI de onboarding/auth-choice
deban conocer el id de elección del proveedor, etiquetas de grupo y
cableado simple de auth con un solo flag sin cargar el runtime del proveedor. Mantén envVars del runtime del proveedor para sugerencias orientadas al operador como etiquetas de onboarding o variables de
configuración de client-id/client-secret de OAuth.
Orden y uso de hooks
Para plugins de modelo/proveedor, OpenClaw llama a los hooks en este orden aproximado. La columna “Cuándo usarlo” es la guía rápida de decisión.| # | Hook | Qué hace | Cuándo usarlo |
|---|---|---|---|
| 1 | catalog | Publica configuración del proveedor en models.providers durante la generación de models.json | El proveedor posee un catálogo o valores predeterminados de base URL |
| 2 | applyConfigDefaults | Aplica valores predeterminados globales propiedad del proveedor durante la materialización de configuración | Los valores predeterminados dependen del modo de auth, del entorno o de la semántica de la familia de modelos del proveedor |
| — | (búsqueda integrada de modelo) | OpenClaw prueba primero la ruta normal de registro/catálogo | (no es un hook de plugin) |
| 3 | normalizeModelId | Normaliza alias heredados o preview de ids de modelo antes de la búsqueda | El proveedor posee la limpieza de alias antes de la resolución canónica del modelo |
| 4 | normalizeTransport | Normaliza api / baseUrl de la familia del proveedor antes del ensamblaje genérico del modelo | El proveedor posee la limpieza del transporte para ids personalizados de proveedor en la misma familia de transporte |
| 5 | normalizeConfig | Normaliza models.providers.<id> antes de la resolución de runtime/proveedor | El proveedor necesita limpieza de configuración que deba vivir con el plugin; los helpers incluidos de la familia Google también respaldan entradas compatibles de configuración Google |
| 6 | applyNativeStreamingUsageCompat | Aplica reescrituras de compatibilidad de uso de streaming nativo a proveedores configurados | El proveedor necesita correcciones de metadatos de uso de streaming nativo basadas en endpoint |
| 7 | resolveConfigApiKey | Resuelve auth de marcador de entorno para proveedores configurados antes de cargar el runtime de auth | El proveedor tiene resolución de API key mediante marcador de entorno propiedad del proveedor; amazon-bedrock también tiene aquí un resolvedor integrado de marcador de entorno AWS |
| 8 | resolveSyntheticAuth | Expone auth local/self-hosted o basada en configuración sin conservar texto sin formato | El proveedor puede operar con un marcador de credencial sintético/local |
| 9 | shouldDeferSyntheticProfileAuth | Baja la prioridad de placeholders sintéticos almacenados detrás de auth basada en entorno/configuración | El proveedor almacena perfiles sintéticos placeholder que no deben ganar precedencia |
| 10 | resolveDynamicModel | Respaldo síncrono para ids de modelo propiedad del proveedor que aún no están en el registro local | El proveedor acepta ids de modelo upstream arbitrarios |
| 11 | prepareDynamicModel | Calentamiento asíncrono, luego resolveDynamicModel vuelve a ejecutarse | El proveedor necesita metadatos de red antes de resolver ids desconocidos |
| 12 | normalizeResolvedModel | Reescritura final antes de que el embedded runner use el modelo resuelto | El proveedor necesita reescrituras de transporte pero sigue usando un transporte central |
| 13 | contributeResolvedModelCompat | Aporta indicadores de compatibilidad para modelos de proveedor detrás de otro transporte compatible | El proveedor reconoce sus propios modelos en transportes proxy sin asumir el control del proveedor |
| 14 | capabilities | Metadatos de transcripción/herramientas propiedad del proveedor usados por lógica central compartida | El proveedor necesita particularidades de transcripción/familia de proveedor |
| 15 | normalizeToolSchemas | Normaliza schemas de herramientas antes de que el embedded runner los vea | El proveedor necesita limpieza de schema de la familia de transporte |
| 16 | inspectToolSchemas | Expone diagnósticos de schema propiedad del proveedor después de la normalización | El proveedor quiere advertencias de palabras clave sin enseñar al núcleo reglas específicas del proveedor |
| 17 | resolveReasoningOutputMode | Selecciona contrato de salida de razonamiento nativo frente a etiquetado | El proveedor necesita razonamiento/salida final etiquetados en lugar de campos nativos |
| 18 | prepareExtraParams | Normalización de parámetros de solicitud antes de wrappers genéricos de opciones de stream | El proveedor necesita parámetros predeterminados de solicitud o limpieza de parámetros por proveedor |
| 19 | createStreamFn | Reemplaza completamente la ruta normal de stream por un transporte personalizado | El proveedor necesita un protocolo wire personalizado, no solo un wrapper |
| 20 | wrapStreamFn | Wrapper de stream después de aplicar wrappers genéricos | El proveedor necesita wrappers de compatibilidad de headers/body/modelo sin un transporte personalizado |
| 21 | resolveTransportTurnState | Adjunta headers nativos por turno o metadatos de transporte | El proveedor quiere que transportes genéricos envíen identidad de turno nativa del proveedor |
| 22 | resolveWebSocketSessionPolicy | Adjunta headers nativos de WebSocket o política de enfriamiento de sesión | El proveedor quiere que los transportes WS genéricos ajusten headers de sesión o política de respaldo |
| 23 | formatApiKey | Formateador de perfil de auth: el perfil almacenado se convierte en la cadena apiKey de runtime | El proveedor almacena metadatos extra de auth y necesita una forma personalizada del token en runtime |
| 24 | refreshOAuth | Reemplazo de refresh OAuth para endpoints personalizados de refresh o política de fallo de refresh | El proveedor no encaja en los refreshers compartidos pi-ai |
| 25 | buildAuthDoctorHint | Sugerencia de reparación añadida cuando falla el refresh OAuth | El proveedor necesita guía de reparación de auth propiedad del proveedor tras el fallo de refresh |
| 26 | matchesContextOverflowError | Detector de overflow de ventana de contexto propiedad del proveedor | El proveedor tiene errores crudos de overflow que las heurísticas genéricas no detectarían |
| 27 | classifyFailoverReason | Clasificación de motivos de failover propiedad del proveedor | El proveedor puede mapear errores crudos de API/transporte a rate-limit/sobrecarga/etc. |
| 28 | isCacheTtlEligible | Política de caché de prompt para proveedores proxy/backhaul | El proveedor necesita control de TTL de caché específico de proxy |
| 29 | buildMissingAuthMessage | Sustitución del mensaje genérico de recuperación por auth faltante | El proveedor necesita una sugerencia específica del proveedor para auth faltante |
| 30 | suppressBuiltInModel | Supresión de modelos upstream obsoletos más sugerencia opcional visible al usuario | El proveedor necesita ocultar filas obsoletas upstream o reemplazarlas con una sugerencia del proveedor |
| 31 | augmentModelCatalog | Filas sintéticas/finales del catálogo agregadas después del descubrimiento | El proveedor necesita filas sintéticas de compatibilidad futura en models list y selectores |
| 32 | isBinaryThinking | Conmutador on/off de razonamiento para proveedores de thinking binario | El proveedor expone solo thinking binario encendido/apagado |
| 33 | supportsXHighThinking | Compatibilidad con razonamiento xhigh para modelos seleccionados | El proveedor quiere xhigh solo en un subconjunto de modelos |
| 34 | resolveDefaultThinkingLevel | Nivel predeterminado de /think para una familia concreta de modelos | El proveedor posee la política predeterminada de /think para una familia de modelos |
| 35 | isModernModelRef | Detector de modelos modernos para filtros live por perfil y selección smoke | El proveedor posee el emparejamiento preferido de modelos para live/smoke |
| 36 | prepareRuntimeAuth | Intercambia una credencial configurada por el token/clave real justo antes de la inferencia | El proveedor necesita un intercambio de token o una credencial efímera por solicitud |
| 37 | resolveUsageAuth | Resuelve credenciales de uso/facturación para /usage y superficies de estado relacionadas | El proveedor necesita análisis personalizado del token de uso/cuota o una credencial de uso distinta |
| 38 | fetchUsageSnapshot | Obtiene y normaliza instantáneas de uso/cuota específicas del proveedor después de resolver auth | El proveedor necesita un endpoint de uso específico del proveedor o un parser de payload específico |
| 39 | createEmbeddingProvider | Construye un adaptador de embeddings propiedad del proveedor para memory/search | El comportamiento de embeddings de memory debe vivir con el plugin del proveedor |
| 40 | buildReplayPolicy | Devuelve una política de replay que controla el manejo de la transcripción del proveedor | El proveedor necesita una política personalizada de transcripción (por ejemplo, eliminar bloques de thinking) |
| 41 | sanitizeReplayHistory | Reescribe el historial de replay después de la limpieza genérica de transcripción | El proveedor necesita reescrituras específicas de replay más allá de los helpers compartidos de compactación |
| 42 | validateReplayTurns | Validación o remodelado final de turnos de replay antes del embedded runner | El transporte del proveedor necesita una validación más estricta de turnos tras el saneamiento genérico |
| 43 | onModelSelected | Ejecuta efectos secundarios propiedad del proveedor después de seleccionar un modelo | El proveedor necesita telemetría o estado propiedad del proveedor cuando un modelo se activa |
normalizeModelId, normalizeTransport y normalizeConfig primero comprueban el
plugin de proveedor emparejado y luego recorren otros plugins de proveedor con capacidad de hook
hasta que uno realmente cambie el id del modelo o el transporte/configuración. Eso mantiene
funcionando los shims de alias/compatibilidad de proveedor sin obligar al llamador a saber qué
plugin incluido posee la reescritura. Si ningún hook de proveedor reescribe una entrada compatible
de configuración de la familia Google, el normalizador incluido de configuración Google sigue aplicando
esa limpieza de compatibilidad.
Si el proveedor necesita un protocolo wire completamente personalizado o un ejecutor de solicitud personalizado,
eso es otra clase de extensión. Estos hooks son para comportamiento de proveedor que
sigue ejecutándose sobre el bucle normal de inferencia de OpenClaw.
Ejemplo de proveedor
Ejemplos integrados
- Anthropic usa
resolveDynamicModel,capabilities,buildAuthDoctorHint,resolveUsageAuth,fetchUsageSnapshot,isCacheTtlEligible,resolveDefaultThinkingLevel,applyConfigDefaults,isModernModelRefywrapStreamFnporque posee compatibilidad futura con Claude 4.6, sugerencias de familia de proveedor, guía de reparación de auth, integración de endpoint de uso, elegibilidad de caché de prompt, valores predeterminados de configuración conscientes de la auth, política predeterminada/adaptativa de thinking para Claude y modelado de stream específico de Anthropic para headers beta,/fast/serviceTierycontext1m. - Los helpers de stream específicos de Claude en Anthropic se mantienen por ahora en el
seam público
api.ts/contract-api.tsdel propio plugin incluido. Esa superficie del paquete exportawrapAnthropicProviderStream, helpers de beta-header, análisis deservice_tiery builders de wrapper de Anthropic de bajo nivel, en lugar de ampliar el SDK genérico en torno a las reglas beta-header de un solo proveedor. - OpenAI usa
resolveDynamicModel,normalizeResolvedModelycapabilitiesmásbuildMissingAuthMessage,suppressBuiltInModel,augmentModelCatalog,supportsXHighThinkingeisModernModelRefporque posee compatibilidad futura con GPT-5.4, la normalización directa de OpenAIopenai-completions->openai-responses, pistas de auth conscientes de Codex, supresión de Spark, filas sintéticas de OpenAI y política de thinking / modelo live de GPT-5; la familia de streamopenai-responses-defaultsposee los wrappers nativos compartidos de OpenAI Responses para headers de atribución,/fast/serviceTier, verbosidad de texto, web search nativo de Codex, modelado de payload de compatibilidad de razonamiento y gestión de contexto de Responses. - OpenRouter usa
catalogmásresolveDynamicModelyprepareDynamicModelporque el proveedor es pass-through 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 núcleo los headers de solicitud específicos del proveedor, los metadatos de enrutamiento, los parches de razonamiento y la política de caché de prompt. Su política de replay viene de la familiapassthrough-gemini, mientras que la familia de streamopenrouter-thinkingposee la inyección de razonamiento proxy y los saltos para modelos no compatibles /auto. - GitHub Copilot usa
catalog,auth,resolveDynamicModelycapabilitiesmásprepareRuntimeAuthyfetchUsageSnapshotporque necesita login por dispositivo propiedad del proveedor, comportamiento de respaldo de modelos, 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,refreshOAuthyaugmentModelCatalogmásprepareExtraParams,resolveUsageAuthyfetchUsageSnapshotporque sigue ejecutándose sobre transportes centrales de OpenAI pero posee su normalización de transporte/base URL, política de respaldo de refresh OAuth, elección de transporte predeterminada, filas sintéticas del catálogo Codex e integración del endpoint de uso de ChatGPT; comparte la misma familia de streamopenai-responses-defaultsque OpenAI directo. - Google AI Studio y Gemini CLI OAuth usan
resolveDynamicModel,buildReplayPolicy,sanitizeReplayHistory,resolveReasoningOutputMode,wrapStreamFneisModernModelRefporque la familia de replaygoogle-geminiposee el respaldo de compatibilidad futura de Gemini 3.1, la validación nativa de replay de Gemini, el saneamiento de replay de bootstrap, el modo etiquetado de salida de razonamiento y el emparejamiento moderno de modelos, mientras que la familia de streamgoogle-thinkingposee la normalización del payload de thinking de Gemini; Gemini CLI OAuth también usaformatApiKey,resolveUsageAuthyfetchUsageSnapshotpara formateo de tokens, análisis de tokens y conexión al 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 limitada a ids de Claude en lugar de aplicarse a cada transporteanthropic-messages. - Amazon Bedrock usa
buildReplayPolicy,matchesContextOverflowError,classifyFailoverReasonyresolveDefaultThinkingLevelporque posee la clasificación específica de Bedrock de errores de throttle/not-ready/context-overflow para tráfico Anthropic-on-Bedrock; su política de replay sigue compartiendo la misma barrera solo-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 saneamiento de firmas de thought 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 proveedor posee tanto semántica de mensajes Anthropic como OpenAI-compatible; mantiene la eliminación de bloques de thinking solo de Claude en el lado Anthropic y, al mismo tiempo, vuelve a sobrescribir el modo de salida de razonamiento a nativo, y la familia de streamminimax-fast-modeposee las reescrituras de modelo en modo rápido en la ruta de stream compartida. - Moonshot usa
catalogmáswrapStreamFnporque sigue usando el transporte compartido de OpenAI pero necesita normalización del payload de thinking propiedad del proveedor; la familia de streammoonshot-thinkingmapea la configuración más el estado/thinka su payload nativo binario de thinking. - Kilocode usa
catalog,capabilities,wrapStreamFneisCacheTtlEligibleporque necesita headers de solicitud propiedad del proveedor, normalización del payload de razonamiento, sugerencias de transcripción de Gemini y control de TTL de caché de Anthropic; la familia de streamkilocode-thinkingmantiene la inyección de thinking de Kilo en la ruta de stream proxy compartida mientras omitekilo/autoy otros ids de modelo proxy que no admiten payloads explícitos de razonamiento. - Z.AI usa
resolveDynamicModel,prepareExtraParams,wrapStreamFn,isCacheTtlEligible,isBinaryThinking,isModernModelRef,resolveUsageAuthyfetchUsageSnapshotporque posee respaldo GLM-5, valores predeterminadostool_stream, UX de thinking binario, emparejamiento moderno de modelos y tanto auth de uso como obtención de cuota; la familia de streamtool-stream-default-onmantiene el wrapper predeterminado detool_streamfuera del pegamento manuscrito por proveedor. - xAI usa
normalizeResolvedModel,normalizeTransport,contributeResolvedModelCompat,prepareExtraParams,wrapStreamFn,resolveSyntheticAuth,resolveDynamicModeleisModernModelRefporque posee normalización nativa del transporte xAI Responses, reescrituras de alias de Grok fast-mode,tool_streampredeterminado, limpieza estricta de herramientas / payload de razonamiento, reutilización de auth de respaldo para herramientas propiedad del plugin, resolución de modelo Grok con compatibilidad futura y parches de compatibilidad propiedad del proveedor como el perfil de schema de herramientas de xAI, palabras clave de schema no compatibles,web_searchnativo y decodificación de argumentos de llamadas a herramientas con entidades HTML. - Mistral, OpenCode Zen y OpenCode Go usan solo
capabilitiespara mantener las particularidades de transcripción/herramientas fuera del núcleo. - Proveedores incluidos 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 más registros compartidos de media-understanding y video-generation para sus superficies multimodales. - MiniMax y Xiaomi usan
catalogmás hooks de uso porque su comportamiento/usagees propiedad del plugin aunque la inferencia siga ejecutándose a través de los transportes compartidos.
Helpers de tiempo de ejecución
Los plugins pueden acceder a helpers seleccionados del núcleo medianteapi.runtime. Para TTS:
textToSpeechdevuelve la carga útil normal de salida TTS del núcleo para superficies de archivo/nota de voz.- Usa la configuración central
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 setup 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 TTS, el respaldo y la entrega de respuestas en el núcleo.
- 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 a empresa: un plugin de proveedor puede poseer texto, voz, imagen y futuros proveedores multimedia a medida que OpenClaw agregue esos contratos de capacidad.
- Mantén la orquestación, el respaldo, la configuración y el cableado del canal en el núcleo.
- 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 núcleo posee el contrato de capacidad y el helper 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 central de audio de media-understanding (
tools.media.audio) y el orden de respaldo 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 respaldo propiedad del plugin, los operadores deben optar explícitamente con
plugins.entries.<id>.subagent.allowModelOverride: true. - Usa
plugins.entries.<id>.subagent.allowedModelspara restringir plugins de confianza a objetivos canónicos concretosprovider/model, o"*"para permitir explícitamente cualquier objetivo. - Las ejecuciones de subagente de plugins no confiables siguen funcionando, pero las solicitudes de reemplazo se rechazan en lugar de recurrir silenciosamente a un valor predeterminado.
api.registerWebSearchProvider(...).
Notas:
- Mantén la selección de proveedor, la resolución de credenciales y la semántica compartida de la solicitud en el núcleo.
- 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 necesiten comportamiento de búsqueda sin depender del wrapper de herramienta del agente.
api.runtime.imageGeneration
generate(...): genera una imagen usando la cadena configurada de proveedores de generación de imágenes.listProviders(...): lista proveedores disponibles de generación de imágenes 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 la auth normal del gateway, o"plugin"para auth gestionada por el plugin / verificación de webhook.match: opcional."exact"(predeterminado) o"prefix".replaceExisting: opcional. Permite al mismo plugin reemplazar su propio registro de ruta existente.handler: devuelvetruecuando la ruta ha manejado la solicitud.
api.registerHttpHandler(...)fue eliminado y provocará un error de carga del plugin. Usaapi.registerHttpRoute(...)en su lugar.- Las rutas de plugins deben declarar
authexplícitamente. - Los conflictos exactos
path + matchse rechazan salvo quereplaceExisting: true, y un plugin no puede reemplazar la ruta de otro plugin. - Las rutas solapadas con distintos niveles de
authse rechazan. Mantén las cadenas de caídaexact/prefixsolo en el mismo nivel de auth. - Las rutas
auth: "plugin"no reciben automáticamente alcances de tiempo de ejecución de operador. Son para webhooks/verificación de firma gestionados por el plugin, no para llamadas helper privilegiadas del Gateway. - Las rutas
auth: "gateway"se ejecutan dentro de un alcance de tiempo de ejecución de solicitud del Gateway, pero ese alcance es intencionalmente conservador:- la auth bearer de secreto compartido (
gateway.auth.mode = "token"/"password") mantiene los alcances de runtime de rutas de plugin fijados aoperator.write, incluso si quien llama envíax-openclaw-scopes - los modos HTTP de confianza con identidad (por ejemplo
trusted-proxyogateway.auth.mode = "none"en un ingreso privado) respetanx-openclaw-scopessolo cuando el encabezado está explícitamente presente - si
x-openclaw-scopesestá ausente en esas solicitudes de rutas de plugin con identidad, el alcance de runtime recurre aoperator.write
- la auth bearer de secreto compartido (
- Regla práctica: no asumas que una ruta de plugin con auth de gateway es una superficie implícita de administración. Si tu ruta necesita comportamiento exclusivo de admin, exige un modo de auth con identidad y documenta el contrato explícito del encabezado
x-openclaw-scopes.
Rutas de import del Plugin SDK
Usa subrutas del SDK en lugar del import monolíticoopenclaw/plugin-sdk al
crear 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 el export del schema 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 cableado compartido de setup/auth/reply/webhook.channel-inboundes el hogar compartido para debounce, coincidencia de menciones, formato de sobres y helpers de contexto de sobre entrante.channel-setupes el seam estrecho de setup para instalación opcional.setup-runtimees la superficie de setup segura para runtime usada porsetupEntry/ inicio diferido, incluidos los adaptadores de parche de setup seguros para import.setup-adapter-runtimees el seam del adaptador de setup de cuenta consciente del entorno.setup-toolses el seam pequeño de helpers CLI/archivo/docs (formatCliCommand,detectBinary,extractArchive,resolveBrewExecutable,formatDocsLink,CONFIG_DIR). - Subrutas 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-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 helpers compartidos de runtime/configuración.telegram-command-configes el seam público estrecho para normalización/validación de comandos personalizados de Telegram y sigue disponible incluso si la superficie de contrato incluida de Telegram no está disponible temporalmente.text-runtimees el seam compartido de texto/markdown/registro, incluida la eliminación de texto visible para el asistente, helpers de renderizado/fragmentación de markdown, helpers de redacción, helpers 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 núcleo lee auth, entrega, renderizado y comportamiento de enrutamiento nativo de aprobaciones a través de esa única capacidad en lugar de mezclar el comportamiento de aprobaciones en campos no relacionados del plugin. openclaw/plugin-sdk/channel-runtimeestá obsoleto y permanece solo como shim de compatibilidad para plugins más antiguos. El código nuevo debe importar las primitivas genéricas más estrechas, y el código del repositorio no debe agregar nuevos imports del shim.- Los internos de extensiones incluidas siguen siendo privados. Los plugins externos deben usar solo subrutas
openclaw/plugin-sdk/*. El código/pruebas del núcleo de OpenClaw puede usar los puntos de entrada públicos del repositorio bajo la raíz de un paquete de plugin comoindex.js,api.js,runtime-api.js,setup-entry.jsy archivos de alcance estrecho comologin-qr-api.js. Nunca importessrc/*de un paquete de plugin desde el núcleo ni desde otra extensión. - División del punto de entrada del repositorio:
<plugin-package-root>/api.jses el barrel de helpers/tipos,<plugin-package-root>/runtime-api.jses el barrel solo de tiempo de ejecución,<plugin-package-root>/index.jses la entrada del plugin incluido y<plugin-package-root>/setup-entry.jses la entrada del plugin de setup. - Ejemplos actuales de proveedores incluidos:
- Anthropic usa
api.js/contract-api.jspara helpers de stream de Claude comowrapAnthropicProviderStream, helpers de beta-header y parsing deservice_tier. - OpenAI usa
api.jspara builders de proveedor, helpers de modelos predeterminados y builders de proveedores realtime. - OpenRouter usa
api.jspara su builder de proveedor más helpers de onboarding/configuración, mientras queregister.runtime.jspuede seguir reexportando helpers genéricosplugin-sdk/provider-streampara uso local del repositorio.
- Anthropic usa
- Los puntos de entrada públicos cargados mediante facade prefieren la instantánea activa de configuración de runtime cuando existe una, y luego recurren al archivo de configuración resuelto en disco cuando OpenClaw aún no está sirviendo una instantánea de runtime.
- Las primitivas genéricas compartidas siguen siendo el contrato público preferido del SDK. Aún existe un pequeño conjunto reservado de compatibilidad de seams helper con marca de canal incluida. Trátalos como seams de mantenimiento/compatibilidad incluidos, no como nuevos objetivos de import de terceros; los nuevos contratos entre canales deben seguir llegando a subrutas genéricas
plugin-sdk/*o a los barrels localesapi.js/runtime-api.jsdel plugin.
- Evita el barrel raíz
openclaw/plugin-sdken código nuevo. - Da preferencia primero a las primitivas estables y estrechas. Las nuevas subrutas de
setup/pairing/reply/feedback/contract/inbound/threading/command/secret-input/webhook/infra/
allowlist/status/message-tool son el contrato previsto para nuevo trabajo de plugins incluidos y externos.
El análisis/emparejamiento de targets pertenece a
openclaw/plugin-sdk/channel-targets. Las barreras de acciones de mensaje y los helpers de id de mensaje de reacciones pertenecen aopenclaw/plugin-sdk/channel-actions. - Los barrels helper específicos de extensiones incluidas no son estables por defecto. Si un
helper solo lo necesita una extensión incluida, mantenlo detrás del seam local
api.jsoruntime-api.jsde la extensión en lugar de promoverlo aopenclaw/plugin-sdk/<extension>. - Los nuevos seams helper compartidos deben ser genéricos, no de marca de canal. El análisis compartido de target
pertenece a
openclaw/plugin-sdk/channel-targets; los internos específicos del canal siguen detrás del seam localapi.jsoruntime-api.jsdel plugin propietario. - Existen subrutas específicas por capacidad como
image-generation,media-understandingyspeechporque los plugins nativos/incluidos las usan hoy. Su presencia no significa por sí sola que cada helper exportado sea un contrato externo congelado a largo plazo.
Schemas de herramientas de mensajes
Los plugins deben poseer las contribuciones específicas del canal al schema dedescribeMessageTool(...).
Mantén los campos específicos del proveedor en el plugin, no en el núcleo compartido.
Para fragmentos de schema portables compartidos, reutiliza los helpers genéricos exportados por
openclaw/plugin-sdk/channel-actions:
createMessageToolButtonsSchema()para cargas tipo cuadrícula de botonescreateMessageToolCardSchema()para cargas de tarjetas estructuradas
Resolución de target de canal
Los plugins de canal deben poseer la semántica específica del canal para targets. Mantén genérico el host saliente compartido y usa la superficie del adaptador de mensajería para las reglas del proveedor:messaging.inferTargetChatType({ to })decide si un target normalizado debe tratarse comodirect,groupochannelantes de la búsqueda en el directorio.messaging.targetResolver.looksLikeId(raw, normalized)indica al núcleo si una entrada debe pasar directamente a una resolución tipo id en lugar de una búsqueda en directorio.messaging.targetResolver.resolveTarget(...)es el respaldo del plugin cuando el núcleo necesita una resolución final propiedad del proveedor después de la normalización o después de un fallo en el directorio.messaging.resolveOutboundSessionRoute(...)posee la construcción específica del proveedor de la ruta de sesión saliente una vez resuelto un target.
- Usa
inferTargetChatTypepara decisiones de categoría que deban ocurrir antes de buscar peers/groups. - Usa
looksLikeIdpara comprobaciones del tipo “tratar esto como un id de target explícito/nativo”. - Usa
resolveTargetcomo respaldo específico del proveedor para normalización, no para búsqueda amplia en directorio. - Mantén ids nativos del proveedor como chat ids, thread ids, JIDs, handles e room ids 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 desde la configuración deben mantener esa lógica en el plugin y reutilizar los helpers compartidos deopenclaw/plugin-sdk/directory-runtime.
Usa esto cuando un canal necesite peers/groups respaldados por configuración, como:
- peers DM controlados por allowlist
- mapas configurados de canal/grupo
- respaldos estáticos de directorio con alcance por cuenta
directory-runtime solo gestionan operaciones genéricas:
- filtrado de consulta
- aplicación de límites
- helpers 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 varias entradas de proveedor
catalog cuando el plugin posea ids de modelo específicos del proveedor, valores predeterminados de base URL
o metadatos de modelos condicionados por auth.
catalog.order controla cuándo se fusiona el catálogo de un plugin con respecto a
los proveedores implícitos integrados de OpenClaw:
simple: proveedores simples controlados por API key o entornoprofile: proveedores que aparecen cuando existen perfiles de authpaired: proveedores que sintetizan varias entradas de proveedor relacionadaslate: último paso, después de otros proveedores implícitos
discoverysigue funcionando como alias heredado- si se registran ambos
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 runtime. 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/config repair no deberían necesitar materializar credenciales de runtime solo para describir la configuración.
inspectAccount(...):
- Devuelve solo 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 brutos de tokens solo para informar disponibilidad de solo lectura. Devolver
tokenStatus: "available"(y el campo de origen correspondiente) es suficiente para comandos tipo status. - Usa
configured_unavailablecuando una credencial esté configurada mediante SecretRef pero no disponible en la ruta de comandos actual.
Package packs
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).
Barrera de seguridad: cada entrada openclaw.extensions debe permanecer dentro del directorio del plugin
después de resolver symlinks. Las entradas que escapen del directorio del paquete se
rechazan.
Nota de seguridad: openclaw plugins install instala dependencias de plugins con
npm install --omit=dev --ignore-scripts (sin lifecycle scripts y sin dev dependencies en runtime). Mantén los árboles de dependencias de plugins como “pure JS/TS” y evita paquetes que requieran builds en postinstall.
Opcional: openclaw.setupEntry puede apuntar a un módulo ligero solo de setup.
Cuando OpenClaw necesita superficies de setup para un plugin de canal deshabilitado, o
cuando un plugin de canal está habilitado pero aún no configurado, carga setupEntry
en lugar de la entrada completa del plugin. Esto mantiene el inicio y el setup más ligeros
cuando la entrada principal del plugin también conecta herramientas, hooks u otro código solo de runtime.
Opcional: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
puede hacer que un plugin de canal opte por la 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 setup
debe registrar todas las capacidades propiedad del canal de las que depende 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 del gateway, herramienta o servicio que deba existir durante esa misma ventana
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* sin cargar la entrada completa del plugin.
Matrix es el ejemplo incluido actual: mueve solo claves de auth/bootstrap a una
cuenta promocionada con nombre cuando ya existen cuentas con nombre, y puede conservar una
clave de cuenta predeterminada configurada no canónica en lugar de crear siempre
accounts.default.
Esos adaptadores de parche de setup mantienen lazy el descubrimiento de la superficie de contrato incluida.
El tiempo de importación sigue siendo ligero; la superficie de promoción se carga solo en el primer uso en lugar de volver a entrar en el inicio del canal incluido en la importación del 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 centrales de administración (config.*,
exec.approvals.*, wizard.*, update.*) siguen reservados y siempre se resuelven
a operator.admin, incluso si un plugin solicita un alcance más estrecho.
Ejemplo:
Metadatos de catálogo de canales
Los plugins de canal pueden anunciar metadatos de setup/descubrimiento medianteopenclaw.channel e
instrucciones de instalación mediante openclaw.install. Esto mantiene el catálogo central sin datos.
Ejemplo:
openclaw.channel además del ejemplo mínimo:
detailLabel: etiqueta secundaria para superficies más ricas de catálogo/statusdocsLabel: sobrescribe el texto del enlace de documentaciónpreferOver: ids de plugin/canal de menor prioridad a los que esta entrada del catálogo debe adelantarselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: controles de copia para superficies de selecciónmarkdownCapable: marca el canal como compatible con markdown para decisiones de formato salienteshowConfigured: oculta el canal en superficies de listado de canales configurados cuando se define enfalsequickstartAllowFrom: hace que el canal opte por el flujo estándar quickstart deallowFromforceAccountBinding: requiere binding explícito de cuenta incluso cuando solo existe una cuentapreferSessionLookupForAnnounceTarget: prefiere la búsqueda de sesión al resolver objetivos de announce
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
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": {...} } } ] }. El analizador también acepta "packages" o "plugins" como alias heredados de la clave "entries".
Plugins de motor de contexto
Los plugins de motor de contexto poseen la orquestación del contexto de sesión para ingestión, ensamblaje 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 ampliar el pipeline de contexto predeterminado
en lugar de solo agregar búsqueda en memory o hooks.
compact()
implementado y delégalo explícitamente:
Agregar una nueva capacidad
Cuando un plugin necesite un comportamiento que no encaje en la API actual, no omitas el sistema de plugins con un acceso privado. Agrega la capacidad que falta. Secuencia recomendada:- define el contrato central Decide qué comportamiento compartido debe poseer el núcleo: política, respaldo, fusión de configuración, ciclo de vida, semántica orientada a canales y forma del helper de tiempo de ejecución.
- agrega superficies tipadas de registro/runtime para plugins
Amplía
OpenClawPluginApiy/oapi.runtimecon la superficie tipada de capacidad más pequeña que sea útil. - conecta consumidores del núcleo + canales/funciones Los canales y plugins de función deben consumir la nueva capacidad a través del núcleo, no importando directamente una implementación del proveedor.
- registra implementaciones de proveedores Luego los plugins de proveedor registran sus backends contra la capacidad.
- agrega 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 debe tocar estas superficies en conjunto:- tipos del contrato central en
src/<capability>/types.ts - ejecutor/helper de runtime central en
src/<capability>/runtime.ts - superficie de registro de la API de plugins en
src/plugins/types.ts - cableado del registro de plugins en
src/plugins/registry.ts - exposición de runtime de plugins en
src/plugins/runtime/*cuando los plugins de función/canal necesiten consumirla - helpers de captura/prueba en
src/test-utils/plugin-registration.ts - afirmaciones de propiedad/contrato en
src/plugins/contracts/registry.ts - documentación para operadores/plugins en
docs/
Plantilla de capacidad
Patrón mínimo:- el núcleo posee el contrato de capacidad + la orquestación
- los plugins de proveedor poseen las implementaciones del proveedor
- los plugins de función/canal consumen helpers de runtime
- las pruebas de contrato mantienen explícita la propiedad