openclaw - ✅(Solved) Fix Prevent isolated cron announce jobs from repeatedly running when implicit `last` delivery has no route [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

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#78608Fetched 2026-05-07 03:34:43
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
2
Assignees
Timeline (top)
assigned ×1closed ×1commented ×1cross-referenced ×1

Isolated cron agentTurn jobs currently default to delivery.mode="announce", but some jobs can still be created/updated when their implicit delivery target is already known to be unroutable (delivery.channel=last with no previous route).

At runtime, those jobs still execute the agent turn and spend tokens before delivery fails with a delivery-target error. Repeated runs can create a noisy/wasteful failure loop and, in the worst case, destabilize the gateway.

Error Message

At runtime, those jobs still execute the agent turn and spend tokens before delivery fails with a delivery-target error. Repeated runs can create a noisy/wasteful failure loop and, in the worst case, destabilize the gateway.

  • last -> no route, will fail-closed: ${params.error}
  • status: "error"

Root Cause

  • wastes model tokens on runs that were never deliverable
  • repeats on every cron fire
  • creates confusing operator experience because preview already hints that the route is invalid
  • can contribute to failure loops / gateway instability when left running

Fix Action

Fix / Workaround

Relevant files:

  • src/cron/isolated-agent/delivery-target.ts
  • src/cron/isolated-agent/run.ts
  • src/cron/isolated-agent/delivery-dispatch.ts

PR fix notes

PR #78644: fix(cron): preflight implicit announce targets

Description (problem / solution / changelog)

Summary

  • Problem: isolated cron agentTurn jobs can default to announce delivery with implicit delivery.channel=last even when there is no previous route.
  • Why it matters: the job can spend model tokens before failing with a permanent delivery-target error, then repeat on later cron fires.
  • What changed: the isolated runner now fails unresolved implicit announce delivery before calling the agent executor, while preserving the existing delivery-target error classification and delivery trace.
  • What did NOT change (scope boundary): explicit delivery targets still run through the existing execution and delivery-dispatch path; add/update rejection and auto-disable policy are left for separate maintainer direction.

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

  • Closes #78608
  • This PR fixes a bug or regression

Root Cause

  • Root cause: isolated cron delivery target resolution happened before execution, but runCronIsolatedAgentTurn still called executeCronRun even when implicit announce delivery had already resolved to a permanent last route failure.
  • Missing detection / guardrail: no pre-execution guard for the known-unroutable implicit announce target shape.
  • Contributing context: delivery dispatch already reports errorKind: "delivery-target", but only after the expensive agent turn.

Regression Test Plan

  • Coverage level that should have caught this:
    • Seam / integration test
  • Target test or file: src/cron/isolated-agent/run.message-tool-policy.test.ts
  • Scenario the test should lock in: implicit announce delivery with channel: "last" and no resolved route returns a delivery-target error without starting the agent executor, dispatching delivery, or firing onExecutionStarted.
  • Why this is the smallest reliable guardrail: it exercises the isolated runner boundary where delivery resolution and model execution meet.

User-visible / Behavior Changes

Recurring isolated cron announce jobs that have no implicit previous delivery route now fail before model execution instead of spending tokens and failing after delivery dispatch.

Diagram

Before:
cron fire -> resolve last route failure -> run model -> delivery-target error

After:
cron fire -> resolve last route failure -> delivery-target error

Security Impact

  • 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

Repro + Verification

Environment

  • OS: macOS local maintainer worktree
  • Runtime/container: Node/pnpm repo test wrapper
  • Model/provider: mocked test harness
  • Integration/channel: cron isolated agent delivery
  • Relevant config: test fixtures only

Steps

  1. Run the focused cron regression suite.
  2. Run changed-surface checks locally.
  3. Attempt remote Crabbox/Blacksmith changed proof.

Expected

  • Unresolved implicit announce delivery fails before model execution.
  • Explicit delivery-target failure behavior continues through existing post-run dispatch tests.

Actual

  • Focused cron tests pass.
  • Local check:changed passed before rebase.
  • Remote Crabbox/Blacksmith proof was not available because Blacksmith was down.
  • Local test:changed hit unrelated workspace package-resolution failures in broader cron direct-delivery tests (openclaw/workspace package resolution), not assertions from this patch.

Evidence

  • Failing test/log before + passing after

Commands run:

pnpm test src/cron/isolated-agent/run.message-tool-policy.test.ts
pnpm exec oxfmt --check --threads=1 src/cron/isolated-agent/run.ts src/cron/isolated-agent/run.message-tool-policy.test.ts
pnpm check:changed
pnpm test:changed
pnpm test src/cron/isolated-agent/run.message-tool-policy.test.ts src/cron/isolated-agent/delivery-dispatch.double-announce.test.ts src/cron/delivery-preview.test.ts
git diff --check origin/main...HEAD

Latest post-rebase focused proof:

Test Files  3 passed (3)
Tests  82 passed (82)

Human Verification

  • Verified scenarios: implicit unresolved announce delivery fails before agent execution; existing explicit unresolved delivery behavior still has test coverage; delivery preview and dispatch suites still pass.
  • Edge cases checked: explicit bad target test remains on the existing execution path; bare delivery.mode="none" behavior remains covered by existing tests.
  • What I did not verify: live cron execution against a real configured channel, due to Blacksmith outage and this being covered by the focused runner seam.

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

Risks and Mitigations

  • Risk: a job with an explicit but invalid target still spends tokens before dispatch reports the delivery-target error.
    • Mitigation: this PR intentionally limits scope to the issue's implicit last footgun; explicit-target validation policy can be handled separately.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/cron/isolated-agent/run.message-tool-policy.test.ts (modified, +57/-7)
  • src/cron/isolated-agent/run.ts (modified, +46/-0)

Code Example

{ mode: "announce" }
RAW_BUFFERClick to expand / collapse

Summary

Isolated cron agentTurn jobs currently default to delivery.mode="announce", but some jobs can still be created/updated when their implicit delivery target is already known to be unroutable (delivery.channel=last with no previous route).

At runtime, those jobs still execute the agent turn and spend tokens before delivery fails with a delivery-target error. Repeated runs can create a noisy/wasteful failure loop and, in the worst case, destabilize the gateway.

Repro shape

The problematic shape is:

  • sessionTarget: "isolated"
  • payload.kind: "agentTurn"
  • delivery.mode: "announce"
  • no explicit delivery.channel / delivery.to
  • no usable previous route for implicit last

What current code appears to do

Default delivery still creates the footgun

resolveInitialCronDelivery(...) defaults isolated agentTurn jobs to:

{ mode: "announce" }

So isolated jobs opt into announce-by-default even without an explicit target.

Relevant file:

  • src/cron/service/initial-delivery.ts

Preview already knows it will fail closed

resolveCronDeliveryPreview(...) already surfaces this condition with messages like:

  • last -> no route, will fail-closed
  • last -> no route, will fail-closed: ${params.error}

Relevant file:

  • src/cron/delivery-preview.ts

Runtime still spends tokens before failing delivery

In the isolated cron run path, the agent turn can still run before delivery target failure is surfaced.

Current failure looks like:

  • Channel is required when delivery.channel=last has no previous channel.

Relevant files:

  • src/cron/isolated-agent/delivery-target.ts
  • src/cron/isolated-agent/run.ts
  • src/cron/isolated-agent/delivery-dispatch.ts

And delivery-target failure can elevate to:

  • status: "error"
  • errorKind: "delivery-target"

Why this hurts

  • wastes model tokens on runs that were never deliverable
  • repeats on every cron fire
  • creates confusing operator experience because preview already hints that the route is invalid
  • can contribute to failure loops / gateway instability when left running

Suggested direction

Any of these would help; ideally more than one:

  1. Reject unroutable implicit announce jobs at add/update time

    • If preview resolves to last -> no route, will fail-closed, require explicit delivery.channel or an existing route.
  2. Preflight delivery target before model execution

    • For isolated cron runs, if delivery is requested and target resolution is permanently impossible, skip the agent turn and fail early.
  3. Auto-disable after repeated permanent delivery-target failures

    • Treat this as a safety rail so a bad cron job cannot burn tokens forever.

Expected outcome

Cron jobs that are known to have no valid delivery route should fail earlier and more safely, instead of repeatedly running the model and only failing after the expensive part is already done.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING