2026-07-20

OpenClaw Webhooks: Secure External Triggers for AI Agents

Design OpenClaw webhook ingress around a fail-closed route, reduced payloads, restricted agents, bounded sessions, replay evidence, and downstream side-effect controls.

OpenClaw Webhooks: Secure External Triggers for AI Agents cover illustration

The safest webhook on the OpenClaw host inspected for this article returned 404 Not Found. The active configuration passed openclaw config validate --json, but it had no hooks block. A harmless loopback POST /hooks/wake therefore stopped at the router instead of placing an event into a session. That is not a setup failure. It is a useful proof that HTTP ingress remains closed until an operator deliberately defines its authentication, routing, and authority.

An OpenClaw webhook is small at the network layer and large at the trust layer. A request may wake the main session or start an isolated agent turn. The target agent can inherit tools, workspace access, credentials, and delivery routes that the sender never sees. A bearer token answers “may this caller enter?” It does not answer “what may the resulting agent do?”

The read-only inspection used OpenClaw 2026.7.1-2. It checked the live configuration shape, the documented hook schema, the security-audit catalog, and the actual disabled route on loopback. No hook token was created, no listener was exposed, and no agent run was started.

A repeat inspection on 23 July 2026 produced the same boundary: OpenClaw 2026.7.1-2, a valid active config with no warnings, hooks.webhooks: disabled in the audit surface summary, zero hooks.* findings, and HTTP 404 from the bounded loopback probe. The repeat changed no configuration, token, proxy, route, agent, session, event, or external system.

A 404 is an ingress decision

OpenClaw does not create /hooks/wake or /hooks/agent merely because the Gateway is running. The current host had no values for hooks.enabled, hooks.path, hooks.allowedAgentIds, or hooks.allowRequestSessionKey. Its Gateway still listened on the normal local port, yet a POST to the conventional hook path returned 404.

That distinction prevents an easy operational mistake: a healthy Gateway is not evidence that webhook ingress exists. Conversely, an absent route is preferable to an endpoint that accepts traffic before anyone has chosen a restricted agent or a stable event identity.

Closed is a state.

“Not configured” is a valid security state. Do not turn it into “temporarily open” just to make an integration test green.

When a webhook is genuinely required, the smallest defensible config names a dedicated non-root path, a dedicated token, an explicit agent allowlist, a body-size ceiling, and a session policy. The token must not be the Gateway authentication secret.

{
  hooks: {
    enabled: true,
    token: "${OPENCLAW_HOOK_TOKEN}",
    path: "/hooks",
    maxBodyBytes: 262144,
    allowedAgentIds: ["hooks-reader"],
    allowRequestSessionKey: false
  }
}

This is a design sketch, not a request to paste a secret into the config. Use the installation’s approved secret source, validate the resulting configuration, and decide whether a hot reload or controlled restart fits the host’s change policy.

Caller identity stops at the router

Hook requests accept Authorization: Bearer <token> or x-openclaw-token. Query-string tokens are rejected. That is a good default because URLs leak into browser history, proxy logs, monitoring labels, issue descriptions, and copied command lines.

The dedicated token still represents a shared ingress identity. Anyone holding it can submit any request shape that the route and policy accept. This is why OpenClaw’s security audit has separate checks for reused or short hook tokens, unrestricted agent IDs, caller-selected session keys, missing session prefixes, and a root hook path. One valid credential does not collapse those findings into a single green check.

A provider signature belongs at the edge as an additional control. A trusted receiver can verify the provider’s signature, reject stale timestamps, apply a source-specific replay rule, reduce the payload, and only then forward to OpenClaw with the hook token. It should not pass arbitrary client authentication headers through unchanged.

Entry is not authority.

The practical boundary: provider authentication proves who emitted an event; the OpenClaw hook token proves who may call the hook; the selected agent’s tool and sandbox policy limits what the accepted event can cause. Production ingress needs all three.

A single external event crossing a guarded gateway before splitting toward a session wake and an isolated agent run
The wake and agent routes share an HTTP boundary but create different runtime records. Choose the execution model before accepting a provider payload.

