Streaming + chunking
OpenClaw ma dwie oddzielne warstwy przesyłania strumieniowego:- Strumieniowanie blokowe (kanały): emituje ukończone bloki podczas pisania przez asystenta. Są to zwykłe wiadomości kanału (nie delty tokenów).
- Strumieniowanie podglądu (Telegram/Discord/Slack): aktualizuje tymczasową wiadomość podglądu podczas generowania.
Strumieniowanie blokowe (wiadomości kanału)
Strumieniowanie blokowe wysyła dane wyjściowe asystenta w większych fragmentach, gdy stają się dostępne.text_delta/events: zdarzenia strumienia modelu (mogą być rzadkie dla modeli bez strumieniowania).chunker:EmbeddedBlockChunkerstosujący dolne/górne granice + preferencję podziału.channel send: rzeczywiste wiadomości wychodzące (odpowiedzi blokowe).
agents.defaults.blockStreamingDefault:"on"/"off"(domyślnie wyłączone).- Nadpisania kanałów:
*.blockStreaming(oraz warianty per konto), aby wymusić"on"/"off"dla kanału. agents.defaults.blockStreamingBreak:"text_end"lub"message_end".agents.defaults.blockStreamingChunk:{ minChars, maxChars, breakPreference? }.agents.defaults.blockStreamingCoalesce:{ minChars?, maxChars?, idleMs? }(scala strumieniowane bloki przed wysłaniem).- Twardy limit kanału:
*.textChunkLimit(np.channels.whatsapp.textChunkLimit). - Tryb dzielenia kanału na fragmenty:
*.chunkMode(lengthdomyślnie,newlinedzieli po pustych liniach (granice akapitów) przed dzieleniem według długości). - Miękki limit Discord:
channels.discord.maxLinesPerMessage(domyślnie 17) dzieli wysokie odpowiedzi, aby uniknąć obcięcia w UI.
text_end: przesyłaj bloki, gdy tylko chunker je wyemituje; opróżniaj przy każdymtext_end.message_end: czekaj, aż wiadomość asystenta się zakończy, a następnie opróżnij zbuforowane dane wyjściowe.
message_end nadal używa chunkera, jeśli zbuforowany tekst przekracza maxChars, więc może wyemitować wiele fragmentów na końcu.
Algorytm dzielenia na fragmenty (dolne/górne granice)
Dzielenie bloków na fragmenty jest implementowane przezEmbeddedBlockChunker:
- Dolna granica: nie emituj, dopóki bufor nie osiągnie >=
minChars(chyba że wymuszono). - Górna granica: preferuj podziały przed
maxChars; jeśli wymuszono, podziel przymaxChars. - Preferencja podziału:
paragraph→newline→sentence→whitespace→ twardy podział. - Bloki kodu: nigdy nie dziel wewnątrz bloków; przy wymuszeniu przy
maxCharszamknij i otwórz ponownie blok, aby zachować poprawność Markdown.
maxChars jest ograniczane do textChunkLimit kanału, więc nie można przekroczyć limitów per kanał.
Scalanie (łączenie strumieniowanych bloków)
Gdy strumieniowanie blokowe jest włączone, OpenClaw może scalać kolejne fragmenty bloków przed ich wysłaniem. Zmniejsza to „spam pojedynczymi liniami”, a jednocześnie nadal zapewnia progresywne dane wyjściowe.- Scalanie czeka na przerwy bezczynności (
idleMs) przed opróżnieniem. - Bufory są ograniczane przez
maxCharsi zostaną opróżnione po przekroczeniu tego limitu. minCharszapobiega wysyłaniu małych fragmentów, dopóki nie zbierze się wystarczająco dużo tekstu (końcowe opróżnienie zawsze wysyła pozostały tekst).- Łącznik jest wyprowadzany z
blockStreamingChunk.breakPreference(paragraph→\n\n,newline→\n,sentence→ spacja). - Nadpisania kanałów są dostępne przez
*.blockStreamingCoalesce(w tym konfiguracje per konto). - Domyślne
minCharsdla scalania jest zwiększane do 1500 dla Signal/Slack/Discord, chyba że zostanie nadpisane.
Bardziej naturalne tempo między blokami
Gdy strumieniowanie blokowe jest włączone, możesz dodać losową pauzę między odpowiedziami blokowymi (po pierwszym bloku). Dzięki temu odpowiedzi wielobąbelkowe wydają się bardziej naturalne.- Konfiguracja:
agents.defaults.humanDelay(nadpisanie per agent przezagents.list[].humanDelay). - Tryby:
off(domyślnie),natural(800–2500ms),custom(minMs/maxMs). - Dotyczy tylko odpowiedzi blokowych, a nie odpowiedzi końcowych ani podsumowań narzędzi.
„Przesyłaj fragmenty strumieniowo albo wszystko”
Mapuje się to następująco:- Przesyłaj fragmenty strumieniowo:
blockStreamingDefault: "on"+blockStreamingBreak: "text_end"(emituj na bieżąco). Kanały inne niż Telegram wymagają także*.blockStreaming: true. - Przesyłaj wszystko na końcu:
blockStreamingBreak: "message_end"(opróżnij raz, ewentualnie w wielu fragmentach, jeśli odpowiedź jest bardzo długa). - Brak strumieniowania blokowego:
blockStreamingDefault: "off"(tylko odpowiedź końcowa).
*.blockStreaming jest jawnie ustawione na true. Kanały mogą przesyłać na żywo podgląd
(channels.<channel>.streaming) bez odpowiedzi blokowych.
Przypomnienie o lokalizacji konfiguracji: ustawienia domyślne blockStreaming* znajdują się w
agents.defaults, a nie w głównej konfiguracji.
Tryby strumieniowania podglądu
Klucz kanoniczny:channels.<channel>.streaming
Tryby:
off: wyłącz strumieniowanie podglądu.partial: pojedynczy podgląd zastępowany najnowszym tekstem.block: aktualizacje podglądu w krokach dzielonych na fragmenty/dopisywanych.progress: podgląd postępu/stanu podczas generowania, końcowa odpowiedź po zakończeniu.
Mapowanie kanałów
| Kanał | off | partial | block | progress |
|---|---|---|---|---|
| Telegram | ✅ | ✅ | ✅ | mapuje się na partial |
| Discord | ✅ | ✅ | ✅ | mapuje się na partial |
| Slack | ✅ | ✅ | ✅ | ✅ |
channels.slack.nativeStreamingprzełącza natywne wywołania API strumieniowania Slack, gdystreaming=partial(domyślnie:true).
- Telegram:
streamMode+ logicznestreamingsą automatycznie migrowane do enumstreaming. - Discord:
streamMode+ logicznestreamingsą automatycznie migrowane do enumstreaming. - Slack:
streamModejest automatycznie migrowane do enumstreaming; logicznestreamingjest automatycznie migrowane donativeStreaming.
Zachowanie w czasie działania
Telegram:- Używa aktualizacji podglądu
sendMessage+editMessageTextw wiadomościach prywatnych i grupach/tematach. - Strumieniowanie podglądu jest pomijane, gdy strumieniowanie blokowe Telegram jest jawnie włączone (aby uniknąć podwójnego strumieniowania).
/reasoning streammoże zapisywać rozumowanie do podglądu.
- Używa wysyłania + edycji wiadomości podglądu.
- Tryb
blockużywa dzielenia szkicu na fragmenty (draftChunk). - Strumieniowanie podglądu jest pomijane, gdy strumieniowanie blokowe Discord jest jawnie włączone.
partialmoże używać natywnego strumieniowania Slack (chat.startStream/append/stop), gdy jest dostępne.blockużywa podglądów szkicu w stylu dopisywania.progressużywa tekstu podglądu stanu, a następnie końcowej odpowiedzi.