Streaming + découpage en morceaux
OpenClaw possède deux couches de streaming distinctes :- Streaming par blocs (canaux) : émet des blocs terminés pendant que l’assistant écrit. Ce sont des messages de canal normaux (pas des deltas de jetons).
- Streaming d’aperçu (Telegram/Discord/Slack) : met à jour un message d’aperçu temporaire pendant la génération.
Streaming par blocs (messages de canal)
Le streaming par blocs envoie la sortie de l’assistant en gros morceaux à mesure qu’elle devient disponible.text_delta/events: événements de flux du modèle (peuvent être rares pour les modèles sans streaming).chunker:EmbeddedBlockChunkerappliquant des limites min/max + la préférence de coupure.channel send: messages sortants réels (réponses par blocs).
agents.defaults.blockStreamingDefault:"on"/"off"(désactivé par défaut).- Surcharges de canal :
*.blockStreaming(et variantes par compte) pour forcer"on"/"off"par canal. agents.defaults.blockStreamingBreak:"text_end"ou"message_end".agents.defaults.blockStreamingChunk:{ minChars, maxChars, breakPreference? }.agents.defaults.blockStreamingCoalesce:{ minChars?, maxChars?, idleMs? }(fusionne les blocs streamés avant l’envoi).- Limite stricte du canal :
*.textChunkLimit(par ex.channels.whatsapp.textChunkLimit). - Mode de découpage du canal :
*.chunkMode(lengthpar défaut,newlinecoupe sur les lignes vides (limites de paragraphe) avant le découpage par longueur). - Limite souple Discord :
channels.discord.maxLinesPerMessage(17 par défaut) découpe les réponses longues pour éviter le rognage dans l’interface.
text_end: diffuse les blocs dès que le chunker en émet ; vide le tampon à chaquetext_end.message_end: attend que le message de l’assistant soit terminé, puis vide la sortie mise en tampon.
message_end utilise quand même le chunker si le texte mis en tampon dépasse maxChars, donc il peut émettre plusieurs morceaux à la fin.
Algorithme de découpage en morceaux (limites basse/haute)
Le découpage par blocs est implémenté parEmbeddedBlockChunker :
- Limite basse : n’émet rien tant que le tampon n’a pas atteint
minChars(sauf si forcé). - Limite haute : préfère des coupures avant
maxChars; si forcé, coupe àmaxChars. - Préférence de coupure :
paragraph→newline→sentence→whitespace→ coupure forcée. - Blocs de code délimités : ne jamais couper à l’intérieur ; en cas de coupure forcée à
maxChars, ferme puis rouvre le bloc pour conserver un Markdown valide.
maxChars est plafonné à la valeur textChunkLimit du canal, donc vous ne pouvez pas dépasser les limites propres à chaque canal.
Coalescence (fusion des blocs streamés)
Quand le streaming par blocs est activé, OpenClaw peut fusionner des morceaux de blocs consécutifs avant de les envoyer. Cela réduit le « spam de lignes uniques » tout en fournissant une sortie progressive.- La coalescence attend des périodes d’inactivité (
idleMs) avant de vider le tampon. - Les tampons sont plafonnés par
maxCharset seront vidés s’ils le dépassent. minCharsempêche l’envoi de fragments minuscules tant qu’assez de texte ne s’est pas accumulé (le vidage final envoie toujours le texte restant).- Le séparateur est dérivé de
blockStreamingChunk.breakPreference(paragraph→\n\n,newline→\n,sentence→ espace). - Des surcharges par canal sont disponibles via
*.blockStreamingCoalesce(y compris dans les configs par compte). - La valeur par défaut de
minCharspour la coalescence est portée à 1500 pour Signal/Slack/Discord sauf surcharge.
Rythme plus humain entre les blocs
Quand le streaming par blocs est activé, vous pouvez ajouter une pause aléatoire entre les réponses par blocs (après le premier bloc). Cela donne aux réponses en plusieurs bulles une impression plus naturelle.- Config :
agents.defaults.humanDelay(surcharge par agent viaagents.list[].humanDelay). - Modes :
off(par défaut),natural(800–2500ms),custom(minMs/maxMs). - S’applique uniquement aux réponses par blocs, pas aux réponses finales ni aux résumés d’outils.
« Stream les morceaux ou tout »
Cela correspond à :- Stream les morceaux :
blockStreamingDefault: "on"+blockStreamingBreak: "text_end"(émet au fil de l’eau). Les canaux autres que Telegram ont aussi besoin de*.blockStreaming: true. - Tout streamer à la fin :
blockStreamingBreak: "message_end"(vide une fois, éventuellement en plusieurs morceaux si c’est très long). - Aucun streaming par blocs :
blockStreamingDefault: "off"(réponse finale uniquement).
*.blockStreaming est explicitement défini sur true. Les canaux peuvent diffuser un aperçu en direct
(channels.<channel>.streaming) sans réponses par blocs.
Rappel sur l’emplacement de la config : les valeurs par défaut blockStreaming* se trouvent sous
agents.defaults, pas à la racine de la config.
Modes de streaming d’aperçu
Clé canonique :channels.<channel>.streaming
Modes :
off: désactive le streaming d’aperçu.partial: aperçu unique remplacé par le texte le plus récent.block: mises à jour d’aperçu par étapes découpées/ajoutées.progress: aperçu d’avancement/statut pendant la génération, réponse finale à la fin.
Mappage par canal
| Canal | off | partial | block | progress |
|---|---|---|---|---|
| Telegram | ✅ | ✅ | ✅ | correspond à partial |
| Discord | ✅ | ✅ | ✅ | correspond à partial |
| Slack | ✅ | ✅ | ✅ | ✅ |
channels.slack.streaming.nativeTransportactive/désactive les appels à l’API de streaming native de Slack lorsquechannels.slack.streaming.mode="partial"(par défaut :true).- Le streaming natif Slack et l’état des fils d’assistant Slack nécessitent une cible de fil de réponse ; les DM de niveau supérieur n’affichent pas cet aperçu de type fil.
- Telegram :
streamMode+ booléenstreamingsont automatiquement migrés vers l’énumérationstreaming. - Discord :
streamMode+ booléenstreamingsont automatiquement migrés vers l’énumérationstreaming. - Slack :
streamModemigre automatiquement versstreaming.mode; le booléenstreamingmigre automatiquement versstreaming.modeplusstreaming.nativeTransport; l’anciennativeStreamingmigre automatiquement versstreaming.nativeTransport.
Comportement à l’exécution
Telegram :- Utilise les mises à jour d’aperçu
sendMessage+editMessageTextdans les DM et les groupes/sujets. - Le streaming d’aperçu est ignoré lorsque le streaming par blocs Telegram est explicitement activé (pour éviter un double streaming).
/reasoning streampeut écrire le raisonnement dans l’aperçu.
- Utilise l’envoi + la modification de messages d’aperçu.
- Le mode
blockutilise le découpage de brouillon (draftChunk). - Le streaming d’aperçu est ignoré lorsque le streaming par blocs Discord est explicitement activé.
partialpeut utiliser le streaming natif de Slack (chat.startStream/append/stop) lorsqu’il est disponible.blockutilise des aperçus de brouillon de style ajout.progressutilise un texte d’aperçu de statut, puis la réponse finale.