openclaw - ✅(Solved) Fix [Bug]: Android companion notification events trigger individual agent runs instead of batching to heartbeat interval [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#61986Fetched 2026-04-08 03:10:29
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×2cross-referenced ×1

Android companion notification events each trigger an independent agent run instead of being batched to the heartbeat interval, causing unbounded API consumption.

Error Message

Error breakdown 2026-04-05 (0 successful runs):

130x network connection error

Root Cause

Android companion notification events each trigger an independent agent run instead of being batched to the heartbeat interval, causing unbounded API consumption.

Fix Action

Fixed

PR fix notes

PR #2: fix: batch Android notification events to heartbeat interval

Description (problem / solution / changelog)

Summary

Instead of triggering an immediate heartbeat wake for each notification event from Android companion, the fix uses scopedHeartbeatWakeOptions to allow events to be batched with the regular heartbeat interval. This prevents individual agent runs for each notification and consolidates them into the configured heartbeat schedule.

Changes

  • Modified src/gateway/server-node-events.ts to use scopedHeartbeatWakeOptions for notifications.changed events instead of directly calling requestHeartbeatNow with sessionKey
  • This matches the existing pattern used for exec.* events

Testing

  • The change follows the same pattern as existing exec.* event handling which uses scopedHeartbeatWakeOptions
  • Code compiles correctly with TypeScript

Fixes openclaw/openclaw#61986

Changed files

  • .agents/skills/openclaw-parallels-smoke/SKILL.md (modified, +15/-5)
  • .agents/skills/openclaw-release-maintainer/SKILL.md (modified, +52/-22)
  • .agents/skills/security-triage/SKILL.md (modified, +3/-0)
  • .codex (added, +0/-0)
  • .dockerignore (modified, +2/-0)
  • .github/actions/setup-node-env/action.yml (modified, +1/-1)
  • .github/actions/setup-pnpm-store-cache/action.yml (modified, +1/-1)
  • .github/labeler.yml (modified, +4/-0)
  • .github/pull_request_template.md (modified, +3/-5)
  • .github/workflows/auto-response.yml (modified, +6/-2)
  • .github/workflows/ci-bun.yml (removed, +0/-110)
  • .github/workflows/ci.yml (modified, +209/-47)
  • .github/workflows/docs-sync-publish.yml (added, +56/-0)
  • .github/workflows/install-smoke.yml (modified, +11/-9)
  • .github/workflows/macos-release.yml (modified, +6/-5)
  • .github/workflows/openclaw-npm-release.yml (modified, +278/-11)
  • .github/workflows/plugin-clawhub-release.yml (added, +276/-0)
  • .github/workflows/plugin-npm-release.yml (modified, +4/-1)
  • .gitignore (modified, +8/-1)
  • .markdownlint-cli2.jsonc (modified, +3/-0)
  • AGENTS.md (modified, +28/-7)
  • CHANGELOG.md (modified, +503/-258)
  • CONTRIBUTING.md (modified, +10/-1)
  • Dockerfile (modified, +1/-1)
  • Makefile (added, +4/-0)
  • README.md (modified, +52/-3)
  • SECURITY.md (modified, +19/-0)
  • appcast.xml (modified, +264/-197)
  • apps/android/app/build.gradle.kts (modified, +41/-33)
  • apps/android/app/src/main/AndroidManifest.xml (modified, +7/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/AssistantLaunch.kt (added, +43/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/MainActivity.kt (modified, +12/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/MainViewModel.kt (modified, +41/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt (modified, +142/-45)
  • apps/android/app/src/main/java/ai/openclaw/app/chat/ChatController.kt (modified, +51/-37)
  • apps/android/app/src/main/java/ai/openclaw/app/gateway/DeviceAuthStore.kt (modified, +67/-7)
  • apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewayHostSecurity.kt (added, +124/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewaySession.kt (modified, +107/-26)
  • apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewayTls.kt (modified, +33/-7)
  • apps/android/app/src/main/java/ai/openclaw/app/node/CanvasActionTrust.kt (modified, +17/-16)
  • apps/android/app/src/main/java/ai/openclaw/app/node/ConnectionManager.kt (modified, +12/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/CanvasScreen.kt (modified, +1/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/ConnectTabScreen.kt (modified, +26/-3)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/GatewayConfigResolver.kt (modified, +86/-12)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/GatewayDiagnostics.kt (modified, +1/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/OnboardingFlow.kt (modified, +41/-21)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/PostOnboardingTabs.kt (modified, +15/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/SettingsSheet.kt (modified, +55/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatComposer.kt (modified, +44/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatSheetContent.kt (modified, +46/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/voice/MicCaptureManager.kt (modified, +116/-10)
  • apps/android/app/src/main/java/ai/openclaw/app/voice/TalkAudioPlayer.kt (added, +242/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/voice/TalkModeManager.kt (modified, +97/-22)
  • apps/android/app/src/main/java/ai/openclaw/app/voice/TalkSpeakClient.kt (added, +143/-0)
  • apps/android/app/src/main/res/values/assistant.xml (added, +7/-0)
  • apps/android/app/src/main/res/xml/shortcuts.xml (added, +17/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/AssistantLaunchTest.kt (added, +43/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/GatewayBootstrapAuthTest.kt (modified, +170/-8)
  • apps/android/app/src/test/java/ai/openclaw/app/gateway/DeviceAuthStoreTest.kt (added, +63/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/gateway/GatewaySessionInvokeTest.kt (modified, +155/-6)
  • apps/android/app/src/test/java/ai/openclaw/app/gateway/GatewaySessionInvokeTimeoutTest.kt (modified, +17/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/node/CanvasActionTrustTest.kt (modified, +30/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/node/ConnectionManagerTest.kt (modified, +275/-1)
  • apps/android/app/src/test/java/ai/openclaw/app/ui/CanvasA2UIActionBridgeTest.kt (added, +50/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/ui/GatewayConfigResolverTest.kt (modified, +219/-25)
  • apps/android/app/src/test/java/ai/openclaw/app/ui/chat/ChatComposerDraftTest.kt (added, +44/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/ui/chat/ChatSheetContentTest.kt (added, +72/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/voice/TalkAudioPlayerTest.kt (added, +44/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/voice/TalkModeManagerTest.kt (added, +97/-0)
  • apps/android/app/src/test/java/ai/openclaw/app/voice/TalkSpeakClientTest.kt (added, +128/-0)
  • apps/ios/Config/Version.xcconfig (modified, +3/-3)
  • apps/ios/README.md (modified, +3/-3)
  • apps/ios/Sources/Gateway/GatewaySettingsStore.swift (modified, +20/-0)
  • apps/ios/Sources/Model/NodeAppModel+Canvas.swift (modified, +15/-2)
  • apps/ios/Sources/Model/NodeAppModel.swift (modified, +265/-20)
  • apps/ios/Sources/Screen/ScreenController.swift (modified, +45/-22)
  • apps/ios/Sources/Screen/ScreenWebView.swift (modified, +1/-6)
  • apps/ios/Sources/Settings/SettingsTab.swift (modified, +5/-0)
  • apps/ios/Tests/GatewayConnectionControllerTests.swift (modified, +46/-0)
  • apps/ios/Tests/GatewayConnectionSecurityTests.swift (modified, +19/-2)
  • apps/ios/Tests/NodeAppModelInvokeTests.swift (modified, +90/-0)
  • apps/ios/Tests/ScreenControllerTests.swift (modified, +19/-10)
  • apps/macos/Package.resolved (modified, +2/-2)
  • apps/macos/Sources/OpenClaw/AppState.swift (modified, +13/-0)
  • apps/macos/Sources/OpenClaw/Constants.swift (modified, +1/-0)
  • apps/macos/Sources/OpenClaw/GatewayConnection.swift (modified, +2/-0)
  • apps/macos/Sources/OpenClaw/HostEnvSecurityPolicy.generated.swift (modified, +4/-1)
  • apps/macos/Sources/OpenClaw/Resources/Info.plist (modified, +2/-2)
  • apps/macos/Sources/OpenClaw/TalkModeController.swift (modified, +6/-0)
  • apps/macos/Sources/OpenClaw/TalkModeRuntime.swift (modified, +6/-0)
  • apps/macos/Sources/OpenClaw/VoiceWakeRuntime.swift (modified, +18/-1)
  • apps/macos/Sources/OpenClaw/VoiceWakeSettings.swift (modified, +10/-0)
  • apps/macos/Sources/OpenClawDiscovery/WideAreaGatewayDiscovery.swift (modified, +2/-2)
  • apps/macos/Sources/OpenClawProtocol/GatewayModels.swift (modified, +86/-2)
  • apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift (modified, +97/-7)
  • apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayTLSPinning.swift (modified, +31/-0)
  • apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/tool-display.json (modified, +935/-78)
  • apps/shared/OpenClawKit/Sources/OpenClawKit/ToolDisplay.swift (modified, +1/-38)
  • apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift (modified, +86/-2)
  • apps/shared/OpenClawKit/Tests/OpenClawKitTests/GatewayNodeSessionTests.swift (modified, +223/-5)

Code Example

# embedded_run_agent_end event counts
2026-04-04: 195 runs, avg gap 487s, min gap 2s
2026-04-05: 473 runs, avg gap 89s,  min gap 0s

# Example run cluster from Android Auto session (all within 4 minutes):
12:56 pm - Gate Doorbell: person seen
12:57 pm - Android Auto connecting
12:57 pm - message access request appeared
12:58 pm - message access cleared/returned
12:59 pm - request cleared again
12:59 pm - request appeared again

# Error breakdown 2026-04-05 (0 successful runs):
322x  moonshot/kimi-k2.5 - account suspended (insufficient balance)
130x  network connection error
 16x  anthropic/claude-sonnet-4-6 - out of extra usage
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

Android companion notification events each trigger an independent agent run instead of being batched to the heartbeat interval, causing unbounded API consumption.

Steps to reproduce

Configure a heartbeat agent with a 30-minute interval Connect the Android companion app as a node Have a noisy notification stream on the phone (Android Auto connecting/disconnecting, Battery Saver toggling, camera doorbell alerts in quick succession) Observe agent run frequency in logs (embedded_run_agent_end events)

Expected behavior

Notification events forwarded by the Android companion should be buffered and surfaced as context at the next scheduled heartbeat, not trigger an immediate agent run per event.

Actual behavior

Each notification change fires an independent run. With a flapping notification source (e.g. Android Auto repeatedly connecting/disconnecting during a car trip), this produced runs every few seconds. Over 24 hours: 195 runs on 2026-04-04 (avg interval ~8 min), 473 runs on 2026-04-05 (avg interval ~89 sec). All runs failed as providers were sequentially exhausted.

OpenClaw version

2026.4.5 (3e72c03)

Operating system

macOS Darwin 25.2.0

Install method

npm global

Model

openai-codex/gpt-5.4

Provider / routing chain

openai-codex/gpt-5.4 → moonshot/kimi-k2.5 → anthropic/claude-sonnet-4-6

Additional provider/model setup details

No response

Logs, screenshots, and evidence

# embedded_run_agent_end event counts
2026-04-04: 195 runs, avg gap 487s, min gap 2s
2026-04-05: 473 runs, avg gap 89s,  min gap 0s

# Example run cluster from Android Auto session (all within 4 minutes):
12:56 pm - Gate Doorbell: person seen
12:57 pm - Android Auto connecting
12:57 pm - message access request appeared
12:58 pm - message access cleared/returned
12:59 pm - request cleared again
12:59 pm - request appeared again

# Error breakdown 2026-04-05 (0 successful runs):
322x  moonshot/kimi-k2.5 - account suspended (insufficient balance)
130x  network connection error
 16x  anthropic/claude-sonnet-4-6 - out of extra usage

Impact and severity

High. Exhausted OpenAI ChatGPT Plus weekly quota and ~$30 Anthropic usage credits within 24 hours. Agent was completely non-functional until quotas reset. No safeguard prevented the runaway consumption.

Additional information

A notification filter, debounce window, or per-interval run cap would mitigate this. The heartbeat timer itself is working correctly at 30 minutes — the issue is exclusively with event-driven runs from the Android companion.

extent analysis

TL;DR

Implement a notification filter, debounce window, or per-interval run cap to prevent excessive agent runs triggered by Android companion notification events.

Guidance

  • Verify that the heartbeat timer is working correctly at 30 minutes and the issue is indeed caused by event-driven runs from the Android companion.
  • Consider implementing a debounce window to batch notification events and prevent multiple agent runs within a short time frame.
  • Explore adding a per-interval run cap to limit the number of agent runs triggered by notification events within the heartbeat interval.
  • Review the notification filter to ensure it is correctly configured to ignore irrelevant events and prevent unnecessary agent runs.

Example

No code snippet is provided as the issue does not specify the exact implementation details.

Notes

The issue is specific to the Android companion notification events and does not affect the heartbeat timer itself. The proposed solutions aim to mitigate the excessive agent runs triggered by these events.

Recommendation

Apply a workaround by implementing a notification filter, debounce window, or per-interval run cap to prevent excessive agent runs and mitigate the issue until a permanent fix is available. This is recommended because it directly addresses the root cause of the problem and can help prevent further quota exhaustion and unnecessary usage credits consumption.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Notification events forwarded by the Android companion should be buffered and surfaced as context at the next scheduled heartbeat, not trigger an immediate agent run per event.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING