#Wake hook no longer working after update from 2026.4.24 to 2026.5.7

1 messages · Page 1 of 1 (latest)

strong mauve
#

I have a webhook that calls /hooks/wake with mode: now and everything used to work properly.

Today I updated OpenClaw to the latest version using openclaw update and the hook does not work anymore. I still receive a successful response to the HTTP call:

{
  "mode" : "now",
  "ok" : true
}

But nothing happens on the bot side. Did something change between those versions? Can you help me debug?

vagrant kindleBOT
#

I checked the current code + docs. The important bit: /hooks/wake still exists and the 200 response only means “accepted + enqueued a system event”; it does not prove a heartbeat turn actually ran.

Between 2026.4.24 and 2026.5.7, the wake path did change internally: it moved from the older requestHeartbeatNow(...) path to the newer heartbeat wake scheduler with source: "hook" / intent: "immediate". mode: now should still wake immediately, but it can now be affected by heartbeat runner state/flood protection, and it may enqueue into the configured main session while nothing visible is delivered if heartbeat is disabled/stuck or pointed somewhere unexpected.

Quick debug path:

openclaw --version
openclaw status --all
openclaw gateway status
openclaw system heartbeat last
openclaw health --verbose

Then test the same underlying mechanism without HTTP hooks:

#
openclaw system event --text "hook wake test" --mode now --expect-final

If that also does nothing, the problem is heartbeat/session/runtime, not the webhook. Try:

openclaw system heartbeat enable
openclaw logs --follow

Then fire the hook again and look for hook:wake, heartbeat, flood guard, disabled, not-due, requests-in-flight, or model/runtime errors.

Also double-check your request still includes non-empty text; current /hooks/wake requires it:

#
{"text":"New event received","mode":"now"}

Docs: https://docs.openclaw.ai/automation/cron-jobs#webhooks and https://docs.openclaw.ai/cli/system

If you paste the redacted output of openclaw status --all, openclaw system heartbeat last, and the log lines around one hook call, I can help narrow it down. My hunch is either heartbeat got disabled/not registered after the update, or the event is landing in a main session that no longer has visible delivery attached.

strong mauve
#
% openclaw system heartbeat last

🦞 OpenClaw 2026.5.7 (eeef486)
   The only open-source project where the mascot could eat the competition.

│
â—‡
{
  "ts": 1778439801789,
  "status": "ok-token",
  "reason": "hook:wake",
  "durationMs": 34,
  "channel": "whatsapp",
  "accountId": "default",
  "silent": true,
  "indicatorType": "ok"
}

No log lines are emitted at all when I fire the webhook.
Made sure heartbeats are enabled.

Test webhook results in log line:

19:26:42+00:00 info ok

I cannot paste the full output of status --all because it's too long for a Discord message

vagrant kindleBOT
#

That heartbeat last output is actually a strong clue: the webhook did wake the heartbeat.

status: "ok-token" + reason: "hook:wake" means the heartbeat turn ran, but the agent returned the silent/OK heartbeat response, so OpenClaw intentionally didn’t send a visible bot message. The 34ms duration also suggests it may be taking a fast “nothing to notify” path rather than doing the behavior you expected.

So I’d split this into two questions:

  1. Is the hook being accepted/waking? Yes — reason: hook:wake confirms that.
  2. Why does the agent decide to stay silent? That’s now the real bug/behavior change.

A few focused checks:

openclaw system event --text "PASTE THE SAME TEXT YOU SEND TO /hooks/wake" --mode now --expect-final
openclaw system heartbeat last

If that also becomes ok-token, the issue is not HTTP hooks; it’s the heartbeat prompt/decision path treating that system event as non-actionable.

#

Also: /hooks/wake is only “enqueue a system event for the main heartbeat”. If you want a guaranteed agent turn for a webhook, 2026.5.7’s better fit is usually /hooks/agent:

curl -X POST http://127.0.0.1:18789/hooks/agent \
  -H 'Authorization: Bearer ***' \
  -H 'Content-Type: application/json' \
  -d '{"message":"Do the webhook action here","name":"Webhook","wakeMode":"now","deliver":true,"channel":"whatsapp"}'

For the too-long status output, don’t paste all of it — the useful bits are:

openclaw status --all | grep -Ei 'heartbeat|agent|main session|session|whatsapp|discord|disabled|error|queue|processing' -C 3
openclaw system heartbeat last --json

And one key question: what exact text are you sending to /hooks/wake? Redacted is fine. If it’s more like “event happened” than “notify me / do X”, the newer heartbeat path may just acknowledge it silently.

strong mauve
#

The heartbeat text should be explicitly be handled by the agent, as it always has been. This issue popped up only after the update and I did not change anything around it.

Also sending the event manually via CLI results in no action. I don't even see HEARTBEAT_OK in the chat on the web UI, which I usually see if the agent decides to take no action

vagrant kindleBOT
#

Yep — I agree with your read. If the same text via openclaw system event --mode now also does nothing, this is below /hooks/wake; the wake endpoint is just the messenger.