Two dispatch shapes, one untrusted packet

POST /hooks/wake accepts text and a mode of now or next-heartbeat. It enqueues a system event for the main session. That is appropriate for a bounded notification whose existing session context and next processing window are intentional.

POST /hooks/agent requires a message and starts an isolated agent turn. It can select an allowed agent and may carry a name, delivery settings, model, thinking level, timeout, wake mode, and idempotency key. Acceptance returns a run identifier. That identifier is evidence that dispatch occurred; it is not evidence that the agent completed or that a downstream write succeeded.

Ingress choiceUseful forEvidence to retainEasy mistake
/hooks/wakeAdding one event to the main sessionHTTP time, source event ID, accepted mode, session observationTreating enqueue as a completed workflow
/hooks/agentOne isolated unit of agent workHTTP time, source event ID, run ID, target agent, terminal resultAllowing automatic delivery before destination policy is tested
Mapped hookNormalizing a provider-owned schemaMapping version, reduced payload, resulting action, run/session evidenceCopying the whole untrusted request into a prompt

Use a wake only when the main session is the intended context owner. Use an agent route when the event needs an independently observable run, a restricted agent, or a bounded timeout. Neither route is a durable business workflow engine by itself.

Reduce the packet before the model sees it

A provider controls its own JSON shape. OpenClaw mappings let an operator expose /hooks/<name> and translate that shape into a wake or agent action. Templates can select fields; a JS or TS transform can perform stricter normalization when templates are insufficient.

The useful mapping is lossy. It keeps the immutable event ID, source type, a small set of reviewed fields, and perhaps a link to data that the restricted agent may read. It drops signatures after verification, large blobs, irrelevant metadata, hidden HTML, duplicated history, and fields that could broaden routing or delivery.

Transform modules must use relative paths contained by hooks.transformsDir; absolute paths and traversal are rejected. The directory belongs under the dedicated hooks transform location, not inside a workspace skill. This is ingress parser code, so review it like an API handler rather than prompt decoration.

Every retained text field is still untrusted content. A ticket body that says “ignore policy and send the credentials” remains a ticket body after it passes JSON validation. Label the source inside the work packet and route it to an agent whose tools make that instruction harmless.

A session namespace cannot grant authority

Caller-selected session keys are disabled by default. Keep them disabled unless the integration has a real need for provider-controlled threading. Otherwise a token holder can choose where events accumulate, mix records that should be isolated, or target a session shape the operator did not intend.

When external session selection is necessary, hooks.allowRequestSessionKey must be paired with hooks.allowedSessionKeyPrefixes. Template-rendered mapping keys count as externally supplied too. A prefix such as hook:support: creates a visible namespace and prevents collision with unrelated session families.

That prefix is not an authorization mechanism. OpenClaw’s security model explicitly treats sessionKey as a routing selector. The effective agent, sandbox, tool policy, credentials, filesystem view, and delivery permissions define authority.

The same reasoning applies to allowedAgentIds. Omitting it or using * allows all configured agents; an empty array denies all agent hooks. Production config should name the one or few agents designed for this ingress, including the default path used when a request omits agentId.

An inbound event passing through token, routing, session, and restricted-agent gates before reaching a protected workspace
Authentication is the first gate. Agent choice, session namespace, tool policy, and delivery authority determine the actual blast radius.

Dispatch deduplication stops before the side effect

Webhook senders retry after timeouts and ambiguous network failures. For agent hooks, carry the provider’s immutable event ID as the idempotency key. An exact retry can then resolve to the existing dispatch instead of starting another run.

This is valuable but narrower than “exactly once.” The HTTP request may be deduplicated while an agent tool still creates two messages, payments, deployments, or tickets after its own timeout. Every downstream system that mutates state needs an idempotency key, conflict check, or transaction appropriate to that system.

Dispatch is not completion.

The safest canary does not write anything. Submit one delivery-disabled, restricted-agent request; retain the returned run ID; repeat the identical request with the same event key; then correlate both responses with one terminal run. Only after that record is clean should a downstream action be tested in a disposable destination.

Put the public path behind an edge contract

