Webhooks
El Gateway puede exponer un pequeño endpoint HTTP de webhooks para disparadores externos.
Habilitar
{
hooks: {
enabled: true,
token: "shared-secret",
path: "/hooks",
// Opcional: restringir el enrutamiento explícito por `agentId` a esta lista.
// Omite o incluye "*" para permitir cualquier agente.
// Configura [] para denegar todo enrutamiento explícito por `agentId`.
allowedAgentIds: ["hooks", "main"],
},
}
Notas:
hooks.tokenes obligatorio cuandohooks.enabled=true.hooks.pathpor defecto es/hooks.
Autenticación
Cada solicitud debe incluir el token del hook. Se prefieren los headers:
Authorization: Bearer <token>(recomendado)x-openclaw-token: <token>- Los tokens en query-string se rechazan (
?token=...devuelve400).
Endpoints
POST /hooks/wake
Payload:
{ "text": "System line", "mode": "now" }
textrequerido (string): la descripción del evento (por ejemplo, “New email received”).modeopcional (now|next-heartbeat): si disparar un heartbeat inmediato (por defectonow) o esperar la próxima verificación periódica.
Efecto:
- Encola un evento del sistema para la sesión principal
- Si
mode=now, dispara un heartbeat inmediato
POST /hooks/agent
Payload:
{
"message": "Run this",
"name": "Email",
"agentId": "hooks",
"sessionKey": "hook:email:msg-123",
"wakeMode": "now",
"deliver": true,
"channel": "last",
"to": "+15551234567",
"model": "openai/gpt-5.2-mini",
"thinking": "low",
"timeoutSeconds": 120
}
messagerequerido (string): el prompt o mensaje que el agente debe procesar.nameopcional (string): nombre legible para el hook (por ejemplo, “GitHub”), usado como prefijo en los resúmenes de sesión.agentIdopcional (string): enruta este hook a un agente específico. Los IDs desconocidos recurren al agente predeterminado. Cuando se configura, el hook se ejecuta usando el workspace y la configuración del agente resuelto.sessionKeyopcional (string): la clave usada para identificar la sesión del agente. Por defecto este campo se rechaza a menos quehooks.allowRequestSessionKey=true.wakeModeopcional (now|next-heartbeat): si disparar un heartbeat inmediato (por defectonow) o esperar la próxima verificación periódica.deliveropcional (boolean): si estrue, la respuesta del agente se enviará al canal de mensajería. Por defectotrue. Las respuestas que son solo confirmaciones de heartbeat se omiten automáticamente.channelopcional (string): el canal de mensajería para la entrega. Uno de:last,whatsapp,telegram,discord,slack,mattermost(plugin),signal,imessage,msteams. Por defectolast.toopcional (string): el identificador del destinatario para el canal (por ejemplo, número de teléfono para WhatsApp/Signal, ID de chat para Telegram, ID de canal para Discord/Slack/Mattermost (plugin), ID de conversación para MS Teams). Por defecto usa el último destinatario en la sesión principal.modelopcional (string): sobreescritura de modelo (por ejemplo,anthropic/claude-3-5-sonneto un alias). Debe estar en la lista de modelos permitidos si está restringida.thinkingopcional (string): sobreescritura de nivel de razonamiento (por ejemplo,low,medium,high).timeoutSecondsopcional (number): duración máxima para la ejecución del agente en segundos.
Efecto:
- Ejecuta un turno aislado del agente (clave de sesión propia)
- Siempre publica un resumen en la sesión principal
- Si
wakeMode=now, dispara un heartbeat inmediato
Política de clave de sesión (cambio incompatible)
Las sobreescrituras de sessionKey en el payload de /hooks/agent están deshabilitadas por defecto.
- Recomendado: configura un
hooks.defaultSessionKeyfijo y mantén las sobreescrituras de solicitud desactivadas. - Opcional: permite sobreescrituras de solicitud solo cuando sea necesario, y restringe los prefijos.
Configuración recomendada:
{
hooks: {
enabled: true,
token: "${OPENCLAW_HOOKS_TOKEN}",
defaultSessionKey: "hook:ingress",
allowRequestSessionKey: false,
allowedSessionKeyPrefixes: ["hook:"],
},
}
Configuración de compatibilidad (comportamiento legacy):
{
hooks: {
enabled: true,
token: "${OPENCLAW_HOOKS_TOKEN}",
allowRequestSessionKey: true,
allowedSessionKeyPrefixes: ["hook:"], // altamente recomendado
},
}
POST /hooks/<name> (mapeado)
Los nombres de hook personalizados se resuelven vía hooks.mappings (consulta la configuración). Un mapeo puede
convertir payloads arbitrarios en acciones wake o agent, con templates o
transformaciones de código opcionales.
Opciones de mapeo (resumen):
hooks.presets: ["gmail"]habilita el mapeo integrado de Gmail.hooks.mappingspermite definirmatch,actiony templates en la configuración.hooks.transformsDir+transform.modulecarga un módulo JS/TS para lógica personalizada.hooks.transformsDir(si se configura) debe permanecer dentro de la raíz de transforms bajo tu directorio de configuración de OpenClaw (normalmente~/.openclaw/hooks/transforms).transform.moduledebe resolverse dentro del directorio efectivo de transforms (las rutas de escape/traversal se rechazan).
- Usa
match.sourcepara mantener un endpoint de ingesta genérico (enrutamiento por payload). - Las transformaciones TS requieren un loader de TS (por ejemplo,
bunotsx) o.jsprecompilado en tiempo de ejecución. - Configura
deliver: true+channel/toen los mapeos para enrutar respuestas a una superficie de chat (channelpor defecto eslasty recurre a WhatsApp). agentIdenruta el hook a un agente específico; los IDs desconocidos recurren al agente predeterminado.hooks.allowedAgentIdsrestringe el enrutamiento explícito poragentId. Omítelo (o incluye*) para permitir cualquier agente. Configura[]para denegar el enrutamiento explícito poragentId.hooks.defaultSessionKeyestablece la sesión predeterminada para ejecuciones del agente por hook cuando no se proporciona clave explícita.hooks.allowRequestSessionKeycontrola si los payloads de/hooks/agentpueden configurarsessionKey(por defecto:false).hooks.allowedSessionKeyPrefixesopcionalmente restringe los valores explícitos desessionKeyde los payloads de solicitud y mapeos.allowUnsafeExternalContent: truedeshabilita el envoltorio de seguridad de contenido externo para ese hook (peligroso; solo para fuentes internas confiables).openclaw webhooks gmail setupescribe la configuraciónhooks.gmailparaopenclaw webhooks gmail run. Consulta Gmail Pub/Sub para el flujo completo de Gmail watch.
Respuestas
200para/hooks/wake200para/hooks/agent(ejecución asíncrona aceptada)401en caso de fallo de autenticación429después de fallos de autenticación repetidos desde el mismo cliente (verificaRetry-After)400en payload inválido413en payloads sobredimensionados
Ejemplos
curl -X POST http://127.0.0.1:18789/hooks/wake \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"text":"New email received","mode":"now"}'
curl -X POST http://127.0.0.1:18789/hooks/agent \
-H 'x-openclaw-token: SECRET' \
-H 'Content-Type: application/json' \
-d '{"message":"Summarize inbox","name":"Email","wakeMode":"next-heartbeat"}'
Usar un modelo diferente
Agrega model al payload del agente (o mapeo) para sobreescribir el modelo de esa ejecución:
curl -X POST http://127.0.0.1:18789/hooks/agent \
-H 'x-openclaw-token: SECRET' \
-H 'Content-Type: application/json' \
-d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.2-mini"}'
Si aplicas agents.defaults.models, asegúrate de que el modelo sobreescrito esté incluido ahí.
curl -X POST http://127.0.0.1:18789/hooks/gmail \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"source":"gmail","messages":[{"from":"Ada","subject":"Hello","snippet":"Hi"}]}'
Seguridad
- Mantén los endpoints de hooks detrás de loopback, tailnet o un proxy inverso confiable.
- Usa un token de hook dedicado; no reutilices tokens de auth del gateway.
- Los fallos de autenticación repetidos se limitan por dirección del cliente para frenar intentos de fuerza bruta.
- Si usas enrutamiento multi-agente, configura
hooks.allowedAgentIdspara limitar la selección explícita deagentId. - Mantén
hooks.allowRequestSessionKey=falsea menos que necesites sesiones seleccionadas por el llamante. - Si habilitas
sessionKeyen la solicitud, restringehooks.allowedSessionKeyPrefixes(por ejemplo,["hook:"]). - Evita incluir payloads crudos sensibles en los logs de webhooks.
- Los payloads de hooks se tratan como no confiables y se envuelven con límites de seguridad por defecto.
Si necesitas deshabilitar esto para un hook específico, configura
allowUnsafeExternalContent: trueen el mapeo de ese hook (peligroso).