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 de la CLI, de forma similar a cómo funcionan las skills en OpenClaw.
Orientación inicial¶
Los hooks son pequeños scripts que se ejecutan cuando ocurre algo. Hay dos tipos:
- Hooks (esta página): se ejecutan dentro del Gateway cuando se disparan eventos del agente, como
/new,/reset,/stopo eventos del ciclo de vida. - Webhooks: webhooks HTTP externos que permiten que otros sistemas activen trabajo en OpenClaw. Consulte Webhook Hooks o use
openclaw webhookspara comandos auxiliares de Gmail.
Los hooks también se pueden incluir dentro de plugins; consulte Plugins.
Usos comunes:
- Guardar una instantánea de memoria cuando se restablece una sesión
- Mantener un rastro de auditoría de comandos para solución de problemas o cumplimiento
- Activar automatizaciones de seguimiento cuando una sesión comienza o termina
- Escribir archivos en el espacio de trabajo del agente o llamar a API externas cuando se disparan eventos
Si puede escribir una pequeña función en TypeScript, puede escribir un hook. Los hooks se descubren automáticamente, y usted los habilita o deshabilita mediante la CLI.
Descripción general¶
El sistema de hooks le permite:
- Guardar el contexto de la sesión en memoria cuando se emite
/new - Registrar todos los comandos para auditoría
- Activar automatizaciones personalizadas en eventos del ciclo de vida del agente
- Extender el comportamiento de OpenClaw sin modificar el código principal
Comenzando¶
Hooks incluidos¶
OpenClaw incluye cuatro hooks integrados que se descubren automáticamente:
- 💾 session-memory: Guarda el contexto de la sesión en el espacio de trabajo de su agente (predeterminado
~/.openclaw/workspace/memory/) cuando emite/new - 📝 command-logger: Registra todos los eventos de comandos en
~/.openclaw/logs/commands.log - 🚀 boot-md: Ejecuta
BOOT.mdcuando se inicia el Gateway (requiere hooks internos habilitados) - 😈 soul-evil: Intercambia contenido inyectado de
SOUL.mdconSOUL_EVIL.mddurante una ventana de purga o por probabilidad aleatoria
Listar hooks disponibles:
openclaw hooks list
Habilitar un hook:
openclaw hooks enable session-memory
Comprobar el estado de un hook:
openclaw hooks check
Obtener información detallada:
openclaw hooks info session-memory
Embarque¶
Durante la incorporación (openclaw onboard), se le pedirá que habilite hooks recomendados. El asistente descubre automáticamente los hooks elegibles y los presenta para su selección.
Descubrimiento de hooks¶
Los hooks se descubren automáticamente desde tres directorios (en orden de precedencia):
- Hooks del espacio de trabajo:
<workspace>/hooks/(por agente, mayor precedencia) - Hooks gestionados:
~/.openclaw/hooks/(instalados por el usuario, compartidos entre espacios de trabajo) - Hooks incluidos:
<openclaw>/dist/hooks/bundled/(incluidos con OpenClaw)
Los directorios de hooks gestionados pueden ser un hook único o un paquete de hooks (directorio de paquete).
Cada hook es un directorio que contiene:
my-hook/
├── HOOK.md # Metadata + documentation
└── handler.ts # Handler implementation
Paquetes de hooks (npm/archivos)¶
Los paquetes de hooks son paquetes npm estándar que exportan uno o más hooks mediante openclaw.hooks en
package.json. Instálelos con:
openclaw hooks install <path-or-spec>
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 en ~/.openclaw/hooks/<id>.
Estructura de un hook¶
Formato de HOOK.md¶
El archivo HOOK.md contiene metadatos en frontmatter YAML más documentación en Markdown:
---
name: my-hook
description: "Short description of what this hook does"
homepage: https://docs.openclaw.ai/hooks#my-hook
metadata:
{ "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
---
# My Hook
Detailed documentation goes here...
## What It Does
- Listens for `/new` commands
- Performs some action
- Logs the result
## Requirements
- Node.js must be installed
## Configuration
No configuration needed.
Campos de metadatos¶
El objeto metadata.openclaw admite:
emoji: Emoji de visualización para la CLI (p. ej.,"💾")events: Arreglo de eventos a escuchar (p. ej.,["command:new", "command:reset"])export: Exportación con nombre a usar (predeterminado"default")homepage: URL de documentaciónrequires: Requisitos opcionalesbins: Binarios requeridos en PATH (p. ej.,["git", "node"])anyBins: Al menos uno de estos binarios debe estar presenteenv: Variables de entorno requeridasconfig: Rutas de configuración requeridas (p. ej.,["workspace.dir"])os: Plataformas requeridas (p. ej.,["darwin", "linux"])always: Omitir comprobaciones de elegibilidad (booleano)install: Métodos de instalación (para hooks incluidos:[{"id":"bundled","kind":"bundled"}])
Implementación del handler¶
El archivo handler.ts exporta una función HookHandler:
import type { HookHandler } from "../../src/hooks/hooks.js";
const myHandler: HookHandler = async (event) => {
// Only trigger on 'new' command
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()}`);
// Your custom logic here
// Optionally send message to user
event.messages.push("✨ My hook executed!");
};
export default myHandler;
Contexto del evento¶
Cada evento incluye:
{
type: 'command' | 'session' | 'agent' | 'gateway',
action: string, // e.g., 'new', 'reset', 'stop'
sessionKey: string, // Session identifier
timestamp: Date, // When the event occurred
messages: string[], // Push messages here to send to user
context: {
sessionEntry?: SessionEntry,
sessionId?: string,
sessionFile?: string,
commandSource?: string, // e.g., 'whatsapp', 'telegram'
senderId?: string,
workspaceDir?: string,
bootstrapFiles?: WorkspaceBootstrapFile[],
cfg?: OpenClawConfig
}
}
Tipos de eventos¶
Eventos de comandos¶
Se activan cuando se emiten comandos del agente:
command: Todos los eventos de comandos (escucha general)command:new: Cuando se emite el comando/newcommand:reset: Cuando se emite el comando/resetcommand:stop: Cuando se emite el comando/stop
Eventos del agente¶
agent:bootstrap: Antes de que se inyecten los archivos de arranque del espacio de trabajo (los hooks pueden mutarcontext.bootstrapFiles)
Eventos del Gateway¶
Se activan cuando se inicia el Gateway:
gateway:startup: Después de que los canales se inician y los hooks se cargan
Hooks de resultados de herramientas (API de plugins)¶
Estos hooks no son escuchas de flujos de eventos; permiten que los plugins ajusten de forma síncrona los resultados de las herramientas antes de que OpenClaw los persista.
tool_result_persist: Transformar resultados de herramientas antes de que se escriban en la transcripción de la sesión. Debe ser síncrono; devuelva la carga útil actualizada del resultado de la herramienta oundefinedpara mantenerla sin cambios. Consulte Agent Loop.
Eventos futuros¶
Tipos de eventos planificados:
session:start: Cuando comienza una nueva sesiónsession:end: Cuando finaliza una sesiónagent:error: Cuando un agente encuentra un errormessage:sent: Cuando se envía un mensajemessage:received: Cuando se recibe un mensaje
Creación de hooks personalizados¶
1. Elegir ubicación¶
- Hooks del espacio de trabajo (
<workspace>/hooks/): Por agente, mayor precedencia - Hooks gestionados (
~/.openclaw/hooks/): Compartidos entre espacios de trabajo
2. Crear la estructura de directorios¶
mkdir -p ~/.openclaw/hooks/my-hook
cd ~/.openclaw/hooks/my-hook
3. Crear HOOK.md¶
---
name: my-hook
description: "Does something useful"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Custom Hook
This hook does something useful when you issue `/new`.
4. Crear handler.ts¶
import type { HookHandler } from "../../src/hooks/hooks.js";
const handler: HookHandler = async (event) => {
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log("[my-hook] Running!");
// Your logic here
};
export default handler;
5. Habilitar y probar¶
# Verify hook is discovered
openclaw hooks list
# Enable it
openclaw hooks enable my-hook
# Restart your gateway process (menu bar app restart on macOS, or restart your dev process)
# Trigger the event
# Send /new via your messaging channel
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 heredado (aún compatible)¶
El formato de configuración antiguo sigue funcionando por compatibilidad hacia atrás:
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts",
"export": "default"
}
]
}
}
}
Migración: Use el nuevo sistema basado en descubrimiento para hooks nuevos. Los handlers heredados se cargan después de los hooks basados en directorios.
Comandos de la CLI¶
Listar hooks¶
# List all hooks
openclaw hooks list
# Show only eligible hooks
openclaw hooks list --eligible
# Verbose output (show missing requirements)
openclaw hooks list --verbose
# JSON output
openclaw hooks list --json
Información del hook¶
# Show detailed info about a hook
openclaw hooks info session-memory
# JSON output
openclaw hooks info session-memory --json
Comprobar elegibilidad¶
# Show eligibility summary
openclaw hooks check
# JSON output
openclaw hooks check --json
Habilitar/deshabilitar¶
# Enable a hook
openclaw hooks enable session-memory
# Disable a hook
openclaw hooks disable command-logger
Referencia de hooks incluidos¶
session-memory¶
Guarda el contexto de la sesión en memoria cuando emite /new.
Eventos: command:new
Requisitos: workspace.dir debe estar configurado
Salida: <workspace>/memory/YYYY-MM-DD-slug.md (predeterminado ~/.openclaw/workspace)
Qué hace:
- Usa la entrada de la sesión previa al restablecimiento para localizar la transcripción correcta
- Extrae las últimas 15 líneas de la conversación
- Usa un LLM para generar un slug descriptivo de nombre de archivo
- Guarda los metadatos de la sesión en un archivo de memoria con fecha
Salida de ejemplo:
# 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 falla la generación del slug)
Habilitar:
openclaw hooks enable session-memory
command-logger¶
Registra todos los eventos de comandos en un archivo centralizado de auditoría.
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 registro en formato JSONL
- Se ejecuta silenciosamente en segundo plano
Entradas de registro de ejemplo:
{"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":"user@example.com","source":"whatsapp"}
Ver registros:
# View recent commands
tail -n 20 ~/.openclaw/logs/commands.log
# Pretty-print with jq
cat ~/.openclaw/logs/commands.log | jq .
# Filter by action
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
Habilitar:
openclaw hooks enable command-logger
soul-evil¶
Intercambia contenido inyectado de SOUL.md con SOUL_EVIL.md durante una ventana de purga o por probabilidad aleatoria.
Eventos: agent:bootstrap
Docs: SOUL Evil Hook
Salida: No se escriben archivos; los intercambios ocurren solo en memoria.
Habilitar:
openclaw hooks enable soul-evil
Configuración:
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"soul-evil": {
"enabled": true,
"file": "SOUL_EVIL.md",
"chance": 0.1,
"purge": { "at": "21:00", "duration": "15m" }
}
}
}
}
}
boot-md¶
Ejecuta BOOT.md cuando se inicia el Gateway (después de que los canales se inician).
Los hooks internos deben estar habilitados para que esto se ejecute.
Eventos: gateway:startup
Requisitos: workspace.dir debe estar configurado
Qué hace:
- Lee
BOOT.mddesde su espacio de trabajo - Ejecuta las instrucciones mediante el ejecutor del agente
- Envía cualquier mensaje saliente solicitado mediante la herramienta de mensajes
Habilitar:
openclaw hooks enable boot-md
Mejores prácticas¶
Mantenga los handlers rápidos¶
Los hooks se ejecutan durante el procesamiento de comandos. Manténgalos livianos:
// ✓ Good - async work, returns immediately
const handler: HookHandler = async (event) => {
void processInBackground(event); // Fire and forget
};
// ✗ Bad - blocks command processing
const handler: HookHandler = async (event) => {
await slowDatabaseQuery(event);
await evenSlowerAPICall(event);
};
Maneje los errores con elegancia¶
Siempre envuelva las 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));
// Don't throw - let other handlers run
}
};
Filtre eventos temprano¶
Regrese temprano si el evento no es relevante:
const handler: HookHandler = async (event) => {
// Only handle 'new' commands
if (event.type !== "command" || event.action !== "new") {
return;
}
// Your logic here
};
Use claves de eventos específicas¶
Especifique eventos exactos en los metadatos cuando sea posible:
metadata: { "openclaw": { "events": ["command:new"] } } # Specific
En lugar de:
metadata: { "openclaw": { "events": ["command"] } } # General - more overhead
Depuración¶
Habilitar registro de hooks¶
El Gateway registra la carga de hooks al inicio:
Registered hook: session-memory -> command:new
Registered hook: command-logger -> command
Registered hook: boot-md -> gateway:startup
Comprobar descubrimiento¶
Liste todos los hooks descubiertos:
openclaw hooks list --verbose
Comprobar registro¶
En su handler, registre cuando se llame:
const handler: HookHandler = async (event) => {
console.log("[my-handler] Triggered:", event.type, event.action);
// Your logic
};
Verificar elegibilidad¶
Compruebe por qué un hook no es elegible:
openclaw hooks info my-hook
Busque requisitos faltantes en la salida.
Pruebas¶
Registros del Gateway¶
Monitoree los registros del Gateway para ver la ejecución de hooks:
# macOS
./scripts/clawlog.sh -f
# Other platforms
tail -f ~/.openclaw/gateway.log
Prueba Hooks Directamente¶
Pruebe sus handlers de forma aislada:
import { test } from "vitest";
import { createHookEvent } from "./src/hooks/hooks.js";
import myHandler from "./hooks/my-hook/handler.js";
test("my handler works", async () => {
const event = createHookEvent("command", "new", "test-session", {
foo: "bar",
});
await myHandler(event);
// Assert side effects
});
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: Comprobación de elegibilidadsrc/hooks/hooks-status.ts: Reporte de estadosrc/hooks/loader.ts: Cargador dinámico de módulossrc/cli/hooks-cli.ts: Comandos de la CLIsrc/gateway/server-startup.ts: Carga hooks al iniciar el Gatewaysrc/auto-reply/reply/commands-core.ts: Dispara eventos de comandos
Flujo de descubrimiento¶
Gateway startup
↓
Scan directories (workspace → managed → bundled)
↓
Parse HOOK.md files
↓
Check eligibility (bins, env, config, os)
↓
Load handlers from eligible hooks
↓
Register handlers for events
Flujo de eventos¶
User sends /new
↓
Command validation
↓
Create hook event
↓
Trigger hook (all registered handlers)
↓
Command processing continues
↓
Session reset
Solución de problemas¶
Hook no descubierto¶
- Verifique la estructura de directorios:
bash
ls -la ~/.openclaw/hooks/my-hook/
# Should show: HOOK.md, handler.ts
- Verifique el formato de HOOK.md:
bash
cat ~/.openclaw/hooks/my-hook/HOOK.md
# Should have YAML frontmatter with name and metadata
- Liste todos los hooks descubiertos:
bash
openclaw hooks list
Hook no elegible¶
Compruebe los requisitos:
openclaw hooks info my-hook
Busque faltantes:
- Binarios (verifique PATH)
- Variables de entorno
- Valores de configuración
- Compatibilidad del SO
Hook no se ejecuta¶
- Verifique que el hook esté habilitado:
bash
openclaw hooks list
# Should show ✓ next to enabled hooks
-
Reinicie su proceso del Gateway para que los hooks se recarguen.
-
Revise los registros del Gateway en busca de errores:
bash
./scripts/clawlog.sh | grep hook
Errores del handler¶
Revise errores de TypeScript/importación:
# Test import directly
node -e "import('./path/to/handler.ts').then(console.log)"
Guía de migración¶
De configuración heredada a descubrimiento¶
Antes:
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts"
}
]
}
}
}
Después:
- Cree el directorio del hook:
bash
mkdir -p ~/.openclaw/hooks/my-hook
mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts
- Cree HOOK.md:
```markdown
name: my-hook description: "My custom hook" metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
# My Hook
Does something useful. ```
- Actualice la configuración:
json
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": { "enabled": true }
}
}
}
}
- Verifique y reinicie su proceso del Gateway:
bash
openclaw hooks list
# Should show: 🎯 my-hook ✓
Beneficios de la migración:
- Descubrimiento automático
- Gestión mediante CLI
- Comprobación de elegibilidad
- Mejor documentación
- Estructura consistente