Streaming + Chunking

OpenClaw hat zwei separate Streaming-Ebenen:

  • Block-Streaming (Kanaele): sendet abgeschlossene Bloecke, waehrend der Assistent schreibt. Das sind normale Kanalnachrichten (keine Token-Deltas).
  • Vorschau-Streaming (Telegram/Discord/Slack): aktualisiert eine temporaere Vorschau-Nachricht waehrend der Generierung.

Es gibt kein echtes Token-Delta-Streaming zu Kanalnachrichten. Vorschau-Streaming ist nachrichtenbasiert (Senden + Bearbeiten/Anhaengen).

Block-Streaming (Kanalnachrichten)

Block-Streaming sendet Assistenten-Output in groben Stuecken, sobald sie verfuegbar sind.

Model output
  └─ text_delta/events
       ├─ (blockStreamingBreak=text_end)
       │    └─ chunker emits blocks as buffer grows
       └─ (blockStreamingBreak=message_end)
            └─ chunker flushes at message_end
                   └─ channel send (block replies)

Legende:

  • text_delta/events: Modell-Stream-Events (koennen bei nicht-streamenden Modellen duenn sein).
  • chunker: EmbeddedBlockChunker mit min/max-Grenzen + Break-Praeferenz.
  • channel send: tatsaechliche ausgehende Nachrichten (Block-Antworten).

Steuerung:

  • agents.defaults.blockStreamingDefault: "on"/"off" (Standard off).
  • Kanal-Overrides: *.blockStreaming (und pro-Account-Varianten) um "on"/"off" pro Kanal zu erzwingen.
  • agents.defaults.blockStreamingBreak: "text_end" oder "message_end".
  • agents.defaults.blockStreamingChunk: { minChars, maxChars, breakPreference? }.
  • agents.defaults.blockStreamingCoalesce: { minChars?, maxChars?, idleMs? } (gestreamte Bloecke vor dem Senden zusammenfuehren).
  • Kanal-Hartlimit: *.textChunkLimit (z.B. channels.whatsapp.textChunkLimit).
  • Kanal-Chunk-Modus: *.chunkMode (length Standard, newline teilt an Leerzeilen (Absatzgrenzen) vor dem Laengen-Chunking).
  • Discord Soft-Cap: channels.discord.maxLinesPerMessage (Standard 17) teilt hohe Antworten auf, um UI-Clipping zu vermeiden.

Grenz-Semantik:

  • text_end: Bloecke streamen, sobald der Chunker sie ausgibt; bei jedem text_end flushen.
  • message_end: warten, bis die Assistenten-Nachricht fertig ist, dann gepufferten Output flushen.

message_end nutzt trotzdem den Chunker, wenn der gepufferte Text maxChars ueberschreitet — es koennen also mehrere Chunks am Ende ausgegeben werden.

Chunking-Algorithmus (Low/High Bounds)

Block-Chunking wird von EmbeddedBlockChunker implementiert:

  • Low Bound: nicht ausgeben, bis Buffer >= minChars (es sei denn, erzwungen).
  • High Bound: bevorzugt Splits vor maxChars; wenn erzwungen, bei maxChars teilen.
  • Break-Praeferenz: paragraph -> newline -> sentence -> whitespace -> harter Umbruch.
  • Code-Fences: nie innerhalb von Fences teilen; wenn bei maxChars erzwungen, Fence schliessen + wieder oeffnen, um das Markdown gueltig zu halten.

maxChars wird auf das Kanal-textChunkLimit gedeckelt, sodass pro-Kanal-Caps nicht ueberschritten werden koennen.

Coalescing (gestreamte Bloecke zusammenfuehren)

