Los hooks de Plugin son puntos de extensión en proceso para plugins de OpenClaw. Úsalos cuando un plugin necesite inspeccionar o cambiar ejecuciones de agentes, llamadas a herramientas, flujo de mensajes, ciclo de vida de sesiones, enrutamiento de subagentes, instalaciones o el inicio del Gateway. Usa hooks internos en su lugar cuando quieras un pequeño scriptDocumentation Index
Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
HOOK.md instalado por el operador para eventos de comandos y Gateway, como
/new, /reset, /stop, agent:bootstrap o gateway:startup.
Inicio rápido
Registra hooks de plugin tipados conapi.on(...) desde la entrada de tu plugin:
priority. Los hooks con la misma prioridad
mantienen el orden de registro.
api.on(name, handler, opts?) acepta:
priority: orden del manejador (los valores más altos se ejecutan primero).timeoutMs: presupuesto opcional por hook. Cuando se establece, el ejecutor de hooks aborta ese manejador después de que venza el presupuesto y continúa con el siguiente, en lugar de permitir que una configuración lenta o trabajo de recuperación consuma el timeout de modelo configurado por el llamador. Omítelo para usar el timeout predeterminado de observación/decisión que el ejecutor de hooks aplica de forma genérica.
hooks.timeouts.<hookName> sobrescribe hooks.timeoutMs, que sobrescribe el
valor api.on(..., { timeoutMs }) escrito por el plugin. Cada valor configurado debe
ser un entero positivo no mayor que 600000 milisegundos. Prefiere anulaciones por hook
para hooks lentos conocidos, de modo que un plugin no reciba un presupuesto más largo
en todas partes.
Cada hook recibe event.context.pluginConfig, la configuración resuelta para el
plugin que registró ese manejador. Úsala para decisiones de hooks que necesiten
las opciones actuales del plugin; OpenClaw la inyecta por manejador sin mutar el
objeto de evento compartido que ven otros plugins.
Catálogo de hooks
Los hooks se agrupan por la superficie que extienden. Los nombres en negrita aceptan un resultado de decisión (bloquear, cancelar, sobrescribir o requerir aprobación); todos los demás son solo de observación. Turno del agentebefore_model_resolve: sobrescribe el proveedor o el modelo antes de que se carguen los mensajes de sesiónagent_turn_prepare: consume inyecciones de turno de plugin en cola y agrega contexto del mismo turno antes de los hooks de promptbefore_prompt_build: agrega contexto dinámico o texto de prompt del sistema antes de la llamada al modelobefore_agent_start: fase combinada solo por compatibilidad; prefiere los dos hooks anterioresbefore_agent_run: inspecciona el prompt final y los mensajes de sesión antes del envío al modelo y, opcionalmente, bloquea la ejecuciónbefore_agent_reply: interrumpe el turno del modelo con una respuesta sintética o silenciobefore_agent_finalize: inspecciona la respuesta final natural y solicita una pasada más del modeloagent_end: observa los mensajes finales, el estado de éxito y la duración de la ejecuciónheartbeat_prompt_contribution: agrega contexto solo de Heartbeat para plugins de monitor en segundo plano y ciclo de vida
model_call_started/model_call_ended: observa metadatos saneados de llamadas a proveedor/modelo, tiempos, resultado y hashes acotados de ID de solicitud sin contenido de prompt ni respuestallm_input: observa la entrada del proveedor (prompt del sistema, prompt, historial)llm_output: observa la salida del proveedor
before_tool_call: reescribe parámetros de la herramienta, bloquea la ejecución o requiere aprobaciónafter_tool_call: observa resultados de herramientas, errores y duracióntool_result_persist: reescribe el mensaje del asistente producido a partir de un resultado de herramientabefore_message_write: inspecciona o bloquea una escritura de mensaje en curso (raro)
inbound_claim: reclama un mensaje entrante antes del enrutamiento del agente (respuestas sintéticas)message_received: observa el contenido entrante, remitente, hilo y metadatosmessage_sending: reescribe contenido saliente o cancela la entregamessage_sent: observa el éxito o fallo de la entrega salientebefore_dispatch: inspecciona o reescribe un envío saliente antes de la transferencia al canalreply_dispatch: participa en la canalización final de despacho de respuestas
session_start/session_end: rastrea límites del ciclo de vida de la sesión. Elreasondel evento es uno denew,reset,idle,daily,compaction,deleted,shutdown,restartounknown. Los valoresshutdownyrestartse disparan desde el finalizador de apagado del gateway cuando el proceso se detiene o reinicia mientras las sesiones siguen activas, de modo que los plugins posteriores (como almacenes de memoria o transcripciones) puedan finalizar filas fantasma que, de lo contrario, quedarían en estado abierto entre reinicios. El finalizador está acotado para que un plugin lento no pueda bloquear SIGTERM/SIGINT.before_compaction/after_compaction: observa o anota ciclos de Compactionbefore_reset: observa eventos de restablecimiento de sesión (/reset, restablecimientos programáticos)
subagent_spawning/subagent_delivery_target/subagent_spawned/subagent_ended- coordinan el enrutamiento de subagentes y la entrega de finalización
gateway_start/gateway_stop- inician o detienen servicios propiedad del plugin con el Gatewaycron_changed- observan cambios del ciclo de vida de cron propiedad del gateway (agregado, actualizado, eliminado, iniciado, finalizado, programado)before_install- inspecciona análisis de instalación de Skills o plugins y, opcionalmente, bloquea
Política de llamadas a herramientas
before_tool_call recibe:
event.toolNameevent.paramsevent.derivedPathsopcional, que contiene indicios de rutas de destino derivadas del host con el mejor esfuerzo para envoltorios de herramientas conocidos comoapply_patch; cuando están presentes, estas rutas pueden estar incompletas o sobreestimar lo que la herramienta realmente tocará (por ejemplo, con entradas mal formadas o parciales)event.runIdopcionalevent.toolCallIdopcional- campos de contexto como
ctx.agentId,ctx.sessionKey,ctx.sessionId,ctx.runId,ctx.jobId(establecido en ejecuciones impulsadas por cron) yctx.tracede diagnóstico
block: truees terminal y omite los controladores de menor prioridad.block: falsese trata como ninguna decisión.paramsreescribe los parámetros de la herramienta para la ejecución.requireApprovalpausa la ejecución del agente y solicita al usuario mediante aprobaciones de plugin. El comando/approvepuede aprobar tanto aprobaciones de exec como de plugin.- Un
block: truede menor prioridad aún puede bloquear después de que un hook de mayor prioridad haya solicitado aprobación. onResolutionrecibe la decisión de aprobación resuelta:allow-once,allow-always,deny,timeoutocancelled.
api.registerTrustedToolPolicy(...). Estas se ejecutan antes de los hooks before_tool_call ordinarios y antes de las decisiones de plugins externos. Úsalas solo para puertas de confianza del host, como política del espacio de trabajo, aplicación de presupuestos o seguridad de flujos de trabajo reservados. Los plugins externos deben usar hooks before_tool_call normales.
Persistencia de resultados de herramientas
Los resultados de herramientas pueden incluirdetails estructurados para renderizado de la interfaz, diagnósticos, enrutamiento de medios o metadatos propiedad del plugin. Trata details como metadatos de runtime, no como contenido del prompt:
- OpenClaw elimina
toolResult.detailsantes de la reproducción del proveedor y de la entrada de Compaction para que los metadatos no se conviertan en contexto del modelo. - Las entradas de sesión persistidas conservan solo
detailsacotados. Los detalles demasiado grandes se reemplazan por un resumen compacto ypersistedDetailsTruncated: true. tool_result_persistybefore_message_writese ejecutan antes del límite final de persistencia. Aun así, los hooks deben mantener pequeños losdetailsdevueltos y evitar colocar texto relevante para el prompt solo endetails; coloca la salida de la herramienta visible para el modelo encontent.
Hooks de prompt y modelo
Usa los hooks específicos de fase para plugins nuevos:before_model_resolve: recibe solo el prompt actual y los metadatos de adjuntos. DevuelveproviderOverrideomodelOverride.agent_turn_prepare: recibe el prompt actual, los mensajes de sesión preparados y cualquier inyección en cola exactamente una vez drenada para esta sesión. DevuelveprependContextoappendContext.before_prompt_build: recibe el prompt actual y los mensajes de sesión. DevuelveprependContext,appendContext,systemPrompt,prependSystemContextoappendSystemContext.heartbeat_prompt_contribution: se ejecuta solo para turnos de Heartbeat y devuelveprependContextoappendContext. Está pensado para monitores en segundo plano que necesitan resumir el estado actual sin cambiar turnos iniciados por el usuario.
before_agent_start se mantiene por compatibilidad. Prefiere los hooks explícitos anteriores para que tu plugin no dependa de una fase combinada heredada.
before_agent_run se ejecuta después de la construcción del prompt y antes de cualquier entrada del modelo, incluida la carga de imágenes locales del prompt y la observación llm_input. Recibe la entrada de usuario actual como prompt, además del historial de sesión cargado en messages y el prompt del sistema activo. Devuelve { outcome: "block", reason, message? } para detener la ejecución antes de que el modelo pueda leer el prompt. reason es interno; message es el reemplazo visible para el usuario. Los únicos resultados admitidos son pass y block; las formas de decisión no admitidas fallan cerradas.
Cuando se bloquea una ejecución, OpenClaw almacena solo el texto de reemplazo en message.content más metadatos de bloqueo no sensibles, como el id del plugin bloqueador y la marca de tiempo. El texto original del usuario no se conserva en la transcripción ni en el contexto futuro. Las razones internas de bloqueo se tratan como sensibles y se excluyen de transcripciones, historial, difusión, logs y cargas útiles de diagnóstico. La observabilidad debe usar campos saneados, como id del bloqueador, resultado, marca de tiempo o una categoría segura.
before_agent_start y agent_end incluyen event.runId cuando OpenClaw puede identificar la ejecución activa. El mismo valor también está disponible en ctx.runId. Las ejecuciones impulsadas por Cron también exponen ctx.jobId (el id del trabajo cron de origen) para que los hooks de plugin puedan acotar métricas, efectos secundarios o estado a un trabajo programado específico.
Para ejecuciones originadas en canales, ctx.messageProvider es la superficie del proveedor, como discord o telegram, mientras que ctx.channelId es el identificador de destino de la conversación cuando OpenClaw puede derivarlo de la clave de sesión o de los metadatos de entrega.
agent_end es un hook de observación y se ejecuta sin esperar resultado después del turno. El ejecutor de hooks aplica un tiempo de espera de 30 segundos para que un plugin bloqueado o un endpoint de embeddings no pueda dejar la promesa del hook pendiente indefinidamente. Un tiempo de espera se registra en logs y OpenClaw continúa; no cancela el trabajo de red propiedad del plugin a menos que el plugin también use su propia señal de aborto.
Use model_call_started y model_call_ended para la telemetría de llamadas al proveedor
que no debe recibir prompts sin procesar, historial, respuestas, encabezados, cuerpos de
solicitud ni ID de solicitud del proveedor. Estos hooks incluyen metadatos estables como
runId, callId, provider, model, api/transport opcionales, durationMs/outcome
terminales y upstreamRequestIdHash cuando OpenClaw puede derivar un hash acotado del ID
de solicitud del proveedor.
before_agent_finalize se ejecuta solo cuando un harness está a punto de aceptar una
respuesta final natural del asistente. No es la ruta de cancelación /stop y no se
ejecuta cuando el usuario aborta un turno. Devuelve { action: "revise", reason } para
pedir al harness una pasada más del modelo antes de finalizar, { action: "finalize", reason? } para forzar la finalización, u omite un resultado para continuar.
Los hooks nativos Stop de Codex se retransmiten a este hook como decisiones
before_agent_finalize de OpenClaw.
Al devolver action: "revise", los plugins pueden incluir metadatos retry para hacer
que la pasada adicional del modelo sea acotada y segura para repetición:
instruction se agrega al motivo de revisión enviado al harness.
idempotencyKey permite que el host cuente los reintentos para la misma solicitud del
plugin entre decisiones de finalización equivalentes, y maxAttempts limita cuántas
pasadas adicionales permitirá el host antes de continuar con la respuesta final natural.
Los plugins no incluidos que necesitan hooks de conversación sin procesar (before_model_resolve,
before_agent_reply, llm_input, llm_output, before_agent_finalize,
agent_end o before_agent_run) deben configurar:
plugins.entries.<id>.hooks.allowPromptInjection=false.
Extensiones de sesión e inyecciones para el siguiente turno
Los plugins de workflow pueden persistir un estado de sesión pequeño compatible con JSON conapi.registerSessionExtension(...) y actualizarlo mediante el método
sessions.pluginPatch del Gateway. Las filas de sesión proyectan el estado de extensión registrado
mediante pluginExtensions, lo que permite que Control UI y otros clientes representen el estado
propiedad del plugin sin conocer sus detalles internos.
Usa api.enqueueNextTurnInjection(...) cuando un plugin necesite que contexto duradero
llegue exactamente una vez al siguiente turno del modelo. OpenClaw vacía las inyecciones en cola antes de
los hooks de prompt, descarta las inyecciones vencidas y deduplica por idempotencyKey
por plugin. Esta es la interfaz adecuada para reanudaciones de aprobación, resúmenes de políticas,
deltas de monitores en segundo plano y continuaciones de comandos que deben ser visibles para
el modelo en el siguiente turno, pero no deben convertirse en texto permanente del prompt del sistema.
La semántica de limpieza forma parte del contrato. La limpieza de extensiones de sesión y
los callbacks de limpieza del ciclo de vida en runtime reciben reset, delete, disable o
restart. El host elimina el estado persistente de extensión de sesión del plugin propietario
y las inyecciones pendientes para el siguiente turno en reset/delete/disable; restart conserva
el estado de sesión duradero mientras los callbacks de limpieza permiten que los plugins liberen
trabajos del programador, contexto de ejecución y otros recursos fuera de banda de la antigua generación
del runtime.
Hooks de mensaje
Usa hooks de mensaje para el enrutamiento a nivel de canal y la política de entrega:message_received: observa el contenido entrante, remitente,threadId,messageId,senderId, correlación opcional de ejecución/sesión y metadatos.message_sending: reescribecontento devuelve{ cancel: true }.message_sent: observa el éxito o fallo final.
content puede contener la transcripción hablada oculta
incluso cuando la carga útil del canal no tiene texto/caption visible. Reescribir ese
content actualiza solo la transcripción visible para el hook; no se renderiza como caption
de medios.
Los contextos de hooks de mensaje exponen campos de correlación estables cuando están disponibles:
ctx.sessionKey, ctx.runId, ctx.messageId, ctx.senderId, ctx.trace,
ctx.traceId, ctx.spanId, ctx.parentSpanId y ctx.callDepth. Prefiere
estos campos de primera clase antes de leer metadatos heredados.
Prefiere los campos tipados threadId y replyToId antes de usar metadatos específicos del canal.
Reglas de decisión:
message_sendingconcancel: truees terminal.message_sendingconcancel: falsese trata como ausencia de decisión.- El
contentreescrito continúa hacia hooks de menor prioridad salvo que un hook posterior cancele la entrega. message_sendingpuede devolvercancelReasonymetadataacotados con una cancelación. Las nuevas API de ciclo de vida de mensajes lo exponen como un resultado de entrega suprimida con motivocancelled_by_message_sending_hook; la entrega directa heredada sigue devolviendo un array de resultados vacío por compatibilidad.message_sentes solo de observación. Los fallos de handlers se registran y no cambian el resultado de entrega.
Hooks de instalación
before_install se ejecuta después del escaneo integrado para instalaciones de Skills y plugins.
Devuelve hallazgos adicionales o { block: true, blockReason } para detener la
instalación.
block: true es terminal. block: false se trata como ausencia de decisión.
Ciclo de vida del Gateway
Usagateway_start para servicios de plugin que necesitan estado propiedad del Gateway. El
contexto expone ctx.config, ctx.workspaceDir y ctx.getCron?.() para
inspección y actualizaciones de cron. Usa gateway_stop para limpiar recursos
de larga duración.
No dependas del hook interno gateway:startup para servicios en runtime propiedad del plugin.
cron_changed se dispara para eventos del ciclo de vida de cron propiedad del gateway con una
carga útil de evento tipada que cubre los motivos added, updated, removed, started, finished
y scheduled. El evento lleva una instantánea PluginHookGatewayCronJob
(incluidos state.nextRunAtMs, state.lastRunStatus y
state.lastError cuando está presente), además de un PluginHookGatewayCronDeliveryStatus
de not-requested | delivered | not-delivered | unknown. Los eventos eliminados
siguen llevando la instantánea del trabajo eliminado para que los programadores externos puedan
conciliar el estado. Usa ctx.getCron?.() y ctx.config desde el contexto del runtime
al sincronizar programadores de activación externos, y mantén OpenClaw como la
fuente de verdad para comprobaciones de vencimiento y ejecución.
Próximas deprecaciones
Algunas superficies adyacentes a hooks están obsoletas, pero aún son compatibles. Migra antes de la próxima versión mayor:- Envoltorios de canal en texto plano en handlers
inbound_claimymessage_received. LeeBodyForAgenty los bloques estructurados de contexto de usuario en lugar de analizar texto plano de envoltorio. Consulta Envoltorios de canal en texto plano → BodyForAgent. before_agent_startse mantiene por compatibilidad. Los plugins nuevos deben usarbefore_model_resolveybefore_prompt_builden lugar de la fase combinada.onResolutionenbefore_tool_callahora usa la unión tipadaPluginApprovalResolution(allow-once/allow-always/deny/timeout/cancelled) en lugar de unstringde formato libre.
command-auth → command-status - consulta
Migración del Plugin SDK → Deprecaciones activas.
Relacionado
- Migración del Plugin SDK - deprecaciones activas y cronograma de eliminación
- Construir plugins
- Resumen del Plugin SDK
- Puntos de entrada del Plugin
- Hooks internos
- Elementos internos de arquitectura de plugins