Merged
Size
M
Change Breakdown
Bug Fix80%
Testing10%
Docs10%
#45737fix(cron): suppress NO_REPLY sentinel in direct delivery path

NO_REPLY sentinel leaks in cron direct delivery fixed

Cron jobs that use the announce delivery mode will no longer spam Telegram and other external channels with internal NO_REPLY system messages.

The NO_REPLY sentinel was slipping through to external channels during cron job executions. When a cron job's isolated session uses delivery: "announce", the direct delivery path failed to filter out the internal sentinel token before sending messages to Telegram or other external channels.

The issue affected a specific code path in the cron delivery system. The deliverViaDirect function constructs outbound payloads from synthesized text but never checked for the NO_REPLY sentinel before delivering. The parallel finalizeTextDelivery path already had this check in place.

Additionally, when silent replies were filtered out, the code returned early without updating delivery state flags. This caused a secondary bug: the heartbeat timer would fire a fallback delivery, resulting in duplicate announcements.

The fix adds the sentinel filter to the direct delivery path and ensures delivery state is properly marked so the job resolves as a silent success rather than triggering a retry. Silent cron replies are now handled consistently regardless of which internal delivery path is used.

View Original GitHub Description

Summary

  • Problem: When a cron job's isolated session uses delivery: "announce", the deliverViaDirect function in src/cron/isolated-agent/delivery-dispatch.ts fails to filter out the NO_REPLY sentinel token. This causes the internal sentinel to leak and be sent as an actual message to external channels (like Telegram). Furthermore, simply returning early without updating delivery state flags causes the heartbeat timer to fire a fallback delivery, resulting in a double-announce bug where the sentinel is still sent.
  • Why it matters: It degrades the user experience by spamming their chat channels with internal NO_REPLY system messages during automated cron executions.

Root Cause

The deliverViaDirect path constructs outbound payloads from synthesizedText or deliveryPayloads but never checks for the NO_REPLY sentinel before calling deliverOutboundPayloads. The parallel finalizeTextDelivery path already has this check and correctly returns delivered: true on NO_REPLY, but deliverViaDirect (used for structured/threaded deliveries) was missing it entirely.

What Changed

FileChangeWhy
src/cron/isolated-agent/delivery-dispatch.tsImport isSilentReplyText and filter rawPayloads before outbound deliveryPrevents NO_REPLY sentinel from leaking to external channels
src/cron/isolated-agent/delivery-dispatch.tsSet deliveryAttempted = true and delivered = true on filtered-empty early return, and return a proper status: "ok" resultPrevents shouldEnqueueCronMainSummary timer guard from firing a fallback enqueueSystemEvent; ensures resolveDeliveryStatus persists the job as a silent success — consistent with finalizeTextDelivery behavior
src/cron/isolated-agent/delivery-dispatch.double-announce.test.tsAdded 2 test cases (exact match + whitespace variant) with deliveryAttempted, delivered, and shouldEnqueueCronMainSummary assertionsCovers the regression path and timer-guard behavior, consistent with existing suppression tests in this file

What Did NOT Change

The finalizeTextDelivery path remains untouched as it already has the correct SILENT_REPLY_TOKEN check. The frontend defense-in-depth logic also remains unchanged.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Gateway / orchestration

Linked Issue/PR

Fixes #45705

AI-Assisted Contribution

  • AI Usage: This PR was developed with AI assistance.
  • Human Review: I have personally reviewed, designed, and fully understand all the code changes.
  • Testing: Fully tested locally with my OpenClaw instance. All 15 tests in delivery-dispatch.double-announce.test.ts pass.
  • Prompt Context: The AI agent analyzed the issue, traced the execution path of cron deliveries, identified the missing sentinel check in deliverViaDirect, and iteratively refined the fix based on automated reviews (greptile-apps, chatgpt-codex-connector) to properly handle delivery state flags (deliveryAttempted and delivered) to prevent timer fallbacks and ensure delivery status consistency.
© 2026 · via Gitpulse