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 webhooks para 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.md cuando 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):

  1. Hooks del workspace: <workspace>/hooks/ (por agente, mayor precedencia)
  2. Hooks gestionados: ~/.openclaw/hooks/ (instalados por el usuario, compartidos entre workspaces)
  3. 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ón
  • requires: requisitos opcionales
    • bins: binarios requeridos en el PATH (por ejemplo, ["git", "node"])
    • anyBins: al menos uno de estos binarios debe estar presente
    • env: variables de entorno requeridas
    • config: 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 /new
  • command:reset: cuando se emite el comando /reset
  • command:stop: cuando se emite el comando /stop

Eventos de sesión

  • session:compact:before: justo antes de que la compactación resuma el historial
  • session: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 mutar context.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, transcript contiene 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 o undefined para 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/tokens
  • after_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ón
  • session:end: cuando termina una sesión
  • agent: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:

  1. Usa la entrada de sesión pre-reinicio para ubicar la transcripción correcta
  2. Extrae las últimas 15 líneas de conversación
  3. Usa el LLM para generar un slug descriptivo para el nombre de archivo
  4. 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.md
  • 2026-01-16-api-design.md
  • 2026-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.md y TOOLS.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:

  1. Captura detalles del evento (acción del comando, marca de tiempo, clave de sesión, ID del remitente, origen)
  2. Agrega al archivo de log en formato JSONL
  3. 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:

  1. Lee BOOT.md de tu workspace
  2. Ejecuta las instrucciones vía el ejecutor del agente
  3. 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 tipos
  • src/hooks/workspace.ts: escaneo y carga de directorios
  • src/hooks/frontmatter.ts: análisis de metadatos de HOOK.md
  • src/hooks/config.ts: verificación de elegibilidad
  • src/hooks/hooks-status.ts: informes de estado
  • src/hooks/loader.ts: cargador dinámico de módulos
  • src/cli/hooks-cli.ts: comandos CLI
  • src/gateway/server-startup.ts: carga hooks al arrancar el gateway
  • src/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

  1. Verifica la estructura del directorio:

    ls -la ~/.openclaw/hooks/my-hook/
    # Debería mostrar: HOOK.md, handler.ts
  2. Verifica el formato de HOOK.md:

    cat ~/.openclaw/hooks/my-hook/HOOK.md
    # Debería tener frontmatter YAML con name y metadata
  3. 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

  1. Verifica que el hook esté habilitado:

    openclaw hooks list
    # Debería mostrar ✓ junto a los hooks habilitados
  2. Reinicia tu proceso del gateway para que los hooks se recarguen.

  3. 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:

  1. Crear directorio del hook:

    mkdir -p ~/.openclaw/hooks/my-hook
    mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts
  2. Crear HOOK.md:

    ---
    name: my-hook
    description: "Mi hook personalizado"
    metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
    ---
    
    # My Hook
    
    Hace algo útil.
  3. Actualizar configuración:

    {
      "hooks": {
        "internal": {
          "enabled": true,
          "entries": {
            "my-hook": { "enabled": true }
          }
        }
      }
    }
  4. 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

Ver también