스트리밍 + 청킹
OpenClaw에는 두 개의 별도 "스트리밍" 레이어가 있습니다.
- 블록 스트리밍(채널): 보조자가 작성하는 대로 완료된 블록을 내보냅니다. 이는 일반 채널 메시지입니다(토큰 델타가 아님).
- 토큰형 스트리밍(텔레그램만 해당): 생성하는 동안 부분 텍스트로 초안 풍선을 업데이트합니다. 마지막에 최종 메시지가 전송됩니다.
현재 외부 채널 메시지에 대한 실제 토큰 스트리밍은 없습니다. 텔레그램 초안 스트리밍은 유일한 부분 스트림 표면입니다.
스트리밍 차단(채널 메시지)
블록 스트리밍은 보조 출력이 사용 가능해지면 대략적인 청크로 전송합니다.
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)범례:
text_delta/events: 모델 스트림 이벤트(비스트리밍 모델의 경우 희소할 수 있음).chunker:EmbeddedBlockChunker최소/최대 경계 + 중단 기본 설정을 적용합니다.channel send: 실제 아웃바운드 메시지(답장 차단)입니다.
컨트롤:
agents.defaults.blockStreamingDefault:"on"/"off"(기본값은 꺼짐).- 채널 재정의:
*.blockStreaming(및 계정별 변형)는 채널당"on"/"off"를 강제합니다. 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에서 강제로 실행되면 울타리를 닫고 다시 열어 마크다운을 유효하게 유지하세요.
maxChars는 textChunkLimit 채널에 고정되어 있으므로 채널당 한도를 초과할 수 없습니다.
병합(스트리밍된 블록 병합)
블록 스트리밍이 활성화되면 OpenClaw는 연속적인 블록 청크를 병합할 수 있습니다. 그들을 보내기 전에. 이렇게 하면 "한 줄 스팸"이 줄어들면서 동시에 프로그레시브 출력.
- 병합은 플러시하기 전에 유휴 간격(
idleMs)을 기다립니다. - 버퍼는
maxChars로 제한되며 이를 초과하면 플러시됩니다. minChars충분한 텍스트가 쌓일 때까지 작은 조각이 전송되는 것을 방지합니다. (최종 플러시는 항상 남은 텍스트를 보냅니다).- Joiner는
blockStreamingChunk.breakPreference에서 파생됩니다. (paragraph→\n\n,newline→\n,sentence→ 공백). - 채널 재정의는
*.blockStreamingCoalesce을 통해 가능합니다(계정별 구성 포함). - 재정의되지 않는 한 Signal/Slack/Discord에 대한 기본 통합
minChars은 1500으로 증가합니다.
블록 간 인간과 같은 속도
블록 스트리밍이 활성화되면 스트리밍 사이에 무작위 일시중지를 추가할 수 있습니다. 응답을 차단합니다(첫 번째 차단 이후). 이는 다중 버블 반응을 느끼게 합니다. 더 자연스러워요.
- 구성:
agents.defaults.humanDelay(agents.list[].humanDelay를 통해 에이전트별로 재정의). - 모드:
off(기본값),natural(800–2500ms),custom(minMs/maxMs). - 최종 답변이나 도구 요약이 아닌 답글 차단에만 적용됩니다.
“스트림 청크 또는 모든 것”
이는 다음에 매핑됩니다.
- 스트림 청크:
blockStreamingDefault: "on"+blockStreamingBreak: "text_end"(진행하면서 방출). 텔레그램이 아닌 채널에도*.blockStreaming: true가 필요합니다. - 끝 부분에 모든 것을 스트리밍합니다:
blockStreamingBreak: "message_end"(한 번 플러시하고 매우 긴 경우 여러 청크를 플러시할 수 있음). - 블록 스트리밍 없음:
blockStreamingDefault: "off"(최종 응답만).
채널 참고 사항: Telegram 채널이 아닌 경우 블록 스트리밍은 해당되지 않는 한 꺼집니다. *.blockStreaming는 명시적으로 true로 설정됩니다. 텔레그램은 초안을 스트리밍할 수 있습니다 (channels.telegram.streamMode) 차단 응답이 없습니다.
구성 위치 알림: blockStreaming* 기본값은 다음 위치에 있습니다. agents.defaults, 루트 구성이 아닙니다.
텔레그램 초안 스트리밍(토큰형)
텔레그램은 초안 스트리밍이 가능한 유일한 채널입니다.
- 주제별 비공개 채팅에서 Bot API
sendMessageDraft를 사용합니다. channels.telegram.streamMode: "partial" | "block" | "off".partial: 최신 스트림 텍스트로 초안 업데이트.block: 청크 블록의 초안 업데이트(동일 청커 규칙).off: 초안 스트리밍이 없습니다.
- 초안 청크 구성(
streamMode: "block"에만 해당):channels.telegram.draftChunk(기본값:minChars: 200,maxChars: 800). - 드래프트 스트리밍은 블록 스트리밍과 별개입니다. 차단 답글은 기본적으로 꺼져 있으며 텔레그램이 아닌 채널에서는
*.blockStreaming: true로만 활성화됩니다. - 최종 답변은 여전히 정상적인 메시지입니다.
/reasoning stream초안 풍선에 추론을 씁니다(텔레그램에만 해당).
초안 스트리밍이 활성화되면 OpenClaw는 이중 스트리밍을 방지하기 위해 해당 응답에 대한 블록 스트리밍을 비활성화합니다.
Telegram (private + topics)
└─ sendMessageDraft (draft bubble)
├─ streamMode=partial → update latest text
└─ streamMode=block → chunker updates draft
└─ final reply → normal message범례:
sendMessageDraft: 텔레그램 초안 풍선(실제 메시지가 아님).final reply: 정상적인 텔레그램 메시지 전송입니다.