Skip to content

runEmbeddedPiAgent (cron path) does not pass allowEmptyAssistantReplyAsSilent for delivery.mode === "none" jobs #79069

Description

@ChrisBot2026

runEmbeddedPiAgent (cron path) does not pass allowEmptyAssistantReplyAsSilent for delivery.mode === "none" jobs

Bug type

Reliability / silent-turn handling regression in cron path.

Summary

Cron jobs configured with delivery.mode === "none" — i.e. jobs whose successful path is intentionally silent — produce false [agent/embedded] incomplete turn detected: stopReason=stop payloads=0 warnings whenever the assistant ends a turn with an empty final message. The cron call site of runEmbeddedPiAgent({...}) does not pass allowEmptyAssistantReplyAsSilent to the runtime, so the runtime correctly classifies the empty-final-payload outcome as an incomplete turn even though the job was configured to permit silent success.

This is structurally the same seam #74409 fixed for the chat-reply (get-reply.ts) path: allowEmptyAssistantReplyAsSilent is computed correctly elsewhere but not threaded through to a sibling call site. #74409 dropped the isGroupChat && short-circuit for direct chats; this report covers a different sibling — the embedded cron-execution path.

Version

Observed on openclaw 2026.5.4. Inspected sandbox tarballs of 2026.5.5, 2026.5.6, and 2026.5.7-beta.1 confirm the same seam is unchanged in all three: runEmbeddedPiAgent({...}) in the cron execution path does not include allowEmptyAssistantReplyAsSilent in its argument object.

Code seam (current bundled output, 2026.5.4)

/dist/run-executor.runtime-CmvK87iL.js (in 2026.5.6 the bundle is run-executor.runtime-iZ2r0NUv.js; in 2026.5.7-beta.1 the bundle is run-executor.runtime-iZ2r0NUv.js also — byte-identical). The relevant runEmbeddedPiAgent call site:

const result = await runEmbeddedPiAgent({
    /* ... */
    abortSignal: params.abortSignal,
    onExecutionStarted: params.onExecutionStarted,
    bootstrapPromptWarningSignaturesSeen,
    bootstrapPromptWarningSignature
    // <-- no allowEmptyAssistantReplyAsSilent here
});

Repro shape

A minimal cron agentTurn job whose successful path produces an empty final assistant message — for example:

{
  "kind": "agentTurn",
  "message": "Run the package detector skill (silent on no detection):\n...\nReply silently if nothing detected.",
  "model": "openai-codex/gpt-5.5",
  "timeoutSeconds": 60
}

with the cron entry's delivery.mode === "none" (silent delivery). When the model finishes with stopReason: "stop" and an empty final assistant message:

[agent/embedded] incomplete turn detected: runId=<redacted> sessionId=<redacted> stopReason=stop payloads=0 — surfacing error to user

The job was configured to be silent on success, but the runtime treats the empty-final-payload outcome as an incomplete turn because allowEmptyAssistantReplyAsSilent was never passed.

Expected behavior

When the cron job's delivery.mode === "none", the call to runEmbeddedPiAgent should pass allowEmptyAssistantReplyAsSilent: true, so that an empty final assistant payload is correctly classified as a silent success rather than an incomplete turn.

Actual behavior

The cron call site never sets allowEmptyAssistantReplyAsSilent. The runtime defaults it to false, and every silent cron job with an empty final assistant message produces a false-positive "incomplete turn detected" warning surfaced to the user.

Proposed fix (minimal)

Add a single line to the runEmbeddedPiAgent({...}) argument object in the cron execution path. The condition mirrors how delivery mode is resolved elsewhere in the same path — accept either the resolved or the raw job-level delivery mode, since both forms appear depending on which cron entry seam invoked the runner:

 const result = await runEmbeddedPiAgent({
     /* ... */
     abortSignal: params.abortSignal,
     onExecutionStarted: params.onExecutionStarted,
     bootstrapPromptWarningSignaturesSeen,
-    bootstrapPromptWarningSignature
+    bootstrapPromptWarningSignature,
+    allowEmptyAssistantReplyAsSilent: params.resolvedDelivery?.mode === "none" || params.job?.delivery?.mode === "none"
 });

(The TypeScript source seam is in the cron execution path corresponding to bundled run-executor.runtime-*.js — the same call site that already threads bootstrapPromptWarningSignature.)

Validation locally

The patched form has been running locally on 2026.5.4 since 2026-05-04. After the fix:

  • silent cron jobs (delivery.mode === "none") with empty final assistant messages no longer produce [agent/embedded] incomplete turn detected: ... payloads=0 warnings
  • visible cron jobs (delivery.mode !== "none") are unaffected (the runtime keeps its existing incomplete-turn detection for those)

Related work

Severity

Low individual impact (warning, not a hard failure), but high noise: every silent cron job with an empty assistant final message produces a user-facing warning, training operators to ignore real incomplete-turn signals.

Why I think this should be a separate tracked bug

#74409 closed the chat-channel sibling but didn't sweep the cron sibling. The cron-path fix is a one-line addition at a different call site and has a distinct test surface (no chat-channel coverage applies).

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions