> ## Documentation Index
> Fetch the complete documentation index at: https://openclaw.veiseule.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Streaming et découpage

# Streaming + découpage

OpenClaw dispose de deux couches de « streaming » distinctes :

* **Streaming par blocs (canaux) :** émet des **blocs** terminés au fur et à mesure que l’assistant écrit. Ce sont des messages de canal normaux (pas des deltas de tokens).
* **Streaming pseudo‑token (Telegram uniquement) :** met à jour une **bulle de brouillon** avec du texte partiel pendant la génération ; le message final est envoyé à la fin.

Il n’existe **pas de véritable streaming de tokens** vers des messages de canal externes aujourd’hui. Le streaming de brouillon Telegram est la seule surface de streaming partiel.

## Streaming par blocs (messages de canal)

Le streaming par blocs envoie la sortie de l’assistant en morceaux grossiers dès qu’ils sont disponibles.

```
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)
```

Légende :

* `text_delta/events` : événements de flux du modèle (peuvent être rares pour les modèles non streaming).
* `chunker` : `EmbeddedBlockChunker` appliquant des bornes min/max + préférence de coupure.
* `channel send` : messages sortants réels (réponses par blocs).

**Contrôles :**

* `agents.defaults.blockStreamingDefault` : `"on"`/`"off"` (désactivé par défaut).
* Surcharges par 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? }` (fusionner les blocs streamés avant l’envoi).
* Plafond strict par canal : `*.textChunkLimit` (p. ex., `channels.whatsapp.textChunkLimit`).
* Mode de découpage par canal : `*.chunkMode` (`length` par défaut, `newline` découpe sur les lignes vides (frontières de paragraphe) avant le découpage par longueur).
* Plafond souple Discord : `channels.discord.maxLinesPerMessage` (17 par défaut) découpe les réponses très longues pour éviter le rognage de l’UI.

**Sémantique des frontières :**

* `text_end` : streamer les blocs dès que le découpeur émet ; vidanger à chaque `text_end`.
* `message_end` : attendre la fin du message de l’assistant, puis vidanger la sortie mise en tampon.

`message_end` utilise toujours le découpeur si le texte tamponné dépasse `maxChars`, ce qui peut émettre plusieurs morceaux à la fin.

## Algorithme de découpage (bornes basse/haute)

Le découpage par blocs est implémenté par `EmbeddedBlockChunker` :

* **Borne basse :** ne pas émettre tant que le tampon \< `minChars` (sauf forçage).
* **Borne haute :** préférer des coupures avant `maxChars` ; si forcé, couper à `maxChars`.
* **Préférence de coupure :** `paragraph` → `newline` → `sentence` → `whitespace` → coupure dure.
* **Blocs de code :** ne jamais couper à l’intérieur ; si forcé à `maxChars`, fermer puis rouvrir le bloc pour conserver un Markdown valide.

`maxChars` est borné par le `textChunkLimit` du canal, vous ne pouvez donc pas dépasser les plafonds par canal.

## Coalescence (fusion des blocs streamés)

Lorsque le streaming par blocs est activé, OpenClaw peut **fusionner des morceaux de blocs consécutifs**
avant leur envoi. Cela réduit le « spam ligne par ligne » tout en fournissant
une sortie progressive.

* La coalescence attend des **intervalles d’inactivité** (`idleMs`) avant de vidanger.
* Les tampons sont plafonnés par `maxChars` et seront vidangés s’ils le dépassent.
* `minChars` empêche l’envoi de fragments minuscules tant que suffisamment de texte ne s’accumule pas
  (la vidange finale 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 des configurations par compte).
* La valeur par défaut de coalescence `minChars` est portée à 1500 pour Signal/Slack/Discord sauf surcharge.

## Rythme « humain » entre les blocs

Lorsque 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 rend les réponses multi‑bulles
plus naturelles.

* Configuration : `agents.defaults.humanDelay` (surcharge par agent via `agents.list[].humanDelay`).
* Modes : `off` (par défaut), `natural` (800–2500 ms), `custom` (`minMs`/`maxMs`).
* S’applique uniquement aux **réponses par blocs**, pas aux réponses finales ni aux résumés d’outils.

## « Streamer les morceaux ou tout à la fin »

Ceci correspond à :

* **Streamer les morceaux :** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"` (émettre au fil de l’eau). Les canaux non Telegram nécessitent aussi `*.blockStreaming: true`.
* **Tout streamer à la fin :** `blockStreamingBreak: "message_end"` (vidange unique, éventuellement en plusieurs morceaux si très long).
* **Pas de streaming par blocs :** `blockStreamingDefault: "off"` (réponse finale uniquement).

**Note par canal :** pour les canaux non Telegram, le streaming par blocs est **désactivé sauf si**
`*.blockStreaming` est explicitement défini sur `true`. Telegram peut streamer des brouillons
(`channels.telegram.streamMode`) sans réponses par blocs.

Rappel d’emplacement de configuration : les valeurs par défaut `blockStreaming*` se trouvent sous
`agents.defaults`, et non à la racine de la configuration.

## Streaming de brouillon Telegram (pseudo‑token)

Telegram est le seul canal avec streaming de brouillon :

* Utilise l’API Bot `sendMessage` (première mise à jour) + `editMessageText` (mises à jour suivantes).
* `channels.telegram.streamMode: "partial" | "block" | "off"`.
  * `partial` : mises à jour du brouillon avec le dernier texte streamé.
  * `block` : mises à jour du brouillon par blocs découpés (mêmes règles de découpage).
  * `off` : pas de streaming de brouillon.
* Configuration du découpage du brouillon (uniquement pour `streamMode: "block"`) : `channels.telegram.draftChunk` (valeurs par défaut : `minChars: 200`, `maxChars: 800`).
* Le streaming d’aperçu est distinct du streaming par blocs.
* Lorsque le streaming de brouillon est actif, OpenClaw désactive le streaming par blocs pour cette réponse afin d’éviter un double streaming.
* Les messages finaux contenant uniquement du texte sont appliqués en modifiant le message d’aperçu sur place.
* Les messages finaux non textuels ou complexes reviennent à un envoi de message final normal.
* `/reasoning stream` écrit le raisonnement dans la bulle de brouillon (Telegram uniquement).

```
Telegram (private + topics)
  └─ sendMessageDraft (draft bubble)
       ├─ streamMode=partial → update latest text
       └─ streamMode=block   → chunker updates draft
  └─ final reply → normal message
```

Légende :

* `preview message` : message Telegram temporaire mis à jour pendant la génération.
* `final edit` : modification sur place du même message d’aperçu (texte uniquement).
