#Block streaming discord

1 messages · Page 1 of 1 (latest)

neon frost
#

I'm trying to get streaming for discord working correctly.

With streaming.mode=partial, it streams with editing but after output is done, it clears everything and send another message which is hard to read.

I tried to enable blockStreamingDefault, but the block is too large now making waiting too much.

Can we fine tune the block streaming so it outputs every paragraph (2 new lines)?

whole anchorBOT
dark raptorBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

eager patioBOT
#

Let me verify the docs path and the streaming config in the repo so I don’t guess.

#

I found the streaming docs, now I’m narrowing it to the actual config behavior in source so I can tell you whether paragraph-level chunking exists or not.

#

One last thing I’m checking is whether the old draftChunk form is still fine on Discord or if I should give you the newer streaming.preview.chunk / streaming.block.coalesce shape.

#

Yep, but not with streaming: "partial".

On Discord, partial is a preview message that gets edited while the model runs. It is not real per-paragraph reply chunking, so the “edit, then clear, then send final” behavior is the wrong mode for what you want.

If you want real block replies, roughly at blank-line / paragraph boundaries, use block streaming like this:

{
  agents: {
    defaults: {
      blockStreamingDefault: "on",
      blockStreamingBreak: "text_end",
      blockStreamingChunk: {
        minChars: 1, // raise if it gets too spammy
        maxChars: 600,
        breakPreference: "paragraph",
#
      },
    },
  },
  channels: {
    discord: {
      blockStreaming: true,
      chunkMode: "newline",
      blockStreamingCoalesce: {
        minChars: 1, // important on Discord
        idleMs: 0,
      },
      streaming: "off", // optional, blockStreaming already suppresses preview
    },
  },
}
#

Important bits:

  • chunkMode: "newline" = prefer \n\n boundaries
  • breakPreference: "paragraph" = prefer paragraph splits
  • low minChars and low blockStreamingCoalesce = flush sooner

So, yes, paragraph-ish block streaming is possible, but there is still no true token-delta channel streaming.

If you want, paste your current Discord/streaming config plus openclaw --version, and I’ll tune the exact values with you.

Docs:
https://docs.openclaw.ai/concepts/streaming
https://docs.openclaw.ai/channels/discord

neon frost
#

but is the “edit, then clear, then send final” behavior is correct? editing is fine, but the clear is making it janky. can we not clear the text and keep the edited text for partial streaming mode?

eager patioBOT
#

I’m checking the Discord preview finalization path in source, because if it explicitly clears the preview before sending the final, that’s either intentional behavior or a bug/regression, and I don’t want to hand-wave it.

#

I didn’t hit the Discord files on the first glob, so I’m locating the actual extension path now. Then I’ll answer whether the preview should finalize in place or whether you’ve found a legit bug.

#

Not exactly.

I checked the Discord path, and partial does try to keep the edited preview for the final text. It only does the clear + fresh send as a fallback.

That fallback happens when the final reply cannot safely be turned into a single final edit, for example if:

  • the final reply splits into multiple Discord chunks
  • it trips maxLinesPerMessage (default is 17, this one is easy to hit)
  • it includes media / error payloads / explicit reply tags
  • the final text ends up shorter than the preview text

So:

  • single normal text final → it should usually finalize in place
  • multi-chunk / mismatched final → it clears preview and sends normal reply

That means if you’re seeing clear + resend on a plain one-chunk text reply, I’d treat that as more of a bug/regression than “expected good UX”.

#

Two things to try:

  1. Increase channels.discord.maxLinesPerMessage
    If your final is over 17 lines, it won’t stay as one editable final.

  2. Disable preview tool progress
    channels.discord.streaming.preview.toolProgress = false
    That can reduce preview/final mismatches.

If you want, paste:

  • openclaw --version
  • your channels.discord config
  • whether the final replies are usually over 17 lines

and I’ll tell you exactly why it’s falling back.

Docs:

neon frost
#

block works. can discord output tool calls? compared to web ui, it just have semicolons "let me do this:" then empty, without tool calls

eager patioBOT
#

Nice, glad block mode is behaving.

I’m checking the exact Discord behavior for tool-call visibility so I can tell you whether this is supported, and if so whether it’s preview-only, verbose-only, or not surfaced yet.

#

Yes, but not like the web UI.

On Discord there are basically 2 tool-visibility paths:

  1. preview tool progress
    Short status text like “reading file”, “calling tool”, etc.
    This only shows while preview streaming is active.

  2. verbose tool bubbles
    If you turn on /verbose on, each tool call is sent as its own small metadata message.
    With /verbose full, you also get tool outputs after they finish.

Important bit for your case:

  • when block streaming is active, Discord skips preview tool-progress
  • so if you want to see actual tool calls in Discord while using block mode, use /verbose on
#

So I’d try:

/verbose on

or set:

{
  agents: {
    defaults: {
      verboseDefault: "on", // or "full"
    },
  },
}
#

A couple notes:

  • Discord does not currently mirror the web UI’s rich inline tool cards
  • tool calls show up as separate bubbles, not inline inside the streamed assistant message
  • the “let me do this:” with nothing after it is usually just the model narrating, while the real structured tool call is hidden because verbose is off

Docs:
https://docs.openclaw.ai/concepts/streaming
https://docs.openclaw.ai/tools/thinking

If you want, I can help you tune a “best Discord UX” combo for:

  • block streaming
  • paragraph chunking
  • visible tool calls
  • minimal spam
neon frost
#

yep, please

eager patioBOT
#

Yep, I’d use this as the balanced Discord setup:

{
  agents: {
    defaults: {
      blockStreamingDefault: "on",
      blockStreamingBreak: "text_end",
      blockStreamingChunk: {
        minChars: 120,
        maxChars: 500,
        breakPreference: "paragraph",
      },
      verboseDefault: "on", // tool call bubbles, but not full output spam
    },
  },
#
  channels: {
    discord: {
      streaming: "off", // optional, block streaming already suppresses preview
      blockStreaming: true,
      chunkMode: "newline",
      blockStreamingCoalesce: {
        minChars: 120,
        idleMs: 250,
      },
    },
  },
}

Why I like this combo:

#
  • paragraph-ish bubbles: chunkMode: "newline" + breakPreference: "paragraph"
  • faster than default: lower minChars
  • not too spammy: blockStreamingCoalesce prevents tiny bursts
  • tool calls visible: verboseDefault: "on"
  • minimal noise: on, not full

Quick tuning guide:

  • want faster / almost every paragraph
    lower both minChars values to 1 to 50

  • want less spam
    raise both to 200 to 300

  • want tool outputs too, not just tool names
    change verboseDefault to "full"

#

Main gotcha on Discord:
blockStreamingCoalesce is usually the thing making it feel “stuck”, so if it still waits too long, lower that first.

If you want, paste your current config and I can rewrite just the relevant section for you.

neon frost
#

explain blockStreamingCoalesce please?

eager patioBOT
#

Yep. Think of blockStreamingCoalesce as a debounce / merge layer on top of block streaming.

Mental model

  1. blockStreamingChunk decides where text can split

    • paragraph
    • newline
    • sentence
    • etc.
  2. blockStreamingCoalesce decides whether to send that split now, or wait and merge a bit more first

So:

  • chunking = “where are valid cut points?”
  • coalescing = “do I send this chunk immediately, or combine it with the next one?”
#

Fields

blockStreamingCoalesce: {
  minChars: 120,
  maxChars: 600,
  idleMs: 250,
}
  • minChars
    Don’t send tiny fragments yet. Keep buffering until at least this many chars.

  • maxChars
    If the buffer gets this big, flush it even if more text is coming.

  • idleMs

#

Wait this long after the last incoming chunk before sending.
If more text arrives before the timer ends, it gets merged in.

Why it exists

Without coalescing, block streaming can get spammy:

  • one short line
  • then another short line
  • then another

With coalescing, those can become one nicer bubble.

Example

If the model emits:

  • paragraph 1
#
  • 100ms later, paragraph 2
  • 100ms later, paragraph 3

and you have:

blockStreamingCoalesce: {
  minChars: 120,
  idleMs: 250,
}

then OpenClaw may send one combined message instead of 3 small ones.

On Discord specifically

This is the big gotcha: Discord has a fairly aggressive default coalesce floor, so block streaming can feel “stuck” unless you lower it.

#

If you want faster paragraph delivery, lower:

channels.discord.blockStreamingCoalesce.minChars
channels.discord.blockStreamingCoalesce.idleMs

Rule of thumb

  • want faster / more live feel
    lower minChars, lower idleMs

  • want less spam
    raise minChars, raise idleMs

Good starter values

#

More live

blockStreamingCoalesce: { minChars: 1, idleMs: 0 }

Balanced

blockStreamingCoalesce: { minChars: 120, idleMs: 250 }

Less spam

blockStreamingCoalesce: { minChars: 250, idleMs: 500 }

If you want, I can also explain how blockStreamingChunk and blockStreamingCoalesce interact together with a concrete paragraph-by-paragraph example.