mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 07:17:26 +00:00
feat(hooks): add agentId support to webhook mappings (#13672)
* feat(hooks): add agentId support to webhook mappings
Allow webhook mappings to route hook runs to a specific agent via
the new `agentId` field. This enables lightweight agents with minimal
bootstrap files to handle webhooks, reducing token cost per hook run.
The agentId is threaded through:
- HookMappingConfig (config type + zod schema)
- HookMappingResolved + HookAction (mapping types)
- normalizeHookMapping + buildActionFromMapping (mapping logic)
- mergeAction (transform override support)
- HookAgentPayload + normalizeAgentPayload (direct /hooks/agent endpoint)
- dispatchAgentHook → CronJob.agentId (server dispatch)
The existing runCronIsolatedAgentTurn already supports agentId on
CronJob — this change simply wires it through from webhook mappings.
Usage in config:
hooks.mappings[].agentId = "my-agent"
Usage via POST /hooks/agent:
{ "message": "...", "agentId": "my-agent" }
Includes tests for mapping passthrough and payload normalization.
Includes doc updates for webhook.md.
* fix(hooks): enforce webhook agent routing policy + docs/changelog updates (#13672) (thanks @BillChirico)
* fix(hooks): harden explicit agent allowlist semantics (#13672) (thanks @BillChirico)
---------
Co-authored-by: Pip <pip@openclaw.ai>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
This commit is contained in:
@@ -3176,12 +3176,17 @@ Defaults:
|
||||
enabled: true,
|
||||
token: "shared-secret",
|
||||
path: "/hooks",
|
||||
// Optional: restrict explicit `agentId` routing.
|
||||
// Omit or include "*" to allow any agent.
|
||||
// Set [] to deny all explicit `agentId` routing.
|
||||
allowedAgentIds: ["hooks", "main"],
|
||||
presets: ["gmail"],
|
||||
transformsDir: "~/.openclaw/hooks",
|
||||
mappings: [
|
||||
{
|
||||
match: { path: "gmail" },
|
||||
action: "agent",
|
||||
agentId: "hooks",
|
||||
wakeMode: "now",
|
||||
name: "Gmail",
|
||||
sessionKey: "hook:gmail:{{messages[0].id}}",
|
||||
@@ -3203,7 +3208,7 @@ Requests must include the hook token:
|
||||
Endpoints:
|
||||
|
||||
- `POST /hooks/wake` → `{ text, mode?: "now"|"next-heartbeat" }`
|
||||
- `POST /hooks/agent` → `{ message, name?, sessionKey?, wakeMode?, deliver?, channel?, to?, model?, thinking?, timeoutSeconds? }`
|
||||
- `POST /hooks/agent` → `{ message, name?, agentId?, sessionKey?, wakeMode?, deliver?, channel?, to?, model?, thinking?, timeoutSeconds? }`
|
||||
- `POST /hooks/<name>` → resolved via `hooks.mappings`
|
||||
|
||||
`/hooks/agent` always posts a summary into the main session (and can optionally trigger an immediate heartbeat via `wakeMode: "now"`).
|
||||
@@ -3214,6 +3219,8 @@ Mapping notes:
|
||||
- `match.source` matches a payload field (e.g. `{ source: "gmail" }`) so you can use a generic `/hooks/ingest` path.
|
||||
- Templates like `{{messages[0].subject}}` read from the payload.
|
||||
- `transform` can point to a JS/TS module that returns a hook action.
|
||||
- `agentId` can route to a specific agent; unknown IDs fall back to the default agent.
|
||||
- `hooks.allowedAgentIds` restricts explicit `agentId` routing (`*` or omitted means allow all, `[]` denies all explicit routing).
|
||||
- `deliver: true` sends the final reply to a channel; `channel` defaults to `last` (falls back to WhatsApp).
|
||||
- If there is no prior delivery route, set `channel` + `to` explicitly (required for Telegram/Discord/Google Chat/Slack/Signal/iMessage/MS Teams).
|
||||
- `model` overrides the LLM for this hook run (`provider/model` or alias; must be allowed if `agents.defaults.models` is set).
|
||||
|
||||
Reference in New Issue
Block a user