mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 10:51:23 +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:
@@ -28,13 +28,16 @@ import {
|
||||
import { applyHookMappings } from "./hooks-mapping.js";
|
||||
import {
|
||||
extractHookToken,
|
||||
getHookAgentPolicyError,
|
||||
getHookChannelError,
|
||||
type HookMessageChannel,
|
||||
type HooksConfigResolved,
|
||||
isHookAgentAllowed,
|
||||
normalizeAgentPayload,
|
||||
normalizeHookHeaders,
|
||||
normalizeWakePayload,
|
||||
readJsonBody,
|
||||
resolveHookTargetAgentId,
|
||||
resolveHookChannel,
|
||||
resolveHookDeliver,
|
||||
} from "./hooks.js";
|
||||
@@ -52,6 +55,7 @@ type HookDispatchers = {
|
||||
dispatchAgentHook: (value: {
|
||||
message: string;
|
||||
name: string;
|
||||
agentId?: string;
|
||||
wakeMode: "now" | "next-heartbeat";
|
||||
sessionKey: string;
|
||||
deliver: boolean;
|
||||
@@ -207,7 +211,14 @@ export function createHooksRequestHandler(
|
||||
sendJson(res, 400, { ok: false, error: normalized.error });
|
||||
return true;
|
||||
}
|
||||
const runId = dispatchAgentHook(normalized.value);
|
||||
if (!isHookAgentAllowed(hooksConfig, normalized.value.agentId)) {
|
||||
sendJson(res, 400, { ok: false, error: getHookAgentPolicyError() });
|
||||
return true;
|
||||
}
|
||||
const runId = dispatchAgentHook({
|
||||
...normalized.value,
|
||||
agentId: resolveHookTargetAgentId(hooksConfig, normalized.value.agentId),
|
||||
});
|
||||
sendJson(res, 202, { ok: true, runId });
|
||||
return true;
|
||||
}
|
||||
@@ -243,9 +254,14 @@ export function createHooksRequestHandler(
|
||||
sendJson(res, 400, { ok: false, error: getHookChannelError() });
|
||||
return true;
|
||||
}
|
||||
if (!isHookAgentAllowed(hooksConfig, mapped.action.agentId)) {
|
||||
sendJson(res, 400, { ok: false, error: getHookAgentPolicyError() });
|
||||
return true;
|
||||
}
|
||||
const runId = dispatchAgentHook({
|
||||
message: mapped.action.message,
|
||||
name: mapped.action.name ?? "Hook",
|
||||
agentId: resolveHookTargetAgentId(hooksConfig, mapped.action.agentId),
|
||||
wakeMode: mapped.action.wakeMode,
|
||||
sessionKey: mapped.action.sessionKey ?? "",
|
||||
deliver: resolveHookDeliver(mapped.action.deliver),
|
||||
|
||||
Reference in New Issue
Block a user