> ## 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 y fragmentación

# Streaming + fragmentación

OpenClaw tiene dos capas de “streaming” separadas:

* **Streaming por bloques (canales):** emite **bloques** completados a medida que el asistente escribe. Estos son mensajes normales del canal (no deltas de tokens).
* **Streaming tipo token (solo Telegram):** actualiza una **burbuja de borrador** con texto parcial mientras se genera; el mensaje final se envía al final.

Hoy **no existe streaming real de tokens** hacia mensajes de canales externos. El streaming de borradores de Telegram es la única superficie de streaming parcial.

## Streaming por bloques (mensajes del canal)

El streaming por bloques envía la salida del asistente en fragmentos gruesos a medida que se vuelve disponible.

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

Leyenda:

* `text_delta/events`: eventos de stream del modelo (pueden ser escasos para modelos sin streaming).
* `chunker`: `EmbeddedBlockChunker` aplicando límites mínimo/máximo + preferencia de corte.
* `channel send`: mensajes salientes reales (respuestas por bloques).

**Controles:**

* `agents.defaults.blockStreamingDefault`: `"on"`/`"off"` (desactivado por defecto).
* Anulaciones por canal: `*.blockStreaming` (y variantes por cuenta) para forzar `"on"`/`"off"` por canal.
* `agents.defaults.blockStreamingBreak`: `"text_end"` o `"message_end"`.
* `agents.defaults.blockStreamingChunk`: `{ minChars, maxChars, breakPreference? }`.
* `agents.defaults.blockStreamingCoalesce`: `{ minChars?, maxChars?, idleMs? }` (fusionar bloques en streaming antes de enviar).
* Límite duro del canal: `*.textChunkLimit` (p. ej., `channels.whatsapp.textChunkLimit`).
* Modo de fragmentación del canal: `*.chunkMode` (`length` por defecto, `newline` divide en líneas en blanco (límites de párrafo) antes de fragmentar por longitud).
* Límite suave de Discord: `channels.discord.maxLinesPerMessage` (predeterminado 17) divide respuestas altas para evitar recortes en la UI.

**Semántica de límites:**

* `text_end`: emite bloques de stream tan pronto como el fragmentador emite; vacía en cada `text_end`.
* `message_end`: espera a que termine el mensaje del asistente y luego vacía la salida en búfer.

`message_end` sigue usando el fragmentador si el texto en búfer supera `maxChars`, por lo que puede emitir múltiples fragmentos al final.

## Algoritmo de fragmentación (límites bajo/alto)

La fragmentación por bloques se implementa mediante `EmbeddedBlockChunker`:

* **Límite bajo:** no emitir hasta que el búfer >= `minChars` (a menos que se fuerce).
* **Límite alto:** preferir cortes antes de `maxChars`; si se fuerza, cortar en `maxChars`.
* **Preferencia de corte:** `paragraph` → `newline` → `sentence` → `whitespace` → corte duro.
* **Vallas de código:** nunca dividir dentro de vallas; cuando se fuerza en `maxChars`, cerrar y reabrir la valla para mantener Markdown válido.

`maxChars` se limita al `textChunkLimit` del canal, por lo que no puede exceder los límites por canal.

## Coalescencia (fusionar bloques en streaming)

Cuando el streaming por bloques está habilitado, OpenClaw puede **fusionar fragmentos de bloques consecutivos**
antes de enviarlos. Esto reduce el “spam de una sola línea” mientras sigue proporcionando
salida progresiva.

* La coalescencia espera **intervalos de inactividad** (`idleMs`) antes de vaciar.
* Los búferes tienen un tope de `maxChars` y se vaciarán si lo superan.
* `minChars` evita que se envíen fragmentos diminutos hasta que se acumule suficiente texto
  (el vaciado final siempre envía el texto restante).
* El conector se deriva de `blockStreamingChunk.breakPreference`
  (`paragraph` → `\n\n`, `newline` → `\n`, `sentence` → espacio).
* Hay anulaciones por canal disponibles mediante `*.blockStreamingCoalesce` (incluidas configuraciones por cuenta).
* El `minChars` de coalescencia predeterminado se incrementa a 1500 para Signal/Slack/Discord a menos que se anule.

## Ritmo humano entre bloques

Cuando el streaming por bloques está habilitado, puede agregar una **pausa aleatoria** entre
respuestas por bloques (después del primer bloque). Esto hace que las respuestas con múltiples burbujas
se sientan más naturales.

* Configuración: `agents.defaults.humanDelay` (anular por agente mediante `agents.list[].humanDelay`).
* Modos: `off` (predeterminado), `natural` (800–2500 ms), `custom` (`minMs`/`maxMs`).
* Se aplica solo a **respuestas por bloques**, no a respuestas finales ni a resúmenes de herramientas.

## “Transmitir fragmentos o todo”

Esto se asigna a:

* **Transmitir fragmentos:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"` (emitir a medida que avanza). Los canales que no son Telegram también necesitan `*.blockStreaming: true`.
* **Transmitir todo al final:** `blockStreamingBreak: "message_end"` (vaciar una vez, posiblemente en múltiples fragmentos si es muy largo).
* **Sin streaming por bloques:** `blockStreamingDefault: "off"` (solo respuesta final).

**Nota del canal:** Para canales que no son Telegram, el streaming por bloques está **desactivado a menos que**
`*.blockStreaming` se establezca explícitamente en `true`. Telegram puede transmitir borradores
(`channels.telegram.streamMode`) sin respuestas por bloques.

Recordatorio de ubicación de configuración: los valores predeterminados de `blockStreaming*` viven bajo
`agents.defaults`, no en la configuración raíz.

## Streaming de borradores de Telegram (tipo token)

Telegram es el único canal con streaming de borradores:

* Usa la API de Bot `sendMessage` (primera actualización) + `editMessageText` (actualizaciones posteriores).
* `channels.telegram.streamMode: "partial" | "block" | "off"`.
  * `partial`: actualizaciones del borrador con el texto más reciente del stream.
  * `block`: actualizaciones del borrador en bloques fragmentados (mismas reglas del fragmentador).
  * `off`: sin streaming de borradores.
* Configuración de fragmentos del borrador (solo para `streamMode: "block"`): `channels.telegram.draftChunk` (valores predeterminados: `minChars: 200`, `maxChars: 800`).
* La transmisión en streaming de vista previa es independiente de la transmisión de bloques.
* Cuando el streaming de borradores está activo, OpenClaw desactiva el streaming por bloques para esa respuesta para evitar doble streaming.
* Los finales solo de texto se aplican editando el mensaje de vista previa en el mismo lugar.
* Los finales no textuales o complejos recurren a la entrega normal del mensaje final.
* `/reasoning stream` escribe el razonamiento en la burbuja de borrador (solo Telegram).

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

Leyenda:

* `preview message`: mensaje temporal de Telegram que se actualiza durante la generación.
* `final edit`: edición en el mismo lugar sobre el mismo mensaje de vista previa (solo texto).
