Hooks
Los hooks proporcionan un sistema extensible basado en eventos para automatizar acciones en respuesta a comandos y eventos del agente. Los hooks se descubren automáticamente desde directorios y se pueden gestionar mediante comandos CLI, de forma similar a cómo funcionan los skills en OpenClaw.
Orientación
Los hooks son pequeños scripts que se ejecutan cuando algo sucede. Hay dos tipos:
- Hooks (esta página): se ejecutan dentro del Gateway cuando se disparan eventos del agente, como
/new,/reset,/stop, o eventos del ciclo de vida. - Webhooks: webhooks HTTP externos que permiten a otros sistemas disparar trabajo en OpenClaw. Consulta Hooks de webhooks o usa
openclaw webhookspara los comandos helper de Gmail.
Los hooks también pueden empaquetarse dentro de plugins; consulta Plugins.
Usos comunes:
- Guardar una instantánea de memoria al reiniciar una sesión
- Mantener un registro de auditoría de comandos para solución de problemas o cumplimiento
- Disparar automatización de seguimiento cuando una sesión inicia o termina
- Escribir archivos en el workspace del agente o llamar APIs externas cuando se disparan eventos
Si puedes escribir una pequeña función TypeScript, puedes escribir un hook. Los hooks se descubren automáticamente y los habilitas o deshabilitas vía CLI.
Descripción general
El sistema de hooks te permite:
- Guardar el contexto de sesión en memoria cuando se emite
/new - Registrar todos los comandos para auditoría
- Disparar automatizaciones personalizadas en eventos del ciclo de vida del agente
- Extender el comportamiento de OpenClaw sin modificar el código fuente
Primeros pasos
Hooks incluidos
OpenClaw viene con cuatro hooks incluidos que se descubren automáticamente:
- session-memory: guarda el contexto de sesión en tu workspace del agente (por defecto
~/.openclaw/workspace/memory/) cuando emites/new - bootstrap-extra-files: inyecta archivos de bootstrap adicionales del workspace desde patrones glob/ruta configurados durante
agent:bootstrap - command-logger: registra todos los eventos de comando en
~/.openclaw/logs/commands.log - boot-md: ejecuta
BOOT.mdcuando el gateway arranca (requiere hooks internos habilitados)
Listar hooks disponibles:
openclaw hooks list
Habilitar un hook:
openclaw hooks enable session-memory
Verificar estado del hook:
openclaw hooks check
Obtener información detallada:
openclaw hooks info session-memory
Onboarding
Durante el onboarding (openclaw onboard), se te pedirá habilitar los hooks recomendados. El asistente descubre automáticamente los hooks elegibles y los presenta para selección.
Descubrimiento de hooks
Los hooks se descubren automáticamente desde tres directorios (en orden de precedencia):
- Hooks del workspace:
<workspace>/hooks/(por agente, mayor precedencia) - Hooks gestionados:
~/.openclaw/hooks/(instalados por el usuario, compartidos entre workspaces) - Hooks incluidos:
<openclaw>/dist/hooks/bundled/(distribuidos con OpenClaw)
Los directorios de hooks gestionados pueden ser un hook individual o un paquete de hooks (directorio de paquete).
Cada hook es un directorio que contiene:
my-hook/
├── HOOK.md # Metadatos + documentación
└── handler.ts # Implementación del manejador
Paquetes de hooks (npm/archivos)
Los paquetes de hooks son paquetes npm estándar que exportan uno o más hooks vía openclaw.hooks en
package.json. Instálalos con:
openclaw hooks install <path-or-spec>
Los specs de npm son solo de registro (nombre del paquete + versión exacta opcional o dist-tag). Los specs de Git/URL/archivo y rangos semver se rechazan.
Los specs simples y @latest permanecen en la pista estable. Si npm resuelve cualquiera de
ellos a un prerelease, OpenClaw se detiene y te pide que optes explícitamente con un
tag de prerelease como @beta/@rc o una versión exacta de prerelease.
Ejemplo de package.json:
{
"name": "@acme/my-hooks",
"version": "0.1.0",
"openclaw": {
"hooks": ["./hooks/my-hook", "./hooks/other-hook"]
}
}
Cada entrada apunta a un directorio de hook que contiene HOOK.md y handler.ts (o index.ts).
Los paquetes de hooks pueden incluir dependencias; se instalarán bajo ~/.openclaw/hooks/<id>.
Cada entrada de openclaw.hooks debe permanecer dentro del directorio del paquete después de
la resolución de symlinks; las entradas que escapan se rechazan.
Nota de seguridad: openclaw hooks install instala dependencias con npm install --ignore-scripts
(sin scripts de ciclo de vida). Mantén los árboles de dependencias de paquetes de hooks como “JS/TS puro” y evita paquetes que
dependan de builds en postinstall.
Estructura del hook
Formato de HOOK.md
El archivo HOOK.md contiene metadatos en frontmatter YAML más documentación en Markdown:
---
name: my-hook
description: "Breve descripción de lo que hace este hook"
homepage: https://docs.openclaw.ai/automation/hooks#my-hook
metadata:
{ "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
---
# My Hook
La documentación detallada va aquí...
## Qué hace
- Escucha comandos `/new`
- Realiza alguna acción
- Registra el resultado
## Requisitos
- Node.js debe estar instalado
## Configuración
No se necesita configuración.
Campos de metadatos
El objeto metadata.openclaw soporta:
emoji: emoji de visualización para el CLI (por ejemplo,"💾")events: array de eventos a escuchar (por ejemplo,["command:new", "command:reset"])export: export con nombre a usar (por defecto"default")homepage: URL de documentaciónrequires: requisitos opcionalesbins: binarios requeridos en el PATH (por ejemplo,["git", "node"])anyBins: al menos uno de estos binarios debe estar presenteenv: variables de entorno requeridasconfig: rutas de configuración requeridas (por ejemplo,["workspace.dir"])os: plataformas requeridas (por ejemplo,["darwin", "linux"])
always: saltar verificaciones de elegibilidad (boolean)install: métodos de instalación (para hooks incluidos:[{"id":"bundled","kind":"bundled"}])
Implementación del manejador
El archivo handler.ts exporta una función HookHandler:
const myHandler = async (event) => {
// Solo disparar en el comando 'new'
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log(`[my-hook] New command triggered`);
console.log(` Session: ${event.sessionKey}`);
console.log(` Timestamp: ${event.timestamp.toISOString()}`);
// Tu lógica personalizada aquí
// Opcionalmente enviar mensaje al usuario
event.messages.push("✨ My hook executed!");
};
export default myHandler;
Contexto del evento
Cada evento incluye:
{
type: 'command' | 'session' | 'agent' | 'gateway' | 'message',
action: string, // por ejemplo, 'new', 'reset', 'stop', 'received', 'sent'
sessionKey: string, // Identificador de sesión
timestamp: Date, // Cuándo ocurrió el evento
messages: string[], // Agrega mensajes aquí para enviar al usuario
context: {
// Eventos de comando:
sessionEntry?: SessionEntry,
sessionId?: string,
sessionFile?: string,
commandSource?: string, // por ejemplo, 'whatsapp', 'telegram'
senderId?: string,
workspaceDir?: string,
bootstrapFiles?: WorkspaceBootstrapFile[],
cfg?: OpenClawConfig,
// Eventos de mensaje (consulta la sección de Eventos de mensaje para detalles completos):
from?: string, // message:received
to?: string, // message:sent
content?: string,
channelId?: string,
success?: boolean, // message:sent
}
}
Tipos de eventos
Eventos de comando
Se disparan cuando se emiten comandos del agente:
command: todos los eventos de comando (listener general)command:new: cuando se emite el comando/newcommand:reset: cuando se emite el comando/resetcommand:stop: cuando se emite el comando/stop
Eventos de sesión
session:compact:before: justo antes de que la compactación resuma el historialsession:compact:after: después de que la compactación se complete con metadatos de resumen
Los payloads internos de hooks emiten estos como type: "session" con action: "compact:before" / action: "compact:after"; los listeners se suscriben con las claves combinadas de arriba.
El registro específico de manejadores usa el formato literal de clave ${type}:${action}. Para estos eventos, registra session:compact:before y session:compact:after.
Eventos del agente
agent:bootstrap: antes de que se inyecten los archivos de bootstrap del workspace (los hooks pueden mutarcontext.bootstrapFiles)
Eventos del gateway
Se disparan cuando el gateway arranca:
gateway:startup: después de que los canales arranquen y los hooks se carguen
Eventos de mensaje
Se disparan cuando se reciben o envían mensajes:
message: todos los eventos de mensaje (listener general)message:received: cuando se recibe un mensaje entrante de cualquier canal. Se dispara temprano en el procesamiento antes de la comprensión de medios. El contenido puede contener placeholders crudos como<media:audio>para adjuntos de medios que aún no se han procesado.message:transcribed: cuando un mensaje ha sido completamente procesado, incluyendo transcripción de audio y comprensión de enlaces. En este punto,transcriptcontiene el texto completo de la transcripción para mensajes de audio. Usa este hook cuando necesites acceso al contenido de audio transcrito.message:preprocessed: se dispara para cada mensaje después de que toda la comprensión de medios + enlaces se completa, dando a los hooks acceso al cuerpo completamente enriquecido (transcripciones, descripciones de imágenes, resúmenes de enlaces) antes de que el agente lo vea.message:sent: cuando un mensaje de salida se envía exitosamente
Contexto de eventos de mensaje
Los eventos de mensaje incluyen contexto detallado sobre el mensaje:
// contexto de message:received
{
from: string, // Identificador del remitente (número de teléfono, ID de usuario, etc.)
content: string, // Contenido del mensaje
timestamp?: number, // Marca de tiempo Unix cuando se recibió
channelId: string, // Canal (por ejemplo, "whatsapp", "telegram", "discord")
accountId?: string, // ID de cuenta del proveedor para configuraciones multi-cuenta
conversationId?: string, // ID de chat/conversación
messageId?: string, // ID del mensaje del proveedor
metadata?: { // Datos adicionales específicos del proveedor
to?: string,
provider?: string,
surface?: string,
threadId?: string,
senderId?: string,
senderName?: string,
senderUsername?: string,
senderE164?: string,
}
}
// contexto de message:sent
{
to: string, // Identificador del destinatario
content: string, // Contenido del mensaje enviado
success: boolean, // Si el envío fue exitoso
error?: string, // Mensaje de error si el envío falló
channelId: string, // Canal (por ejemplo, "whatsapp", "telegram", "discord")
accountId?: string, // ID de cuenta del proveedor
conversationId?: string, // ID de chat/conversación
messageId?: string, // ID del mensaje devuelto por el proveedor
isGroup?: boolean, // Si este mensaje de salida pertenece a un contexto de grupo/canal
groupId?: string, // Identificador de grupo/canal para correlación con message:received
}
// contexto de message:transcribed
{
body?: string, // Cuerpo crudo entrante antes de enriquecimiento
bodyForAgent?: string, // Cuerpo enriquecido visible para el agente
transcript: string, // Texto de la transcripción de audio
channelId: string, // Canal (por ejemplo, "telegram", "whatsapp")
conversationId?: string,
messageId?: string,
}
// contexto de message:preprocessed
{
body?: string, // Cuerpo crudo entrante
bodyForAgent?: string, // Cuerpo final enriquecido después de la comprensión de medios/enlaces
transcript?: string, // Transcripción cuando hubo audio presente
channelId: string, // Canal (por ejemplo, "telegram", "whatsapp")
conversationId?: string,
messageId?: string,
isGroup?: boolean,
groupId?: string,
}
Ejemplo: hook de registro de mensajes
const isMessageReceivedEvent = (event: { type: string; action: string }) =>
event.type === "message" && event.action === "received";
const isMessageSentEvent = (event: { type: string; action: string }) =>
event.type === "message" && event.action === "sent";
const handler = async (event) => {
if (isMessageReceivedEvent(event as { type: string; action: string })) {
console.log(`[message-logger] Received from ${event.context.from}: ${event.context.content}`);
} else if (isMessageSentEvent(event as { type: string; action: string })) {
console.log(`[message-logger] Sent to ${event.context.to}: ${event.context.content}`);
}
};
export default handler;
Hooks de resultados de herramientas (API de plugins)
Estos hooks no son listeners del flujo de eventos; permiten a los plugins ajustar sincrónicamente los resultados de herramientas antes de que OpenClaw los persista.
tool_result_persist: transforma resultados de herramientas antes de que se escriban en la transcripción de sesión. Debe ser síncrono; devuelve el payload actualizado del resultado de la herramienta oundefinedpara mantenerlo como está. Consulta Bucle del agente.
Eventos de hooks de plugins
Hooks del ciclo de vida de compactación expuestos a través del ejecutor de hooks de plugins:
before_compaction: se ejecuta antes de la compactación con metadatos de conteo/tokensafter_compaction: se ejecuta después de la compactación con metadatos de resumen de compactación
Eventos futuros
Tipos de eventos planificados:
session:start: cuando comienza una nueva sesiónsession:end: cuando termina una sesiónagent:error: cuando un agente encuentra un error
Crear hooks personalizados
1. Elegir ubicación
- Hooks del workspace (
<workspace>/hooks/): por agente, mayor precedencia - Hooks gestionados (
~/.openclaw/hooks/): compartidos entre workspaces
2. Crear estructura de directorios
mkdir -p ~/.openclaw/hooks/my-hook
cd ~/.openclaw/hooks/my-hook
3. Crear HOOK.md
---
name: my-hook
description: "Hace algo útil"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Custom Hook
Este hook hace algo útil cuando emites `/new`.
4. Crear handler.ts
const handler = async (event) => {
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log("[my-hook] Running!");
// Tu lógica aquí
};
export default handler;
5. Habilitar y probar
# Verificar que el hook se descubrió
openclaw hooks list
# Habilitarlo
openclaw hooks enable my-hook
# Reiniciar tu proceso del gateway (reiniciar la app de barra de menú en macOS, o reiniciar tu proceso de desarrollo)
# Disparar el evento
# Envía /new vía tu canal de mensajería
Configuración
Nuevo formato de configuración (recomendado)
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"session-memory": { "enabled": true },
"command-logger": { "enabled": false }
}
}
}
}
Configuración por hook
Los hooks pueden tener configuración personalizada:
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": {
"enabled": true,
"env": {
"MY_CUSTOM_VAR": "value"
}
}
}
}
}
}
Directorios adicionales
Cargar hooks desde directorios adicionales:
{
"hooks": {
"internal": {
"enabled": true,
"load": {
"extraDirs": ["/path/to/more/hooks"]
}
}
}
}
Formato de configuración legacy (aún soportado)
El formato de configuración antiguo sigue funcionando por compatibilidad:
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts",
"export": "default"
}
]
}
}
}
Nota: module debe ser una ruta relativa al workspace. Las rutas absolutas y el traversal fuera del workspace se rechazan.
Migración: usa el nuevo sistema basado en descubrimiento para hooks nuevos. Los manejadores legacy se cargan después de los hooks basados en directorio.
Comandos CLI
Listar hooks
# Listar todos los hooks
openclaw hooks list
# Mostrar solo hooks elegibles
openclaw hooks list --eligible
# Salida detallada (muestra requisitos faltantes)
openclaw hooks list --verbose
# Salida JSON
openclaw hooks list --json
Información del hook
# Mostrar información detallada de un hook
openclaw hooks info session-memory
# Salida JSON
openclaw hooks info session-memory --json
Verificar elegibilidad
# Mostrar resumen de elegibilidad
openclaw hooks check
# Salida JSON
openclaw hooks check --json
Habilitar/Deshabilitar
# Habilitar un hook
openclaw hooks enable session-memory
# Deshabilitar un hook
openclaw hooks disable command-logger
Referencia de hooks incluidos
session-memory
Guarda el contexto de sesión en memoria cuando emites /new.
Eventos: command:new
Requisitos: workspace.dir debe estar configurado
Salida: <workspace>/memory/YYYY-MM-DD-slug.md (por defecto ~/.openclaw/workspace)
Qué hace:
- Usa la entrada de sesión pre-reinicio para ubicar la transcripción correcta
- Extrae las últimas 15 líneas de conversación
- Usa el LLM para generar un slug descriptivo para el nombre de archivo
- Guarda los metadatos de sesión en un archivo de memoria con fecha
Ejemplo de salida:
# Session: 2026-01-16 14:30:00 UTC
- **Session Key**: agent:main:main
- **Session ID**: abc123def456
- **Source**: telegram
Ejemplos de nombres de archivo:
2026-01-16-vendor-pitch.md2026-01-16-api-design.md2026-01-16-1430.md(marca de tiempo de respaldo si la generación del slug falla)
Habilitar:
openclaw hooks enable session-memory
bootstrap-extra-files
Inyecta archivos de bootstrap adicionales (por ejemplo, AGENTS.md / TOOLS.md locales al monorepo) durante agent:bootstrap.
Eventos: agent:bootstrap
Requisitos: workspace.dir debe estar configurado
Salida: no se escriben archivos; el contexto de bootstrap se modifica solo en memoria.
Configuración:
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"bootstrap-extra-files": {
"enabled": true,
"paths": ["packages/*/AGENTS.md", "packages/*/TOOLS.md"]
}
}
}
}
}
Notas:
- Las rutas se resuelven relativas al workspace.
- Los archivos deben permanecer dentro del workspace (verificación por realpath).
- Solo se cargan los nombres base de bootstrap reconocidos.
- La allowlist de subagentes se preserva (solo
AGENTS.mdyTOOLS.md).
Habilitar:
openclaw hooks enable bootstrap-extra-files
command-logger
Registra todos los eventos de comando en un archivo de auditoría centralizado.
Eventos: command
Requisitos: ninguno
Salida: ~/.openclaw/logs/commands.log
Qué hace:
- Captura detalles del evento (acción del comando, marca de tiempo, clave de sesión, ID del remitente, origen)
- Agrega al archivo de log en formato JSONL
- Se ejecuta silenciosamente en segundo plano
Ejemplo de entradas de log:
{"timestamp":"2026-01-16T14:30:00.000Z","action":"new","sessionKey":"agent:main:main","senderId":"+1234567890","source":"telegram"}
{"timestamp":"2026-01-16T15:45:22.000Z","action":"stop","sessionKey":"agent:main:main","senderId":"[email protected]","source":"whatsapp"}
Ver logs:
# Ver comandos recientes
tail -n 20 ~/.openclaw/logs/commands.log
# Formatear con jq
cat ~/.openclaw/logs/commands.log | jq .
# Filtrar por acción
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
Habilitar:
openclaw hooks enable command-logger
boot-md
Ejecuta BOOT.md cuando el gateway arranca (después de que los canales arranquen).
Los hooks internos deben estar habilitados para que esto se ejecute.
Eventos: gateway:startup
Requisitos: workspace.dir debe estar configurado
Qué hace:
- Lee
BOOT.mdde tu workspace - Ejecuta las instrucciones vía el ejecutor del agente
- Envía cualquier mensaje de salida solicitado vía la herramienta de mensajes
Habilitar:
openclaw hooks enable boot-md
Buenas prácticas
Mantener los manejadores rápidos
Los hooks se ejecutan durante el procesamiento de comandos. Mantenlos ligeros:
// ✓ Bien - trabajo asíncrono, retorna inmediatamente
const handler: HookHandler = async (event) => {
void processInBackground(event); // Disparar y olvidar
};
// ✗ Mal - bloquea el procesamiento del comando
const handler: HookHandler = async (event) => {
await slowDatabaseQuery(event);
await evenSlowerAPICall(event);
};
Manejar errores con elegancia
Siempre envuelve operaciones riesgosas:
const handler: HookHandler = async (event) => {
try {
await riskyOperation(event);
} catch (err) {
console.error("[my-handler] Failed:", err instanceof Error ? err.message : String(err));
// No lances - deja que otros manejadores se ejecuten
}
};
Filtrar eventos temprano
Retorna pronto si el evento no es relevante:
const handler: HookHandler = async (event) => {
// Solo manejar comandos 'new'
if (event.type !== "command" || event.action !== "new") {
return;
}
// Tu lógica aquí
};
Usar claves de evento específicas
Especifica eventos exactos en los metadatos cuando sea posible:
metadata: { "openclaw": { "events": ["command:new"] } } # Específico
En lugar de:
metadata: { "openclaw": { "events": ["command"] } } # General - más overhead
Depuración
Habilitar logging de hooks
El gateway registra la carga de hooks al arrancar:
Registered hook: session-memory -> command:new
Registered hook: bootstrap-extra-files -> agent:bootstrap
Registered hook: command-logger -> command
Registered hook: boot-md -> gateway:startup
Verificar descubrimiento
Listar todos los hooks descubiertos:
openclaw hooks list --verbose
Verificar registro
En tu manejador, registra cuando es llamado:
const handler: HookHandler = async (event) => {
console.log("[my-handler] Triggered:", event.type, event.action);
// Tu lógica
};
Verificar elegibilidad
Verifica por qué un hook no es elegible:
openclaw hooks info my-hook
Busca requisitos faltantes en la salida.
Pruebas
Logs del gateway
Monitorea los logs del gateway para ver la ejecución de hooks:
# macOS
./scripts/clawlog.sh -f
# Otras plataformas
tail -f ~/.openclaw/gateway.log
Probar hooks directamente
Prueba tus manejadores de forma aislada:
import { test } from "vitest";
import myHandler from "./hooks/my-hook/handler.js";
test("my handler works", async () => {
const event = {
type: "command",
action: "new",
sessionKey: "test-session",
timestamp: new Date(),
messages: [],
context: { foo: "bar" },
};
await myHandler(event);
// Verificar efectos secundarios
});
Arquitectura
Componentes principales
src/hooks/types.ts: definiciones de tipossrc/hooks/workspace.ts: escaneo y carga de directoriossrc/hooks/frontmatter.ts: análisis de metadatos de HOOK.mdsrc/hooks/config.ts: verificación de elegibilidadsrc/hooks/hooks-status.ts: informes de estadosrc/hooks/loader.ts: cargador dinámico de módulossrc/cli/hooks-cli.ts: comandos CLIsrc/gateway/server-startup.ts: carga hooks al arrancar el gatewaysrc/auto-reply/reply/commands-core.ts: dispara eventos de comando
Flujo de descubrimiento
Arranque del gateway
↓
Escanear directorios (workspace → gestionados → incluidos)
↓
Analizar archivos HOOK.md
↓
Verificar elegibilidad (bins, env, config, os)
↓
Cargar manejadores de hooks elegibles
↓
Registrar manejadores para eventos
Flujo de eventos
El usuario envía /new
↓
Validación del comando
↓
Crear evento de hook
↓
Disparar hook (todos los manejadores registrados)
↓
El procesamiento del comando continúa
↓
Reinicio de sesión
Solución de problemas
Hook no descubierto
-
Verifica la estructura del directorio:
ls -la ~/.openclaw/hooks/my-hook/ # Debería mostrar: HOOK.md, handler.ts -
Verifica el formato de HOOK.md:
cat ~/.openclaw/hooks/my-hook/HOOK.md # Debería tener frontmatter YAML con name y metadata -
Lista todos los hooks descubiertos:
openclaw hooks list
Hook no elegible
Verifica los requisitos:
openclaw hooks info my-hook
Busca lo que falta:
- Binarios (verifica el PATH)
- Variables de entorno
- Valores de configuración
- Compatibilidad de SO
Hook no se ejecuta
-
Verifica que el hook esté habilitado:
openclaw hooks list # Debería mostrar ✓ junto a los hooks habilitados -
Reinicia tu proceso del gateway para que los hooks se recarguen.
-
Verifica los logs del gateway en busca de errores:
./scripts/clawlog.sh | grep hook
Errores del manejador
Verifica errores de TypeScript/import:
# Probar import directamente
node -e "import('./path/to/handler.ts').then(console.log)"
Guía de migración
De configuración legacy a descubrimiento
Antes:
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts"
}
]
}
}
}
Después:
-
Crear directorio del hook:
mkdir -p ~/.openclaw/hooks/my-hook mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts -
Crear HOOK.md:
--- name: my-hook description: "Mi hook personalizado" metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } } --- # My Hook Hace algo útil. -
Actualizar configuración:
{ "hooks": { "internal": { "enabled": true, "entries": { "my-hook": { "enabled": true } } } } } -
Verificar y reiniciar tu proceso del gateway:
openclaw hooks list # Debería mostrar: 🎯 my-hook ✓
Beneficios de la migración:
- Descubrimiento automático
- Gestión por CLI
- Verificación de elegibilidad
- Mejor documentación
- Estructura consistente