Skip to content

fix(whatsapp): ignore outbound echoes for inbound activity#79057

Merged
mcaxtr merged 2 commits intoopenclaw:mainfrom
ai-hpc:fix/whatsapp-inbound-activity-echoes
May 8, 2026
Merged

fix(whatsapp): ignore outbound echoes for inbound activity#79057
mcaxtr merged 2 commits intoopenclaw:mainfrom
ai-hpc:fix/whatsapp-inbound-activity-echoes

Conversation

@ai-hpc
Copy link
Copy Markdown
Contributor

@ai-hpc ai-hpc commented May 7, 2026

Summary

  • Problem: WhatsApp Web outbound echo events could update channel inbound activity before the message was filtered out as an outbound echo.
  • Why it matters: openclaw channels status --probe could report fresh inbound activity after a Gateway-originated self-send even though no real inbound WhatsApp message was handled.
  • What changed: WhatsApp now records inbound channel activity only after the message survives normalization, append-history filtering, enrichment, and recent-inbound dedupe, immediately before enqueueing the inbound message.
  • What did NOT change: Outbound activity recording, WhatsApp send behavior, self-chat filtering, group handling, and auto-reply dispatch are otherwise unchanged.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: WhatsApp self-sends should advance outbound activity but should not make channel status look like a fresh inbound message arrived.
  • Real environment tested: Ubuntu VPS, Node 22, managed systemd user Gateway, live linked WhatsApp Web account.
  • Exact steps or command run after this patch: rebuilt the local checkout, restarted the managed Gateway, captured openclaw channels status --json, sent one WhatsApp message to the linked account's own E.164 number through openclaw message send --channel whatsapp --account default, waited, then captured channels status --json and redacted Gateway logs.
  • Evidence after fix:
{
  "sendMessageId": "3EB0FE70141FB96653FA7A",
  "before": {
    "lastInboundAt": null,
    "lastOutboundAt": null,
    "connected": true,
    "healthState": "healthy"
  },
  "after": {
    "lastInboundAt": null,
    "lastOutboundAt": "2026-05-07T17:55:58.765Z",
    "connected": true,
    "healthState": "healthy"
  },
  "inboundAdvanced": false,
  "outboundAdvanced": true
}

Redacted matching logs after fix only showed the outbound send:

[whatsapp] Sending message -> sha256:<redacted>
[whatsapp] Sent message 3EB0FE70141FB96653FA7A -> sha256:<redacted> (138ms)
[ws] res send channel=whatsapp
  • Observed result after fix: outbound activity advanced and inbound activity did not advance.
  • What was not tested: every WhatsApp deployment mode, multi-account WhatsApp, and full repository test suite.
  • Before evidence: current main advanced both status timestamps for the same Gateway-originated self-send path:
{
  "sendMessageId": "3EB03B031C04B624AAEA9B",
  "before": {
    "lastInboundAt": "2026-05-07T17:18:40.619Z",
    "lastOutboundAt": "2026-05-07T17:18:40.517Z"
  },
  "after": {
    "lastInboundAt": "2026-05-07T17:41:18.191Z",
    "lastOutboundAt": "2026-05-07T17:41:18.145Z"
  },
  "inboundAdvanced": true,
  "outboundAdvanced": true
}

Root Cause (if applicable)

  • Root cause: attachWebInboxToSocket recorded inbound channel activity at the top of each WhatsApp messages.upsert item, before normalizeInboundMessage could reject Gateway-originated outbound echoes via the recent outbound-message filter.
  • Missing detection / guardrail: Existing outbound echo tests asserted no inbound message was delivered, but did not assert that inbound channel activity was not recorded.
  • Contributing context (if known): channels status uses channel activity as fallback status metadata, so pre-filter raw WhatsApp Web events can leak into user-visible status even when the inbound message is later dropped.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/whatsapp/src/monitor-inbox.behavior.test.ts
  • Scenario the test should lock in: Gateway-originated WhatsApp fromMe echoes are filtered without recording inbound channel activity.
  • Why this is the smallest reliable guardrail: The bug is local to the WhatsApp inbox monitor's ordering around echo filtering and enqueueing.
  • Existing test that already covers this (if any): Existing echo-filter tests covered no inbound delivery; this PR extends them to cover channel activity accounting.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

openclaw channels status --probe no longer reports fresh WhatsApp inbound activity from a Gateway-originated outbound echo/self-send.

Diagram (if applicable)

Before:
WhatsApp Web upsert -> record inbound activity -> echo filter drops message -> status still shows inbound activity

After:
WhatsApp Web upsert -> echo/history/enrichment/dedupe filters -> record inbound activity only for accepted inbound -> enqueue

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: Ubuntu 24.04
  • Runtime/container: Node 22, systemd user Gateway
  • Model/provider: N/A
  • Integration/channel (if any): WhatsApp Web, account default
  • Relevant config (redacted): live linked WhatsApp account, loopback Gateway

Steps

  1. Start a linked WhatsApp Gateway account.
  2. Capture openclaw channels status --json.
  3. Send a Gateway-originated WhatsApp message to the linked account's own E.164 number.
  4. Capture openclaw channels status --json again.
  5. Compare lastInboundAt and lastOutboundAt.

Expected

  • lastOutboundAt advances.
  • lastInboundAt does not advance unless a real inbound WhatsApp message is handled.

