Skip to content

[Bug]: Heartbeat wakeups are persisted into main dashboard session as synthetic user messages #43168

@swissmike-zh

Description

@swissmike-zh

Bug type

Regression (worked before, now fails)

Summary

Summary

Heartbeat / gateway exec-completion events are being persisted into the main Gateway Dashboard chat session as normal role:"user" messages.

What happens

After some idle time, or after a WhatsApp gateway send completes, the dashboard chat shows a message like:

System: [timestamp] Exec completed (...) :: ✅ Sent via gateway (whatsapp). Message ID: ...

followed by:

Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.

My original user prompt is still processed correctly, but this internal heartbeat/system message is also written into the visible transcript.

Expected behavior

Heartbeat wakeups and gateway exec/system events should remain internal, or use a hidden/internal session.

They should not be appended to the visible main chat transcript as synthetic user messages.

Actual behavior

They are persisted into the main session JSONL as normal user messages, and appear in the dashboard chat.

Evidence

Session file:
/home/openclaw/.openclaw/agents/main/sessions/3e286de2-bf8d-4fca-a5cf-f8513a76450a.jsonl

Normal dashboard user message:
[Wed 2026-03-11 11:57 UTC] lets go!

Later in the same session, persisted synthetic user message:
System: [2026-03-11 12:08:32 UTC] Exec completed (briny-nu, code 0) :: ✅ Sent via gateway (whatsapp). Message ID: 3EB04BAAAB0A15952DBBDD

followed by the full HEARTBEAT prompt.

Example persisted entry shape:

  • message.role = "user"
  • content starts with System: [timestamp] Exec completed ...
  • then includes Read HEARTBEAT.md ...

Additional observations

  • Refreshing chat causes my original message to reappear, but the injected heartbeat/system message remains.
  • The original user prompt is still acted upon correctly.
  • This appears to be backend session contamination, not only a frontend rendering issue.

Version

OpenClaw 2026.3.8

Environment

Self-hosted Gateway Dashboard with WhatsApp gateway enabled.

Suspected cause

A gateway exec-completion/system event wakes heartbeat, and that wakeup is appended into the main visible session as a synthetic user message instead of being handled in an internal/hidden session.

Steps to reproduce

  1. Start OpenClaw Gateway Dashboard with a normal agent session (e.g. main) and WhatsApp gateway enabled.

  2. Ensure a HEARTBEAT.md file exists in the workspace, for example:
    /home/openclaw/.openclaw/workspace/HEARTBEAT.md
    containing a heartbeat task (e.g. polling GitHub for issues).

  3. Open the Gateway Dashboard chat UI and send a normal user message (for example: lets go).

  4. Wait until the agent performs an action that sends a WhatsApp message via the gateway (for example via CLI or a tool call).

  5. Wait for the next heartbeat wakeup or background system event.

  6. Observe the dashboard chat.


Observed result

A new message appears in the dashboard chat that looks like:

System: [timestamp] Exec completed (...) :: ✅ Sent via gateway (whatsapp). Message ID: ...

Read HEARTBEAT.md if it exists...
...
reply HEARTBEAT_OK

This message is persisted into the session transcript as:

message.role = "user"

even though it is an internal heartbeat/system event.

Expected behavior

Heartbeat polling and gateway exec-completion events should remain internal (or use a hidden session) and should not appear as user messages in the dashboard chat transcript.

Actual behavior

Heartbeat polling and gateway exec-completion events were visible as user messages in the dashboard chat transcript**.

OpenClaw version

2026.3.8

Operating system

Ubuntu

Install method

docker

Model

claude-sonnet-4.5

Provider / routing chain

openclaw->anthropic

Config file / key location

No response

Additional provider/model setup details

Image

Logs, screenshots, and evidence

Screenshot attached

Impact and severity

No response

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingregressionBehavior that previously worked and now fails

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions