스트리밍 + 청킹

OpenClaw에는 두 가지 별도의 스트리밍 레이어가 있습니다:

  • 블록 스트리밍 (채널): 어시스턴트가 작성하는 동안 완료된 블록을 내보냅니다. 이것은 일반 채널 메시지이며 토큰 델타가 아닙니다.
  • 미리보기 스트리밍 (Telegram/Discord/Slack): 생성 중에 임시 미리보기 메시지를 업데이트합니다.

현재 채널 메시지에 대한 실시간 토큰 델타 스트리밍은 없습니다. 미리보기 스트리밍은 메시지 기반(전송 + 편집/추가)입니다.

블록 스트리밍 (채널 메시지)

블록 스트리밍은 어시스턴트 출력을 사용 가능해지는 대로 대략적인 청크 단위로 전송합니다.

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" (기본값 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에서 분할.
  • 분할 선호도: paragraphnewlinesentencewhitespace → 하드 분할.
  • 코드 펜스: 펜스 내부에서는 절대 분할하지 않음. maxChars에서 강제 시 마크다운 유효성을 유지하기 위해 펜스를 닫고 다시 엽니다.

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로 설정되지 않으면 비활성화됩니다. 채널은 블록 응답 없이 실시간 미리보기(channels.<channel>.streaming)를 스트리밍할 수 있습니다.

설정 위치 참고: blockStreaming* 기본값은 루트 설정이 아닌 agents.defaults 아래에 있습니다.

미리보기 스트리밍 모드

정규 키: channels.<channel>.streaming

모드:

  • off: 미리보기 스트리밍 비활성화.
  • partial: 최신 텍스트로 대체되는 단일 미리보기.
  • block: 청크/추가 단계로 업데이트되는 미리보기.
  • progress: 생성 중 진행/상태 미리보기, 완료 시 최종 답변.

채널 매핑

채널offpartialblockprogress
Telegrampartial로 매핑
Discordpartial로 매핑
Slack

Slack 전용:

  • channels.slack.nativeStreamingstreaming=partial일 때 Slack 네이티브 스트리밍 API 호출을 토글합니다(기본값: true).

레거시 키 마이그레이션:

  • Telegram: streamMode + 불리언 streamingstreaming 열거형으로 자동 마이그레이션.
  • Discord: streamMode + 불리언 streamingstreaming 열거형으로 자동 마이그레이션.
  • Slack: streamModestreaming 열거형으로 자동 마이그레이션, 불리언 streamingnativeStreaming으로 자동 마이그레이션.

런타임 동작

Telegram:

  • DM과 그룹/토픽 전반에서 sendMessage + editMessageText 미리보기 업데이트를 사용합니다.
  • Telegram 블록 스트리밍이 명시적으로 활성화된 경우 이중 스트리밍을 방지하기 위해 미리보기 스트리밍을 건너뜁니다.
  • /reasoning stream으로 추론을 미리보기에 쓸 수 있습니다.

Discord:

  • 전송 + 편집 미리보기 메시지를 사용합니다.
  • block 모드는 드래프트 청킹(draftChunk)을 사용합니다.
  • Discord 블록 스트리밍이 명시적으로 활성화된 경우 미리보기 스트리밍을 건너뜁니다.

Slack:

  • partial은 사용 가능한 경우 Slack 네이티브 스트리밍(chat.startStream/append/stop)을 사용할 수 있습니다.
  • block은 추가 방식 드래프트 미리보기를 사용합니다.
  • progress는 상태 미리보기 텍스트를 사용하고 최종 답변을 표시합니다.