openclaw - ✅(Solved) Fix Text payload silently dropped when agent responds with text + MEDIA: URL (block streaming disabled) [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#61535Fetched 2026-04-08 02:57:38
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×1

Root Cause

In agent-runner (createBlockReplyDeliveryHandler), when blockStreamingEnabled is false and the payload contains media, text is explicitly stripped before calling onBlockReply:

} else if (blockHasMedia) {
    params.directlySentBlockKeys.add(createBlockReplyContentKey(blockPayload)); // key includes text
    await params.onBlockReply({
        ...blockPayload,
        text: void 0   // ← text dropped here
    });
}

The content key is computed from blockPayload (which includes the text), so the final delivery pass correctly identifies this payload as already sent and skips it. The text is lost at both stages.

Fix Action

Fix / Workaround

This is compounded by the fact that disableBlockStreaming: true is hardcoded in at least one gateway handler, meaning blockStreamingDefault: "on" in agent config cannot override it. Even users who discover and set blockStreamingDefault: "on" as a workaround will find it has no effect.

PR fix notes

PR #61545: fix(reply): preserve text for direct media blocks

Description (problem / solution / changelog)

Summary

  • preserve text when directly delivering media-bearing block replies while block streaming is disabled
  • keep direct-send dedupe intact by recording the same full payload content key before final payload suppression
  • add a regression covering text + media direct delivery through runReplyAgent with block streaming disabled

Testing

  • attempted: pnpm test -- src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts -t "preserves text for direct media delivery when block streaming is disabled"
  • local installs/tests were previously blocked by npm registry DNS failures in this environment (EAI_AGAIN registry.npmjs.org)

Closes #61535

Changed files

  • docs/automation/cron-jobs.md (modified, +1/-0)
  • docs/cli/cron.md (modified, +2/-0)
  • src/auto-reply/reply.block-streaming.test.ts (modified, +34/-0)
  • src/auto-reply/reply/agent-runner-execution.ts (modified, +2/-0)
  • src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts (modified, +59/-0)
  • src/auto-reply/reply/agent-runner.ts (modified, +1/-0)
  • src/auto-reply/reply/reply-delivery.ts (modified, +51/-7)
  • src/cron/isolated-agent.delivers-response-has-heartbeat-ok-but-includes.test.ts (modified, +45/-0)
  • src/cron/isolated-agent.direct-delivery-forum-topics.test.ts (modified, +71/-0)
  • src/cron/isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true.test.ts (modified, +18/-0)
  • src/cron/isolated-agent/delivery-dispatch.ts (modified, +41/-4)

Code Example

here's something interesting

   MEDIA:https://example.com/photo.jpg

---

} else if (blockHasMedia) {
    params.directlySentBlockKeys.add(createBlockReplyContentKey(blockPayload)); // key includes text
    await params.onBlockReply({
        ...blockPayload,
        text: void 0   // ← text dropped here
    });
}

---

} else if (blockHasMedia) {
    params.directlySentBlockKeys.add(createBlockReplyContentKey(blockPayload));
    await params.onBlockReply(blockPayload);
}
RAW_BUFFERClick to expand / collapse

Describe the bug

When an agent response contains both text and a MEDIA: URL, and block streaming is disabled (the default — blockStreamingDefault is "off" unless explicitly set), the text is silently discarded. Only the image is delivered to the channel; the accompanying text is never sent.

To Reproduce

  1. Leave blockStreamingDefault at its default ("off")
  2. Have an agent produce a response like:
    here's something interesting
    
    MEDIA:https://example.com/photo.jpg
  3. The channel receives only the image. The text is never delivered — not as a caption, not as a preceding message, not at all.

Expected behavior

Text accompanying a MEDIA: URL should be delivered — either as the image caption or as a preceding/following message, depending on what the channel supports.

Root cause

In agent-runner (createBlockReplyDeliveryHandler), when blockStreamingEnabled is false and the payload contains media, text is explicitly stripped before calling onBlockReply:

} else if (blockHasMedia) {
    params.directlySentBlockKeys.add(createBlockReplyContentKey(blockPayload)); // key includes text
    await params.onBlockReply({
        ...blockPayload,
        text: void 0   // ← text dropped here
    });
}

The content key is computed from blockPayload (which includes the text), so the final delivery pass correctly identifies this payload as already sent and skips it. The text is lost at both stages.

Proposed fix

Remove the text: void 0 override — pass blockPayload directly:

} else if (blockHasMedia) {
    params.directlySentBlockKeys.add(createBlockReplyContentKey(blockPayload));
    await params.onBlockReply(blockPayload);
}

The content key logic is unchanged, so deduplication still works correctly. Channels that support captions receive the text as the image caption. Channels that don't support inline captions (e.g., QQBot) already handle this gracefully via sendTextAfterMedia, which sends text as a follow-up if text?.trim() is non-empty.

Additional context

This is compounded by the fact that disableBlockStreaming: true is hardcoded in at least one gateway handler, meaning blockStreamingDefault: "on" in agent config cannot override it. Even users who discover and set blockStreamingDefault: "on" as a workaround will find it has no effect.

extent analysis

TL;DR

Remove the text: void 0 override in the createBlockReplyDeliveryHandler function to prevent text from being stripped when blockStreamingDefault is set to "off".

Guidance

  • Identify the createBlockReplyDeliveryHandler function in the agent-runner and locate the text: void 0 override.
  • Remove the override and pass blockPayload directly to params.onBlockReply to preserve the accompanying text.
  • Verify that the text is delivered as expected, either as an image caption or as a preceding/following message, depending on the channel's capabilities.
  • Be aware that setting blockStreamingDefault: "on" may not override hardcoded disableBlockStreaming: true values in certain gateway handlers.

Example

} else if (blockHasMedia) {
    params.directlySentBlockKeys.add(createBlockReplyContentKey(blockPayload));
    await params.onBlockReply(blockPayload); // Pass blockPayload directly
}

Notes

This fix assumes that the createBlockReplyContentKey logic remains unchanged, ensuring deduplication still works correctly. Additionally, channels that do not support inline captions will handle the text as a follow-up message via sendTextAfterMedia.

Recommendation

Apply the proposed fix by removing the text: void 0 override, as it directly addresses the issue of text being stripped when blockStreamingDefault is set to "off".

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

Text accompanying a MEDIA: URL should be delivered — either as the image caption or as a preceding/following message, depending on what the channel supports.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Text payload silently dropped when agent responds with text + MEDIA: URL (block streaming disabled) [1 pull requests, 1 participants]