Two important clues:

  • status: "ok-token" means a heartbeat turn completed and was classified as “agent chose no visible notification”.
  • In 2026.5.7, tool-capable/Codex heartbeat runs may use the structured heartbeat_respond tool with notify:false instead of literally sending HEARTBEAT_OK. So not seeing HEARTBEAT_OK in Web UI may be expected now, but it doesn’t explain why your actionable event is ignored.

The durationMs: 34 is the part I don’t like — that’s suspiciously fast for a real agent turn. It suggests the heartbeat may be short-circuiting / using a path that never includes the queued system event in the model prompt.

Can you paste only these redacted snippets instead of full status --all?

openclaw config get agents.defaults.heartbeat --json
openclaw config get messages.visibleReplies --json
openclaw config get channels.whatsapp.heartbeat --json
openclaw system heartbeat last --json
#

Also please run this exact A/B test:

openclaw system event --text "URGENT TEST: reply visibly with the words webhook wake handled" --mode now
sleep 3
openclaw system heartbeat last --json

If that returns another fast ok-token, I’d call this a regression in the 2026.5.7 heartbeat/system-event path and file it: https://github.com/openclaw/openclaw/issues

Temporary workaround if you need reliable behavior now: switch this integration from /hooks/wake to /hooks/agent. /hooks/wake depends on heartbeat interpretation; /hooks/agent runs an isolated agent turn directly and returns a runId.

strong mauve
#

Your test still returns ok-token. Can you try to pinpoint the bug in the code so that we can figure out which version to downgrade to?

vagrant kindleBOT
#

I think I’ve got the regression narrowed down pretty tightly.

The webhook is not the broken layer. /hooks/wake enqueues the system event and heartbeat runs. The likely break is in the heartbeat response-tool path added after your old version.

What changed:

  • v2026.4.29 / your old v2026.4.24 path: heartbeat prompts end with normal HEARTBEAT_OK semantics. Generic queued system events are drained into the heartbeat prompt as System: lines and a visible reply can be produced.
  • v2026.5.2: commit 439d8edf68 adds heartbeat_respond. If the model returns notify:false, heartbeat-runner.ts emits status: "ok-token", restores updatedAt, consumes inspected events, and sends nothing visible.
  • v2026.5.3: commit 8f4eaa9c00 / follow-up 877eb1cbed makes this path much more likely/forced for Codex/message-tool style runs: enableHeartbeatTool: true, forceHeartbeatTool: true, sourceReplyDeliveryMode: "message_tool_only", and the prompt switches from “reply HEARTBEAT_OK” to “use heartbeat_respond”.

The suspicious bug is: a wake/system-event run can include the queued event, but the model is now allowed/encouraged to satisfy the heartbeat with heartbeat_respond({ notify:false, ... }). The runner then treats that as success and consumes the event, so your explicit wake text disappears as a silent ok-token.

Most relevant code in current src/infra/heartbeat-runner.ts:

  • resolveHeartbeatRunPrompt(...) chooses resolveHeartbeatResponseToolPrompt(...) when useHeartbeatResponseTool is true.
  • replyOpts sets forceHeartbeatTool: true and sourceReplyDeliveryMode: "message_tool_only".
  • the if (heartbeatToolResponse && !heartbeatToolResponse.notify) branch emits ok-token and calls consumeInspectedSystemEvents().

Downgrade recommendation:

#
  • safest known-good: v2026.4.24 since you confirmed it worked.
  • latest stable before this regression family: v2026.4.29.
  • I would avoid v2026.5.2+ for this specific webhook/system-event behavior; v2026.5.3+ is especially suspect because that’s where the response-tool path becomes forced for the relevant runs.

Short-term config workaround to test before downgrading: if you have messages.visibleReplies: "message_tool", try setting it to "automatic" temporarily. That should make shouldUseHeartbeatResponseToolPrompt(...) return false and bypass the forced heartbeat response-tool path. If that fixes it, we’ve basically confirmed the culprit. 🦞

strong mauve
#

I currently don't have that key set. What's the default value? Also what does it do exactly?

vagrant kindleBOT
#

Good catch — if messages.visibleReplies itself is unset, there isn’t a simple literal config default like "automatic" stored in config.

Effective behavior is:

  • Direct/source chats: unset usually behaves like "automatic", except runtimes/harnesses can provide their own default. The Codex harness defaults unset direct/source turns to tool-only / message_tool behavior.
  • Group/channel rooms: default is effectively messages.groupChat.visibleReplies: "message_tool" unless overridden.

What it does:

  • "automatic" = OpenClaw may take the assistant’s final text and post it back to the source chat automatically.
  • "message_tool" = normal final text stays private/internal; if the assistant wants visible output, it must call the message tool. This avoids accidental public replies in group/channel contexts and gives the model explicit control over visible sends.

Why it matters here: in heartbeat-runner.ts, the heartbeat response-tool path checks:

if (messages.visibleReplies === "message_tool") return true;
if (messages.visibleReplies === "automatic") return false;
return usesCodexHarness(...);
#

So with the key unset and Codex harness active, it can still choose the heartbeat_respond tool path. That’s why explicitly setting:

messages: {
  visibleReplies: "automatic"
}

is a useful diagnostic: it forces that function to return false and should bypass the forced structured heartbeat response path for direct/source heartbeat runs. Docs reference: https://docs.openclaw.ai/gateway/config-channels

strong mauve
#

Changed the config, restarted the gateway, still no changes

vagrant kindleBOT
#

Okay, then my previous branch is probably not the whole issue. There are two ways to get ok-token now:

  1. heartbeat_respond notify:false
  2. plain final text of HEARTBEAT_OK / equivalent, after the event never made it into the prompt

Since messages.visibleReplies: "automatic" didn’t change it, I’d check the second path next.

The next suspicious code path is session mismatch with heartbeat.isolatedSession:

// hooks.ts
const sessionKey = resolveMainSessionKeyFromConfig();
enqueueSystemEvent(value.text, { sessionKey, trusted: false });
requestHeartbeat({ source: "hook", intent: "immediate", reason: "hook:wake" });

But in heartbeat-runner.ts, if heartbeat.isolatedSession === true, wake events are only inspected when the heartbeat is already running on the isolated :heartbeat session:

#
if (params.heartbeat?.isolatedSession !== true) return true;
...
return isolatedSessionKey === session.sessionKey;

So if your wake hook queues the event on the main session, but the heartbeat run executes in a fresh :heartbeat session, the queued text can be ignored and the model just sees the normal heartbeat prompt → HEARTBEAT_OK → ok-token.

Can you check this one value?

openclaw config get agents.defaults.heartbeat.isolatedSession --json

If it’s true, try temporarily setting it to false, restart, and run the manual event test again. That would confirm the bug is: wake hooks enqueue system events to the base session, while isolated heartbeat runs don’t inspect/drain that base-session wake queue.

If it’s already false, then the next thing I’d want is the new openclaw system heartbeat last --json after your latest test — specifically whether it has a preview. A preview usually means heartbeat tool notify:false; no preview usually points to literal HEARTBEAT_OK stripping.

strong mauve
#

There is no agents.defaults.heartbeat.isolatedSession. I don't know if that defaults to false, but anyway here is the heartbeat:

{
  "ts": 1778442929340,
  "status": "ok-token",
  "reason": "hook:wake",
  "durationMs": 96,
  "channel": "whatsapp",
  "accountId": "default",
  "silent": true,
  "indicatorType": "ok"
}
vagrant kindleBOT
#

Yep — heartbeat.isolatedSession defaults to false. If the key is absent, that specific isolated-session theory is probably not it.

The heartbeat JSON is useful: because there’s no preview, this is probably not the heartbeat_respond notify:false branch. That branch normally records the tool summary as preview.

So the current evidence points to the older/plain path:

normalized.shouldSkip && ... -> emit status: "ok-token"

Meaning the model/runtime returned something equivalent to HEARTBEAT_OK, and OpenClaw stripped it. In practical terms: the wake did run, but the queued wake text either:

  1. did not make it into the model prompt, or
  2. made it in as a generic/untrusted System: line and the new heartbeat prompt/model behavior ignored it as “nothing worth surfacing”.

Given you set messages.visibleReplies: "automatic" and there’s no preview, I’d revise the suspected regression window:

#
  • not primarily v2026.5.3 forced heartbeat_respond
  • more likely starts at v2026.5.2, where a cluster of heartbeat/message-tool prompt changes landed, including structured heartbeat responses and prompt changes around silent/no-reply handling.

Safe downgrade recommendation now:

  • Use v2026.4.29 as the latest stable-looking pre-v2026.5.2 target.
  • If you want the exact version you personally verified, use v2026.4.24.
  • I would avoid v2026.5.2+ for this wake/system-event flow until fixed.

For a maintainer fix, I’d focus the bug report on this invariant:

/hooks/wake and openclaw system event --mode now enqueue text and trigger heartbeat, but heartbeat returns silent ok-token with no preview. That means the queued wake payload is being treated like a normal empty heartbeat, not as actionable wake input.

Likely code-level fix direction: wake/system-event payloads should become a dedicated heartbeat prompt type, similar to cron/exec prompts, instead of relying on generic session-system-event draining plus the default “reply HEARTBEAT_OK if nothing needs attention” prompt.

strong mauve
#

How do I perform the downgrade?

vagrant kindleBOT
#

Use the updater with an exact tag/version.

I’d do a dry run first:

openclaw update --tag 2026.4.29 --dry-run

Then actually downgrade:

openclaw update --tag 2026.4.29

It should ask for confirmation because downgrades can be config-risky. If you want non-interactive:

#
openclaw update --tag 2026.4.29 --yes

Afterward verify:

openclaw --version
openclaw gateway status --deep
openclaw system event --text "URGENT TEST: reply visibly with the words webhook wake handled" --mode now

If the newer-config guard blocks a service action during this intentional downgrade, use the emergency env var for that single command only, e.g.:

OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1 openclaw gateway restart