Actual

  • Before this patch, both lastInboundAt and lastOutboundAt advanced for the self-send echo.
  • After this patch, only lastOutboundAt advances.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: outbound self-send status accounting on a live linked WhatsApp Gateway; focused WhatsApp inbox echo tests; broader WhatsApp send/inbound/status/session tests.
  • Edge cases checked: outbound DM echo, self-chat DM echo, append history filtering, inbound dedupe, media/status/session neighboring tests.
  • What you did not verify: full repository suite, every WhatsApp account topology, and long-lived multi-day runtime behavior.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: Moving activity accounting later could miss activity for messages that are normalized but intentionally skipped before enqueueing.
  • Mitigation: That is the intended boundary for user-visible inbound activity; skipped echoes, stale append history, failed enrichment, and duplicate redeliveries should not make status report fresh inbound handling.

@openclaw-barnacle openclaw-barnacle Bot added channel: whatsapp-web Channel integration: whatsapp-web size: S proof: supplied External PR includes structured after-fix real behavior proof. labels May 7, 2026
@ai-hpc ai-hpc force-pushed the fix/whatsapp-inbound-activity-echoes branch from f44426b to d6b3476 Compare May 7, 2026 18:51
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 7, 2026

Codex review: needs maintainer review before merge.

Summary
The PR moves WhatsApp Web inbound activity recording to the accepted-inbound enqueue boundary, adds outbound-echo activity assertions to inbox tests, and adds a changelog entry.

Reproducibility: yes. The linked bug report gives a live current-main WhatsApp Web self-send reproduction, and source inspection confirms current main records inbound activity before the outbound-echo filter while channel status exposes that activity.

Real behavior proof
Sufficient (logs): The PR body includes after-fix live WhatsApp Web status JSON and redacted Gateway logs showing the corrected outbound-only activity result.

Next step before merge
No ClawSweeper repair job is needed because the latest PR diff has no actionable code-level finding and the earlier changelog blocker is fixed.

Security
Cleared: The diff only moves local activity accounting and adds unit-test/changelog coverage; it does not add permissions, dependencies, downloads, secrets handling, or execution surfaces.

Review details

Best possible solution:

Land this PR or an equivalent narrow fix once the normal exact-head checks pass.

Do we have a high-confidence way to reproduce the issue?

Yes. The linked bug report gives a live current-main WhatsApp Web self-send reproduction, and source inspection confirms current main records inbound activity before the outbound-echo filter while channel status exposes that activity.

Is this the best way to solve the issue?

Yes. Moving the timestamp side effect to the accepted-inbound boundary is the narrow maintainable fix, and the latest diff also restores the required changelog coverage.

What I checked:

Likely related people:

  • steipete: Recent local history and blame cover the current WhatsApp monitor ordering and the channel activity runtime refactor used by this path. (role: recent maintainer / adjacent owner; confidence: high; commits: 164ecfd7c8fe, 491969efb091; files: extensions/whatsapp/src/inbound/monitor.ts, extensions/whatsapp/src/inbound/send-api.ts)
  • OfflynAI: Merged history shows the WhatsApp fromMe outbound echo filter was introduced in the monitor, which is the filter this PR now aligns activity recording with. (role: introduced related echo-filter behavior; confidence: medium; commits: e45533d5680c; files: extensions/whatsapp/src/inbound/monitor.ts)
  • Takhoffman: History shows adjacent work on channel status state in the server method that falls back to channel activity timestamps. (role: adjacent status-surface owner; confidence: medium; commits: 0bcf07690137; files: src/gateway/server-methods/channels.ts)

Remaining risk / open question:

  • This was a read-only review, so exact-head CI and focused test execution should still be the merge gate.

Codex review notes: model gpt-5.5, reasoning high; reviewed against b1eedb2fc8a1.

@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 7, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 7, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 7, 2026
@ai-hpc ai-hpc force-pushed the fix/whatsapp-inbound-activity-echoes branch from d6b3476 to ec81a59 Compare May 7, 2026 19:27
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 7, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 7, 2026
@mcaxtr mcaxtr self-assigned this May 8, 2026
@mcaxtr mcaxtr force-pushed the fix/whatsapp-inbound-activity-echoes branch from ec81a59 to eb051e8 Compare May 8, 2026 03:52
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 8, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 8, 2026
@mcaxtr mcaxtr force-pushed the fix/whatsapp-inbound-activity-echoes branch from eb051e8 to 3b1f38a Compare May 8, 2026 04:01
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 8, 2026
@mcaxtr mcaxtr merged commit 36f847a into openclaw:main May 8, 2026
96 of 97 checks passed
@mcaxtr
Copy link
Copy Markdown
Member

mcaxtr commented May 8, 2026

Merged via squash.

Thanks @ai-hpc!

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…79057)

Merged via squash.

Prepared head SHA: 3b1f38a
Co-authored-by: ai-hpc <183861985+ai-hpc@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
rogerdigital pushed a commit to rogerdigital/openclaw that referenced this pull request May 9, 2026
…79057)

Merged via squash.

Prepared head SHA: 3b1f38a
Co-authored-by: ai-hpc <183861985+ai-hpc@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: whatsapp-web Channel integration: whatsapp-web proof: supplied External PR includes structured after-fix real behavior proof. size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: WhatsApp outbound self-sends make channels status report fresh inbound activity

2 participants