Skip to content

fix(cron): prevent duplicate delivery for isolated jobs with announce mode#15739

Merged
steipete merged 2 commits intoopenclaw:mainfrom
widingmarcus-cyber:fix/cron-duplicate-delivery-15692
Feb 13, 2026
Merged

fix(cron): prevent duplicate delivery for isolated jobs with announce mode#15739
steipete merged 2 commits intoopenclaw:mainfrom
widingmarcus-cyber:fix/cron-duplicate-delivery-15692

Conversation

@widingmarcus-cyber
Copy link
Contributor

@widingmarcus-cyber widingmarcus-cyber commented Feb 13, 2026

fix(cron): prevent duplicate delivery for isolated jobs with announce mode

Fixes #15692

Problem

When an isolated cron job runs with delivery.mode=announce, the output is delivered twice to the target channel with different content:

  1. The isolated agent run delivers via deliverOutboundPayloads (structured content) or runSubagentAnnounceFlow (text-based announce) → Message fix: add @lid format support and allowFrom wildcard handling #1
  2. executeJobCore in timer.ts unconditionally calls enqueueSystemEvent + requestHeartbeatNow, which wakes the main agent. The main agent processes the system event, generates its own response, and delivers it → Message Login fails with 'WebSocket Error (socket hang up)' ECONNRESET #2

Result: two messages with different content for a single cron run.

Root Cause

In src/cron/service/timer.ts, executeJobCore() posts a summary to the main agent session after every isolated job, regardless of whether the isolated run already delivered its output:

// Before fix:
if (summaryText && deliveryPlan.requested) {
  state.deps.enqueueSystemEvent(label, { agentId: job.agentId });
  if (job.wakeMode === "now") {
    state.deps.requestHeartbeatNow({ reason: \`cron:\${job.id}\` });
  }
}

Fix

Add a delivered flag to RunCronAgentTurnResult that tracks whether the isolated run already delivered its output. Skip enqueueSystemEvent + requestHeartbeatNow when delivered === true.

Changed files: src/cron/isolated-agent/run.ts, src/cron/service/state.ts, src/cron/service/timer.ts

Testing

  • All 128 existing cron tests pass
  • Lint + format pass (oxlint + oxfmt)
  • TypeScript type-check passes

Greptile Overview

Greptile Summary

This PR adds a delivered flag to the isolated cron job execution result so the cron timer can avoid enqueueing a summary system event (and waking the main agent) when the isolated run has already delivered output to the target channel (via outbound payload delivery or the announce flow).

Concretely:

  • src/cron/isolated-agent/run.ts now tracks whether delivery happened and returns it.
  • src/cron/service/state.ts extends the runIsolatedAgentJob dep return type to include delivered.
  • src/cron/service/timer.ts gates enqueueSystemEvent + requestHeartbeatNow behind !res.delivered to prevent duplicate channel messages for delivery.mode=announce isolated runs.

Overall, the change is narrowly scoped to the cron isolated-run → main-session handoff logic and matches the stated root cause in #15692.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk.
  • Changes are small, localized, and type-propagated: delivered is only used to suppress a main-session wakeup when isolated delivery already occurred. The new flag is set only on successful delivery paths (outbound payload delivery or announce success) and is otherwise false/undefined, preserving prior behavior. No other call sites are affected beyond the cron service dependency return type and the single gating condition in the timer.
  • No files require special attention

Last reviewed commit: a355115

(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!

Context used:

  • Context from dashboard - CLAUDE.md (source)
  • Context from dashboard - AGENTS.md (source)

@steipete steipete self-assigned this Feb 13, 2026
widingmarcus-cyber and others added 2 commits February 13, 2026 23:45
… mode

When an isolated cron job delivers its output via deliverOutboundPayloads
or the subagent announce flow, the finish handler in executeJobCore
unconditionally posts a summary to the main agent session and wakes it
via requestHeartbeatNow. The main agent then generates a second response
that is also delivered to the target channel, resulting in duplicate
messages with different content.

Add a `delivered` flag to RunCronAgentTurnResult that is set to true
when the isolated run successfully delivers its output. In executeJobCore,
skip the enqueueSystemEvent + requestHeartbeatNow call when the flag is
set, preventing the main agent from waking up and double-posting.

Fixes openclaw#15692
@steipete steipete force-pushed the fix/cron-duplicate-delivery-15692 branch from a355115 to 38e2e2f Compare February 13, 2026 22:49
@steipete steipete merged commit 45a2cd5 into openclaw:main Feb 13, 2026
9 checks passed
@steipete
Copy link
Contributor

Landed via temp rebase onto main.

  • Gate: pnpm check && pnpm build && pnpm test
  • Land commit: 38e2e2f
  • Merge commit: 45a2cd5

Thanks @widingmarcus-cyber!

steipete added a commit to azade-c/openclaw that referenced this pull request Feb 14, 2026
GwonHyeok pushed a commit to learners-superpumped/openclaw that referenced this pull request Feb 15, 2026
cloud-neutral pushed a commit to cloud-neutral-toolkit/openclawbot.svc.plus that referenced this pull request Feb 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: cron isolated agentTurn with delivery.mode=announce posts duplicate messages with different content (extra agent run triggered)

2 participants

Comments