콘텐츠로 이동

OpenClaw 스트리밍 및 청킹 설정 가이드

AI 응답이 올 때까지 하염없이 커서만 바라보고 있었던 적이 있나요? 특히 긴 답변을 생성할 때 답변이 다 완성될 때까지 아무것도 보이지 않는다면 사용자 경험은 답답해질 수밖에 없어요. 그렇다고 토큰 하나가 생성될 때마다 매번 메시지를 보내면 알림이 쏟아지는 ‘알림 지옥’에 빠지게 되죠.

OpenClaw는 이런 문제를 해결하기 위해 두 가지 영리한 스트리밍 레이어를 제공해요. 답변을 적절한 덩어리로 끊어서 보내는 블록 스트리밍과, 메시지 하나를 실시간으로 업데이트하는 프리뷰 스트리밍을 통해 사용자에게 가장 자연스러운 피드백을 전달할 수 있습니다.

블록 스트리밍은 어시스턴트의 출력을 사용 가능한 시점에 맞춰 큼직한 청크(chunk) 단위로 전송해요.

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? } (전송 전 스트리밍된 블록들을 병합해요).
  • 채널 하드 캡(Hard cap): *.textChunkLimit (예: channels.whatsapp.textChunkLimit).
  • 채널 청크 모드: *.chunkMode (length가 기본이며, newline은 길이에 따라 나누기 전 빈 줄(단락 경계)에서 먼저 나눕니다).
  • Discord 소프트 캡(Soft cap): channels.discord.maxLinesPerMessage (기본값 17)는 UI가 잘리는 것을 방지하기 위해 세로로 긴 답장을 나눕니다.

경계 의미(Boundary semantics):

  • text_end: 청커가 블록을 내보내는 즉시 스트리밍하고, 각 text_end마다 플러시(flush)해요.
  • message_end: 어시스턴트 메시지가 끝날 때까지 기다렸다가 버퍼링된 출력을 한꺼번에 플러시해요.

message_end를 사용하더라도 버퍼링된 텍스트가 maxChars를 초과하면 청커가 작동하여 마지막에 여러 개의 청크로 나누어 보낼 수 있어요.

청킹 알고리즘 (최소/최대 범위)

섹션 제목: “청킹 알고리즘 (최소/최대 범위)”

블록 청킹은 EmbeddedBlockChunker에 의해 구현됩니다.

  • 최소 범위(Low bound): 버퍼가 minChars 이상이 될 때까지는 내보내지 않아요 (강제 플러시 제외).
  • 최대 범위(High bound): maxChars 직전에서 끊는 것을 선호하며, 강제될 경우 maxChars에서 나눕니다.
  • 줄 바꿈 선호도(Break preference): paragraph → newline → sentence → whitespace → 하드 브레이크 순서로 적용돼요.
  • 코드 펜스(Code fences): 코드 블록 내부에서는 절대 나누지 않아요. maxChars 때문에 어쩔 수 없이 나눠야 할 때는 Markdown 문법이 깨지지 않도록 펜스를 닫고 다시 열어줍니다.

maxChars는 채널의 textChunkLimit에 고정되므로, 채널별 제한을 초과할 걱정은 없어요.

블록 스트리밍이 활성화되었을 때, OpenClaw는 연속된 블록 청크를 전송하기 전에 하나로 병합할 수 있어요. 이렇게 하면 진행 상황을 보여주면서도 “한 줄씩 도배되는 스팸” 현상을 줄일 수 있습니다.

  • Coalescing은 플러시하기 전에 유휴 시간(idleMs)을 기다려요.
  • 버퍼는 maxChars로 제한되며, 이를 초과하면 즉시 플러시됩니다.
  • minChars는 충분한 텍스트가 쌓일 때까지 아주 작은 파편이 전송되는 것을 방지해요 (최종 플러시 때는 남은 텍스트를 모두 보냅니다).
  • 결합 방식은 blockStreamingChunk.breakPreference에서 가져와요 (paragraph → \n\n, newline → \n, sentence → 공백).
  • *.blockStreamingCoalesce를 통해 채널별 오버라이드가 가능해요 (계정별 설정 포함).
  • Signal/Slack/Discord의 경우 별도 설정이 없으면 기본 coalesce minChars가 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
Telegram✅✅✅partial로 매핑됨
Discord✅✅✅partial로 매핑됨
Slack✅✅✅✅

Slack 전용:

  • streaming=partial일 때 channels.slack.nativeStreaming을 통해 Slack 네이티브 스트리밍 API 호출 여부를 결정할 수 있어요 (기본값: true).

기존 키 마이그레이션:

  • Telegram: streamMode와 불리언(boolean) 값인 streaming은 자동으로 streaming 열거형(enum)으로 마이그레이션됩니다.
  • Discord: streamMode와 불리언 값인 streaming은 자동으로 streaming 열거형으로 마이그레이션됩니다.
  • Slack: streamMode는 streaming 열거형으로, 불리언 값인 streaming은 nativeStreaming으로 자동 마이그레이션됩니다.

Telegram:

  • DM, 그룹, 토픽 전체에서 sendMessage + editMessageText를 사용하여 프리뷰를 업데이트해요.
  • Telegram 블록 스트리밍이 명시적으로 활성화된 경우, 중복 스트리밍을 피하기 위해 프리뷰 스트리밍은 건너뜁니다.
  • /reasoning stream 명령으로 추론 과정을 프리뷰에 표시할 수 있어요.

Discord:

  • 메시지 전송 후 수정(send + edit) 방식을 사용해요.
  • block 모드는 드래프트 청킹(draftChunk)을 사용합니다.
  • Discord 블록 스트리밍이 활성화된 경우 프리뷰 스트리밍은 건너뜁니다.

Slack:

  • partial 모드에서 사용 가능한 경우 Slack 네이티브 스트리밍(chat.startStream/append/stop)을 사용할 수 있어요.
  • block 모드는 추가 방식(append-style)의 드래프트 프리뷰를 사용합니다.
  • progress 모드는 상태 프리뷰 텍스트를 보여준 뒤 최종 답변을 표시해요.
  • Messages — 메시지 생명주기 및 전달
  • Retry — 전달 실패 시 재시도 동작
  • Channels — 채널별 스트리밍 지원

AI Setup Assistant

OpenClaw

OpenClaw Expert

아직 막혀 있나요?

이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.