Wenn Block-Streaming aktiviert ist, kann OpenClaw aufeinanderfolgende Block-Chunks zusammenfuehren, bevor sie gesendet werden. Das reduziert “Einzelzeilen-Spam” und liefert trotzdem progressiven Output.

  • Coalescing wartet auf Idle-Luecken (idleMs) vor dem Flushen.
  • Buffer sind durch maxChars begrenzt und werden geflusht, wenn sie ueberschritten werden.
  • minChars verhindert, dass winzige Fragmente gesendet werden, bis genug Text angesammelt ist (der finale Flush sendet immer den restlichen Text).
  • Der Joiner wird aus blockStreamingChunk.breakPreference abgeleitet (paragraph -> \n\n, newline -> \n, sentence -> Leerzeichen).
  • Kanal-Overrides sind per *.blockStreamingCoalesce verfuegbar (einschliesslich pro-Account-Configs).
  • Standard-Coalesce-minChars wird fuer Signal/Slack/Discord auf 1500 angehoben, sofern nicht ueberschrieben.

Menschliches Pacing zwischen Bloecken

Wenn Block-Streaming aktiviert ist, kannst du eine zufaellige Pause zwischen Block-Antworten einfuegen (nach dem ersten Block). Das laesst Multi-Bubble-Antworten natuerlicher wirken.

  • Config: agents.defaults.humanDelay (pro Agent ueberschreiben per agents.list[].humanDelay).
  • Modi: off (Standard), natural (800-2500ms), custom (minMs/maxMs).
  • Gilt nur fuer Block-Antworten, nicht fuer finale Antworten oder Tool-Zusammenfassungen.

”Chunks streamen oder alles”

Das entspricht:

  • Chunks streamen: blockStreamingDefault: "on" + blockStreamingBreak: "text_end" (laufend ausgeben). Nicht-Telegram-Kanaele brauchen zusaetzlich *.blockStreaming: true.
  • Alles am Ende streamen: blockStreamingBreak: "message_end" (einmal flushen, moeglicherweise mehrere Chunks bei langem Text).
  • Kein Block-Streaming: blockStreamingDefault: "off" (nur finale Antwort).

Kanal-Hinweis: Block-Streaming ist aus, sofern nicht *.blockStreaming explizit auf true gesetzt ist. Kanaele koennen eine Live-Vorschau streamen (channels.<channel>.streaming) ohne Block-Antworten.

Config-Erinnerung: die blockStreaming*-Standards leben unter agents.defaults, nicht im Root-Config.

Vorschau-Streaming-Modi

Kanonischer Key: channels.<channel>.streaming

Modi:

  • off: Vorschau-Streaming deaktivieren.
  • partial: eine einzelne Vorschau, die mit dem neuesten Text ersetzt wird.
  • block: Vorschau-Updates in gestuften/angehaengten Schritten.
  • progress: Fortschritts-/Status-Vorschau waehrend der Generierung, finale Antwort bei Abschluss.

Kanal-Zuordnung

Kanaloffpartialblockprogress
Telegramwird zu partial
Discordwird zu partial
Slack

Nur Slack:

  • channels.slack.nativeStreaming schaltet native Slack-Streaming-API-Aufrufe ein, wenn streaming=partial (Standard: true).

Legacy-Key-Migration:

  • Telegram: streamMode + boolesches streaming migrieren automatisch zum streaming-Enum.
  • Discord: streamMode + boolesches streaming migrieren automatisch zum streaming-Enum.
  • Slack: streamMode migriert automatisch zum streaming-Enum; boolesches streaming migriert automatisch zu nativeStreaming.

Laufzeitverhalten

Telegram:

  • Nutzt sendMessage + editMessageText Vorschau-Updates fuer DMs und Gruppen/Themen.
  • Vorschau-Streaming wird uebersprungen, wenn Telegram-Block-Streaming explizit aktiviert ist (um Doppel-Streaming zu vermeiden).
  • /reasoning stream kann Reasoning in die Vorschau schreiben.

Discord:

  • Nutzt Senden + Bearbeiten fuer Vorschau-Nachrichten.
  • block-Modus nutzt Draft-Chunking (draftChunk).
  • Vorschau-Streaming wird uebersprungen, wenn Discord-Block-Streaming explizit aktiviert ist.

Slack:

  • partial kann natives Slack-Streaming (chat.startStream/append/stop) nutzen, wenn verfuegbar.
  • block nutzt Append-Style-Draft-Vorschauen.
  • progress nutzt Status-Vorschautext, dann finale Antwort.