스트리밍 + 청킹
OpenClaw 에는 서로 분리된 두 가지 ‘스트리밍’ 레이어가 있습니다:- 블록 스트리밍 (채널): 어시스턴트가 작성하는 동안 완료된 블록을 방출합니다. 이는 토큰 델타가 아닌 일반 채널 메시지입니다.
- 토큰 유사 스트리밍 (Telegram 전용): 생성 중에 부분 텍스트로 초안 버블을 업데이트하며, 최종 메시지는 끝에 전송됩니다.
블록 스트리밍 (채널 메시지)
블록 스트리밍은 사용 가능해지는 대로 어시스턴트 출력을 거친 청크로 전송합니다.text_delta/events: 모델 스트림 이벤트 (스트리밍을 지원하지 않는 모델의 경우 드물 수 있음).chunker:EmbeddedBlockChunker가 최소/최대 경계와 분할 선호도를 적용합니다.channel send: 실제 발신 메시지 (블록 응답).
agents.defaults.blockStreamingDefault:"on"/"off"(기본값 꺼짐).- 채널 재정의: 채널별로
"on"/"off"을 강제하기 위한*.blockStreaming(계정별 변형 포함). agents.defaults.blockStreamingBreak:"text_end"또는"message_end".agents.defaults.blockStreamingChunk:{ minChars, maxChars, breakPreference? }.agents.defaults.blockStreamingCoalesce:{ minChars?, maxChars?, idleMs? }(전송 전에 스트리밍된 블록 병합).- 채널 하드 캡:
*.textChunkLimit(예:channels.whatsapp.textChunkLimit). - 채널 청크 모드:
*.chunkMode(length기본값,newline은 길이 기반 청킹 전에 빈 줄(문단 경계)에서 분할). - Discord 소프트 캡:
channels.discord.maxLinesPerMessage(기본값 17) 은 UI 클리핑을 피하기 위해 긴 응답을 분할합니다.
text_end: 청커가 방출하는 즉시 스트림 블록을 전송하며, 각text_end마다 플러시합니다.message_end: 어시스턴트 메시지가 끝날 때까지 기다린 다음 버퍼링된 출력을 플러시합니다.
message_end 도 버퍼링된 텍스트가 maxChars 를 초과하면 청커를 사용하므로, 끝에서 여러 청크를 방출할 수 있습니다.
청킹 알고리즘 (저/고 경계)
블록 청킹은EmbeddedBlockChunker 에 의해 구현됩니다:
- 하한: 버퍼가
minChars이상이 될 때까지 방출하지 않습니다 (강제되지 않는 한). - 상한:
maxChars이전에서 분할을 선호하며, 강제 시maxChars에서 분할합니다. - 분할 선호도:
paragraph→newline→sentence→whitespace→ 하드 분할. - 코드 펜스: 펜스 내부에서는 절대 분할하지 않으며,
maxChars에서 강제될 경우 Markdown 유효성을 유지하기 위해 펜스를 닫았다가 다시 엽니다.
maxChars 는 채널 textChunkLimit 에 의해 클램프되므로, 채널별 캡을 초과할 수 없습니다.
병합 (스트리밍된 블록 병합)
블록 스트리밍이 활성화되면, OpenClaw 는 전송 전에 연속된 블록 청크를 병합할 수 있습니다. 이는 점진적 출력을 유지하면서도 ‘단일 줄 스팸’을 줄입니다.- 병합은 플러시 전에 유휴 간격 (
idleMs) 을 기다립니다. - 버퍼는
maxChars로 제한되며, 이를 초과하면 플러시됩니다. minChars는 충분한 텍스트가 누적될 때까지 작은 조각의 전송을 방지합니다 (최종 플러시는 항상 남은 텍스트를 전송합니다).- 조인 문자열은
blockStreamingChunk.breakPreference에서 파생됩니다 (paragraph→\n\n,newline→\n,sentence→ 공백). - 채널 재정의는
*.blockStreamingCoalesce(계정별 설정 포함) 을 통해 사용할 수 있습니다. - 기본 병합
minChars은 재정의되지 않는 한 Signal/Slack/Discord 에 대해 1500 으로 상향됩니다.
블록 간 사람 같은 페이싱
블록 스트리밍이 활성화되면, 블록 응답 사이(첫 번째 블록 이후)에 무작위 지연을 추가할 수 있습니다. 이는 여러 버블로 구성된 응답이 더 자연스럽게 느껴지도록 합니다.- 설정:
agents.defaults.humanDelay(에이전트별로agents.list[].humanDelay를 통해 재정의). - 모드:
off(기본값),natural(800–2500ms),custom(minMs/maxMs). - 블록 응답에만 적용되며, 최종 응답이나 도구 요약에는 적용되지 않습니다.
‘청크를 스트림할지 전체를 보낼지’
이는 다음에 매핑됩니다:- 청크 스트림:
blockStreamingDefault: "on"+blockStreamingBreak: "text_end"(진행하면서 방출). Telegram 이 아닌 채널도*.blockStreaming: true이 필요합니다. - 끝에서 모두 스트림:
blockStreamingBreak: "message_end"(한 번 플러시하며, 매우 길 경우 여러 청크일 수 있음). - 블록 스트리밍 없음:
blockStreamingDefault: "off"(최종 응답만).
*.blockStreaming 가 명시적으로 true 로 설정되지 않는 한 블록 스트리밍은 꺼짐입니다. Telegram 은 블록 응답 없이도 초안을 스트림할 수 있습니다
(channels.telegram.streamMode).
설정 위치 알림: blockStreaming* 기본값은 루트 설정이 아니라
agents.defaults 아래에 있습니다.
Telegram 초안 스트리밍 (토큰 유사)
Telegram 은 초안 스트리밍을 지원하는 유일한 채널입니다:- Bot API
sendMessage(첫 업데이트) +editMessageText(이후 업데이트)를 사용합니다. channels.telegram.streamMode: "partial" | "block" | "off".partial: 최신 스트림 텍스트로 초안을 업데이트합니다.block: 청킹된 블록으로 초안을 업데이트합니다 (동일한 청커 규칙).off: 초안 스트리밍 없음.
- 초안 청크 설정 (
streamMode: "block"전용):channels.telegram.draftChunk(기본값:minChars: 200,maxChars: 800). - 미리보기 스트리밍은 블록 스트리밍과 별개입니다.
- 초안 스트리밍이 활성화되면, OpenClaw 는 이중 스트리밍을 피하기 위해 해당 응답에 대해 블록 스트리밍을 비활성화합니다.
- 텍스트 전용 final은 미리보기 메시지를 해당 위치에서 직접 수정하여 적용됩니다.
- 텍스트가 아니거나 복잡한 final은 일반적인 최종 메시지 전송 방식으로 대체됩니다.
/reasoning stream는 추론을 초안 버블에 기록합니다 (Telegram 전용).
preview message: 생성 중에 업데이트되는 임시 Telegram 메시지.final edit: 동일한 미리보기 메시지에서 수행되는 직접 수정(텍스트 전용).