openclaw - 💡(How to fix) Fix Bug: buffered block dispatcher splits messages at ~4000 chars, breaking non-chunked channels [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#59097Fetched 2026-04-08 02:28:41
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Participants

Fix Action

Fix / Workaround

The dispatchReplyWithBufferedBlockDispatcher splits LLM replies into chunks at DEFAULT_CHUNK_LIMIT (4000 chars) and calls deliver() multiple times per turn. Channels that concatenate these chunks (like atticus-channel, which joins with \n\n) end up with spurious line breaks mid-sentence at ~4000-char boundaries.

OpenClaw core (src/auto-reply/reply/provider-dispatcher.ts):

  • DEFAULT_CHUNK_LIMIT = 4000
  • chunkMarkdownTextWithMode() splits text at paragraph/newline/length boundaries
  • deliver() called once per chunk

The atticus-channel plugin should use dispatchReplyWithDispatcher (non-buffered, single deliver() call) instead of dispatchReplyWithBufferedBlockDispatcher. The atticus channel has no message length limit — it delivers via SSE as a single message.

Code Example

this.buffer += `${this.buffer ? "\n\n" : ""}${t}`
RAW_BUFFERClick to expand / collapse

The dispatchReplyWithBufferedBlockDispatcher splits LLM replies into chunks at DEFAULT_CHUNK_LIMIT (4000 chars) and calls deliver() multiple times per turn. Channels that concatenate these chunks (like atticus-channel, which joins with \n\n) end up with spurious line breaks mid-sentence at ~4000-char boundaries.

This is correct for channels with message length limits (Telegram, WhatsApp, Discord) but wrong for channels that deliver the full reply as a single message via SSE.

Where it happens

OpenClaw core (src/auto-reply/reply/provider-dispatcher.ts):

  • DEFAULT_CHUNK_LIMIT = 4000
  • chunkMarkdownTextWithMode() splits text at paragraph/newline/length boundaries
  • deliver() called once per chunk

atticus-channel plugin (delivery.ts):

this.buffer += `${this.buffer ? "\n\n" : ""}${t}`

Buffers all chunks, sends one SSE message at finalize(), but \n\n between chunks creates visible paragraph breaks that were not in the original text.

Symptoms

  • Paragraph breaks appearing mid-sentence every ~4000 chars
  • Bold markdown (**...**) broken when chunk boundary falls inside emphasis span (CommonMark cannot span paragraphs, so raw ** is displayed)

Recommended fix

The atticus-channel plugin should use dispatchReplyWithDispatcher (non-buffered, single deliver() call) instead of dispatchReplyWithBufferedBlockDispatcher. The atticus channel has no message length limit — it delivers via SSE as a single message.

extent analysis

TL;DR

The atticus-channel plugin should use dispatchReplyWithDispatcher instead of dispatchReplyWithBufferedBlockDispatcher to prevent spurious line breaks and broken markdown.

Guidance

  • Identify the dispatchReplyWithBufferedBlockDispatcher call in the atticus-channel plugin and replace it with dispatchReplyWithDispatcher to ensure a single deliver() call per turn.
  • Verify that the finalize() method in the atticus-channel plugin sends a single SSE message without introducing paragraph breaks.
  • Check the chunkMarkdownTextWithMode() function in OpenClaw core to ensure it does not split text at unwanted boundaries.
  • Test the fix with various input texts, including those with markdown emphasis spans, to ensure that paragraph breaks and markdown rendering are correct.

Example

// Replace this line in delivery.ts:
// dispatchReplyWithBufferedBlockDispatcher(reply);
// With this:
dispatchReplyWithDispatcher(reply);

Notes

This fix assumes that the atticus-channel plugin has no message length limits and delivers replies via SSE as a single message. If other channels have similar requirements, they may also need to use dispatchReplyWithDispatcher.

Recommendation

Apply workaround: Replace dispatchReplyWithBufferedBlockDispatcher with dispatchReplyWithDispatcher in the atticus-channel plugin, as it has no message length limits and delivers replies via SSE as a single message.

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