Streaming + chunking
O OpenClaw tem duas camadas separadas de streaming:- Streaming em blocos (canais): emite blocos concluídos à medida que o assistente escreve. Essas são mensagens normais do canal (não deltas de token).
- Streaming de prévia (Telegram/Discord/Slack): atualiza uma mensagem de prévia temporária durante a geração.
Streaming em blocos (mensagens de canal)
O streaming em blocos envia a saída do assistente em partes mais amplas à medida que ela fica disponível.text_delta/events: eventos de stream do modelo (podem ser esparsos para modelos sem streaming).chunker:EmbeddedBlockChunkeraplicando limites mínimo/máximo + preferência de quebra.channel send: mensagens reais de saída (respostas em blocos).
agents.defaults.blockStreamingDefault:"on"/"off"(padrão: desativado).- Substituições por canal:
*.blockStreaming(e variantes por conta) para forçar"on"/"off"por canal. agents.defaults.blockStreamingBreak:"text_end"ou"message_end".agents.defaults.blockStreamingChunk:{ minChars, maxChars, breakPreference? }.agents.defaults.blockStreamingCoalesce:{ minChars?, maxChars?, idleMs? }(mescla blocos transmitidos antes do envio).- Limite rígido do canal:
*.textChunkLimit(por exemplo,channels.whatsapp.textChunkLimit). - Modo de chunking do canal:
*.chunkMode(lengthé o padrão,newlinedivide em linhas em branco (limites de parágrafo) antes da divisão por tamanho). - Limite flexível do Discord:
channels.discord.maxLinesPerMessage(padrão: 17) divide respostas altas para evitar corte na UI.
text_end: transmite blocos assim que o chunker os emite; faz flush em cadatext_end.message_end: espera a mensagem do assistente terminar e então faz flush da saída armazenada.
message_end ainda usa o chunker se o texto em buffer exceder maxChars, então ele pode emitir vários chunks no final.
Algoritmo de chunking (limites baixo/alto)
O chunking em blocos é implementado porEmbeddedBlockChunker:
- Limite baixo: não emite até que o buffer >=
minChars(a menos que seja forçado). - Limite alto: prefere divisões antes de
maxChars; se forçado, divide emmaxChars. - Preferência de quebra:
paragraph→newline→sentence→whitespace→ quebra rígida. - Code fences: nunca divide dentro de fences; quando forçado em
maxChars, fecha + reabre a fence para manter o Markdown válido.
maxChars é limitado por textChunkLimit do canal, então você não pode exceder os limites por canal.
Coalescência (mesclar blocos transmitidos)
Quando o streaming em blocos está habilitado, o OpenClaw pode mesclar chunks de bloco consecutivos antes de enviá-los. Isso reduz o “spam de linha única” e ainda fornece saída progressiva.- A coalescência espera por intervalos de inatividade (
idleMs) antes de fazer flush. - Buffers são limitados por
maxCharse fazem flush se o excederem. minCharsimpede o envio de fragmentos minúsculos até que texto suficiente se acumule (o flush final sempre envia o texto restante).- O separador é derivado de
blockStreamingChunk.breakPreference(paragraph→\n\n,newline→\n,sentence→ espaço). - Há substituições por canal disponíveis via
*.blockStreamingCoalesce(incluindo configurações por conta). - O
minCharspadrão de coalescência é elevado para 1500 em Signal/Slack/Discord, a menos que seja substituído.
Ritmo mais humano entre blocos
Quando o streaming em blocos está habilitado, você pode adicionar uma pausa aleatória entre respostas em bloco (depois do primeiro bloco). Isso faz respostas em várias bolhas parecerem mais naturais.- Configuração:
agents.defaults.humanDelay(substituível por agente viaagents.list[].humanDelay). - Modos:
off(padrão),natural(800–2500ms),custom(minMs/maxMs). - Aplica-se apenas a respostas em bloco, não a respostas finais nem resumos de ferramentas.
”Transmitir chunks ou tudo”
Isso corresponde a:- Transmitir chunks:
blockStreamingDefault: "on"+blockStreamingBreak: "text_end"(emite durante a geração). Canais não Telegram também precisam de*.blockStreaming: true. - Transmitir tudo no final:
blockStreamingBreak: "message_end"(faz flush uma vez, possivelmente em vários chunks se for muito longo). - Sem streaming em blocos:
blockStreamingDefault: "off"(apenas resposta final).
*.blockStreaming seja explicitamente definido como true. Os canais podem transmitir uma prévia ao vivo
(channels.<channel>.streaming) sem respostas em bloco.
Lembrete de localização da configuração: os padrões blockStreaming* ficam em
agents.defaults, não na configuração raiz.
Modos de streaming de prévia
Chave canônica:channels.<channel>.streaming
Modos:
off: desabilita o streaming de prévia.partial: uma única prévia que é substituída pelo texto mais recente.block: atualizações da prévia em etapas com chunking/anexos.progress: prévia de progresso/status durante a geração, resposta final ao concluir.
Mapeamento por canal
| Canal | off | partial | block | progress |
|---|---|---|---|---|
| Telegram | ✅ | ✅ | ✅ | mapeia para partial |
| Discord | ✅ | ✅ | ✅ | mapeia para partial |
| Slack | ✅ | ✅ | ✅ | ✅ |
channels.slack.nativeStreamingalterna chamadas da API nativa de streaming do Slack quandostreaming=partial(padrão:true).
- Telegram:
streamMode+ booleanostreamingmigram automaticamente para o enumstreaming. - Discord:
streamMode+ booleanostreamingmigram automaticamente para o enumstreaming. - Slack:
streamModemigra automaticamente para o enumstreaming; o booleanostreamingmigra automaticamente paranativeStreaming.
Comportamento em runtime
Telegram:- Usa atualizações de prévia com
sendMessage+editMessageTextem DMs e grupos/tópicos. - O streaming de prévia é ignorado quando o streaming em blocos do Telegram está explicitamente habilitado (para evitar streaming duplo).
/reasoning streampode gravar raciocínio na prévia.
- Usa envio + edição de mensagens de prévia.
- O modo
blockusa chunking de rascunho (draftChunk). - O streaming de prévia é ignorado quando o streaming em blocos do Discord está explicitamente habilitado.
partialpode usar o streaming nativo do Slack (chat.startStream/append/stop) quando disponível.blockusa prévias de rascunho no estilo append.progressusa texto de prévia de status e depois a resposta final.