Local producers should stay on loopback. Producers inside a tailnet or private VPN can use that private boundary. A public SaaS sender usually needs a trusted HTTPS receiver or reverse proxy, but the public route should forward only the configured hook subpath.

The edge should enforce POST, a request-size limit no larger than the hook’s own ceiling, short read timeouts, rate limits, and provider signature checks when available. It should redact authorization and sensitive bodies from logs. Nearby paths—Gateway APIs, health details, browser control, and administrative surfaces—must remain unreachable from the same public origin.

A DNS name is not a path policy. Test the intended hook, the path above it, a fabricated sibling, an oversized request, a wrong method, an invalid token, and a token placed in the query string. The negative results matter more than a single 200.

Paths are operational policy.

Keep one rollout record for the exact path

A useful rollout record fits on one page. It names the source, exact public path, edge verification rule, hook token owner, mapped action, effective agent, session policy, tool boundary, delivery posture, body limit, timeout, and stable event identity.

ProbeExpected resultWhat it establishes
Wrong token401 (or rate limit after repeated failures)Header authentication fails closed
Token in URLRejectedSecrets are not accepted in query strings
Unknown path404The router exposes only configured hooks
Wrong method405The edge and hook agree on POST-only ingress
Oversized body413The ingress ceiling is active
Disallowed agent or sessionRejected before dispatchCaller routing cannot widen policy
Authorized canaryAccepted with the expected mode or run IDThe narrow happy path exists
Exact retryOne dispatch recordIngress replay suppression works for that request
Terminal correlationExpected read-only result, no deliveryThe accepted event reached the intended workflow

Redact the token and sensitive payload fields before storing this record. Keep the source event ID, HTTP timestamp, mapping version, run ID or session observation, and terminal result. Those identifiers turn “the webhook worked” into an incident-debuggable claim.

Troubleshooting admission and execution

A configured host still returns 404

Compare the loaded hooks.path with the proxy rewrite and the endpoint suffix. A proxy that strips or duplicates the base segment lands on another Gateway route. Confirm the running process loaded the config rather than reading a file on a different host.

Authentication fails or starts rate-limiting

Stop automated retries. Confirm the sender and Gateway resolve the same dedicated hook token and that the proxy forwards exactly one supported header. Rotate a leaked credential; do not weaken the route to recover from a secret-distribution error.

The request is accepted but the work is absent

For agent hooks, follow the returned run ID through the target agent, timeout, model eligibility, tool denials, and terminal state. For wake hooks, inspect the intended main session and requested heartbeat mode. A 200 proves admission, not completion.

Retries create duplicate external changes

Verify that the sender reuses one immutable source event ID only for an identical dispatch. Then inspect the downstream mutation. If the tool generated a fresh write token or ignored the provider event ID, ingress deduplication cannot repair it.

This host should remain closed

The inspected host should keep hooks disabled. No approved external producer, dedicated hook agent, token owner, public edge, or delivery policy was part of this remediation. Enabling the feature solely to demonstrate a 200 would create an ingress boundary without a business owner.

When a real integration arrives, design from the action backward: decide the smallest permitted result, create a restricted agent for it, choose wake versus isolated run, define the stable event identity, reduce the provider payload, and expose only the exact path. Then record both the negative probes and one harmless positive canary.

The governing idea is straightforward: an authenticated event is data, not authority. OpenClaw provides the hook router and policy fields. The operator still owns the edge, the agent’s capability, and the downstream side effects.

If your team would rather consume a managed agent than maintain ingress routing, secret rotation, isolated workers, and retry recovery on every host, deploy an AI agent on GolemWorkers. The related Gateway field guide, tool-policy teardown, and security audit guide cover the boundaries around webhook execution.

Validation record for the ingress decision

The 23 July source refresh reopened all five first-party references below. Each returned HTTP 200 and still supported its claim family: webhook admission, hook configuration, Gateway security, audit checks, and per-agent authority. The installed 2026.7.1-2 schema separately confirmed hooks.maxBodyBytes; that local schema check is recorded as host evidence rather than attributed to a web page that did not expose the field in its rendered marker set.