Messages and delivery
การสตรีมและการแบ่งเป็นชังก์
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"(ค่าเริ่มต้นปิด)- การแทนที่ระดับช่องทาง:
*.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: สตรีมบล็อกทันทีเมื่อ chunker ส่งออกมา; ล้างบัฟเฟอร์ทุกครั้งที่text_endmessage_end: รอจนข้อความผู้ช่วยเสร็จสิ้น แล้วค่อยล้างเอาต์พุตที่บัฟเฟอร์ไว้
message_end ยังคงใช้ chunker หากข้อความที่บัฟเฟอร์ไว้ยาวเกิน maxChars ดังนั้นจึงอาจส่งหลายชิ้นในตอนท้ายได้
การส่งสื่อพร้อมการสตรีมแบบบล็อก
คำสั่ง MEDIA: เป็นเมทาดาทาการส่งปกติ เมื่อการสตรีมแบบบล็อกส่งบล็อกสื่อออกไปก่อน OpenClaw จะจดจำการส่งนั้นไว้สำหรับรอบนั้น หาก payload สุดท้ายของผู้ช่วยทำซ้ำ URL สื่อเดียวกัน การส่งสุดท้ายจะตัดสื่อที่ซ้ำออกแทนการส่งไฟล์แนบอีกครั้ง
payload สุดท้ายที่ซ้ำกันทุกประการจะถูกระงับ หาก payload สุดท้ายเพิ่มข้อความที่แตกต่างรอบสื่อที่สตรีมไปแล้ว OpenClaw ยังคงส่งข้อความใหม่โดยคงสื่อให้ส่งเพียงครั้งเดียว วิธีนี้ป้องกันการส่งโน้ตเสียงหรือไฟล์ซ้ำในช่องทางอย่าง Telegram เมื่อ agent ส่ง MEDIA: ระหว่างการสตรีม และ provider รวมสิ่งเดียวกันไว้ในการตอบกลับที่เสร็จสมบูรณ์ด้วย
อัลกอริทึมการแบ่งชิ้น (ขอบเขตต่ำ/สูง)
การแบ่งชิ้นแบบบล็อกดำเนินการโดย 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สำหรับการรวมชิ้นจะถูกเพิ่มเป็น 1500 สำหรับ Signal/Slack/Discord เว้นแต่ถูกแทนที่
จังหวะที่เหมือนมนุษย์ระหว่างบล็อก
เมื่อเปิดใช้การสตรีมแบบบล็อก คุณสามารถเพิ่ม การหยุดแบบสุ่ม ระหว่างการตอบกลับแบบบล็อก (หลังบล็อกแรก) ได้ วิธีนี้ทำให้การตอบกลับแบบหลายบับเบิลรู้สึกเป็นธรรมชาติมากขึ้น
- การกำหนดค่า:
agents.defaults.humanDelay(แทนที่ต่อ agent ผ่าน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 ไม่ใช่ config ราก
โหมดการสตรีมตัวอย่าง
คีย์มาตรฐาน: channels.<channel>.streaming
โหมด:
off: ปิดใช้การสตรีมตัวอย่างpartial: ตัวอย่างเดียวที่ถูกแทนที่ด้วยข้อความล่าสุดblock: ตัวอย่างอัปเดตเป็นขั้นแบบแบ่งชิ้น/ต่อท้ายprogress: ตัวอย่างความคืบหน้า/สถานะระหว่างการสร้าง และคำตอบสุดท้ายเมื่อเสร็จสิ้น
streaming.mode: "block" เป็นโหมดการสตรีมตัวอย่างสำหรับช่องทางที่แก้ไขได้ เช่น Discord และ Telegram โหมดนี้ไม่ได้เปิดใช้การส่งบล็อกผ่านช่องทางนั้น ใช้ streaming.block.enabled หรือคีย์ช่องทางแบบเดิม blockStreaming เมื่อต้องการการตอบกลับแบบบล็อกปกติ Microsoft Teams เป็นข้อยกเว้น: ไม่มีการขนส่งบล็อกแบบร่างตัวอย่าง ดังนั้น streaming.mode: "block" จึงแมปเป็นการส่งบล็อกของ Teams แทนการสตรีมแบบบางส่วน/ความคืบหน้าแบบเนทีฟ
การแมปช่องทาง
| ช่องทาง | off |
partial |
block |
progress |
|---|---|---|---|---|
| Telegram | ✅ | ✅ | ✅ | ร่างความคืบหน้าที่แก้ไขได้ |
| Discord | ✅ | ✅ | ✅ | ร่างความคืบหน้าที่แก้ไขได้ |
| Slack | ✅ | ✅ | ✅ | ✅ |
| Mattermost | ✅ | ✅ | ✅ | ✅ |
| MS Teams | ✅ | ✅ | ✅ | สตรีมความคืบหน้าแบบเนทีฟ |
เฉพาะ Slack:
channels.slack.streaming.nativeTransportสลับการเรียก Slack native streaming API เมื่อchannels.slack.streaming.mode="partial"(ค่าเริ่มต้น:true)- Slack native streaming และสถานะเธรดผู้ช่วยของ Slack ต้องมีเป้าหมายเป็นเธรดตอบกลับ DM ระดับบนสุดไม่แสดงตัวอย่างรูปแบบเธรดนั้น แต่ยังสามารถใช้โพสต์ตัวอย่างแบบร่างและการแก้ไขของ Slack ได้
การย้ายคีย์เดิม:
- Telegram: ค่าเดิม
streamModeและค่าstreamingแบบสเกลาร์/บูลีนจะถูกตรวจพบและย้ายโดยเส้นทาง doctor/ความเข้ากันได้ของ config ไปยังstreaming.mode - Discord:
streamMode+streamingแบบบูลีนยังคงเป็น alias ขณะรันไทม์สำหรับ enumstreaming; รันopenclaw doctor --fixเพื่อเขียน config ที่บันทึกไว้ใหม่ - Slack:
streamModeยังคงเป็น alias ขณะรันไทม์สำหรับstreaming.mode;streamingแบบบูลีนยังคงเป็น alias ขณะรันไทม์สำหรับstreaming.modeรวมถึงstreaming.nativeTransport;nativeStreamingแบบเดิมยังคงเป็น alias ขณะรันไทม์สำหรับstreaming.nativeTransportรันopenclaw doctor --fixเพื่อเขียน config ที่บันทึกไว้ใหม่
พฤติกรรมขณะรันไทม์
Telegram:
- ใช้
sendMessage+ การอัปเดตตัวอย่างด้วยeditMessageTextใน DM และกลุ่ม/หัวข้อ - ข้อความสุดท้ายจะแก้ไขตัวอย่างที่ใช้งานอยู่ในตำแหน่งเดิม; ข้อความสุดท้ายที่ยาวจะใช้ข้อความนั้นซ้ำสำหรับชิ้นแรกและส่งเฉพาะชิ้นที่เหลือ
- โหมด
progressเก็บความคืบหน้าของเครื่องมือไว้ในร่างสถานะที่แก้ไขได้ ล้างร่างนั้นเมื่อเสร็จสิ้น และส่งคำตอบสุดท้ายผ่านการส่งปกติ - หากการแก้ไขสุดท้ายล้มเหลวก่อนยืนยันข้อความที่เสร็จสมบูรณ์ OpenClaw จะใช้การส่งสุดท้ายแบบปกติและล้างตัวอย่างเก่าที่ค้างอยู่
- การสตรีมตัวอย่างจะถูกข้ามเมื่อเปิดใช้การสตรีมแบบบล็อกของ Telegram อย่างชัดเจน (เพื่อหลีกเลี่ยงการสตรีมซ้ำซ้อน)
/reasoning streamสามารถเขียนเหตุผลลงในตัวอย่างชั่วคราวที่จะถูกลบหลังการส่งสุดท้าย
Discord:
- ใช้ข้อความตัวอย่างแบบส่ง + แก้ไข
- โหมด
blockใช้การแบ่งชิ้นแบบร่าง (draftChunk) - การสตรีมตัวอย่างจะถูกข้ามเมื่อเปิดใช้การสตรีมแบบบล็อกของ Discord อย่างชัดเจน
- payload สุดท้ายที่เป็นสื่อ ข้อผิดพลาด และการตอบกลับแบบระบุชัดเจนจะยกเลิกตัวอย่างที่รออยู่โดยไม่ล้างเป็นร่างใหม่ แล้วใช้การส่งปกติ
Slack:
partialสามารถใช้ Slack native streaming (chat.startStream/append/stop) เมื่อพร้อมใช้งานblockใช้ตัวอย่างแบบร่างสไตล์ต่อท้ายprogressใช้ข้อความตัวอย่างสถานะ แล้วตามด้วยคำตอบสุดท้าย- DM ระดับบนสุดที่ไม่มีเธรดตอบกลับจะใช้โพสต์ตัวอย่างแบบร่างและการแก้ไขแทน Slack native streaming
- การสตรีมตัวอย่างทั้งแบบเนทีฟและแบบร่างจะระงับการตอบกลับแบบบล็อกสำหรับรอบนั้น ดังนั้นการตอบกลับของ Slack จะถูกสตรีมผ่านเส้นทางการส่งเพียงเส้นทางเดียว
- payload สุดท้ายที่เป็นสื่อ/ข้อผิดพลาดและผลสุดท้ายของความคืบหน้าจะไม่สร้างข้อความร่างชั่วคราว; เฉพาะผลสุดท้ายแบบข้อความ/บล็อกที่แก้ไขตัวอย่างได้เท่านั้นที่จะล้างข้อความร่างที่รออยู่
Mattermost:
- สตรีมการคิด กิจกรรมเครื่องมือ และข้อความตอบกลับบางส่วนลงในโพสต์ตัวอย่างแบบร่างเดียว ซึ่งจะถูกทำให้เป็นผลสุดท้ายในตำแหน่งเดิมเมื่อคำตอบสุดท้ายปลอดภัยที่จะส่ง
- ถอยกลับไปส่งโพสต์สุดท้ายใหม่หากโพสต์ตัวอย่างถูกลบหรือไม่พร้อมใช้งานด้วยเหตุอื่นในเวลาทำผลสุดท้าย
- payload สุดท้ายที่เป็นสื่อ/ข้อผิดพลาดจะยกเลิกการอัปเดตตัวอย่างที่รออยู่ก่อนการส่งปกติ แทนการล้างเป็นโพสต์ตัวอย่างชั่วคราว
Matrix:
- ตัวอย่างแบบร่างจะถูกทำให้เป็นผลสุดท้ายในตำแหน่งเดิมเมื่อข้อความสุดท้ายสามารถใช้เหตุการณ์ตัวอย่างซ้ำได้
- ผลสุดท้ายที่เป็นสื่อเท่านั้น ข้อผิดพลาด และเป้าหมายการตอบกลับไม่ตรงกันจะยกเลิกการอัปเดตตัวอย่างที่รออยู่ก่อนการส่งปกติ; ตัวอย่างเก่าที่มองเห็นอยู่แล้วจะถูกลบแบบ redaction
การอัปเดตตัวอย่างความคืบหน้าของเครื่องมือ
การสตรีมตัวอย่างยังสามารถรวมการอัปเดต ความคืบหน้าของเครื่องมือ ได้ด้วย - บรรทัดสถานะสั้น ๆ เช่น "กำลังค้นหาเว็บ", "กำลังอ่านไฟล์" หรือ "กำลังเรียกใช้เครื่องมือ" - ซึ่งปรากฏในข้อความตัวอย่างเดียวกันระหว่างที่เครื่องมือกำลังทำงาน ก่อนการตอบกลับสุดท้าย วิธีนี้ทำให้รอบการใช้เครื่องมือหลายขั้นตอนยังคงมีความเคลื่อนไหวให้เห็น แทนที่จะเงียบระหว่างตัวอย่างการคิดแรกกับคำตอบสุดท้าย
พื้นผิวที่รองรับ:
- Discord, Slack, Telegram และ Matrix จะสตรีมความคืบหน้าของเครื่องมือเข้าไปในการแก้ไขตัวอย่างแบบสดตามค่าเริ่มต้นเมื่อการสตรีมตัวอย่างทำงานอยู่ Microsoft Teams ใช้สตรีมความคืบหน้าแบบเนทีฟในแชตส่วนตัว
- Telegram จัดส่งพร้อมการอัปเดตตัวอย่างความคืบหน้าของเครื่องมือที่เปิดใช้มาตั้งแต่
v2026.4.22; การเปิดใช้ต่อไปจะรักษาพฤติกรรมที่เผยแพร่ไปแล้วนั้นไว้ - Mattermost รวมกิจกรรมของเครื่องมือเข้าไว้ในโพสต์ตัวอย่างฉบับร่างเดียวของตัวเองอยู่แล้ว (ดูด้านบน)
- การแก้ไขความคืบหน้าของเครื่องมือจะทำตามโหมดการสตรีมตัวอย่างที่ทำงานอยู่; ระบบจะข้ามการแก้ไขเหล่านี้เมื่อการสตรีมตัวอย่างเป็น
offหรือเมื่อการสตรีมบล็อกรับช่วงข้อความไปแล้ว บน Telegram,streaming.mode: "off"เป็นแบบผลลัพธ์สุดท้ายเท่านั้น: ข้อความความคืบหน้าทั่วไปจะถูกระงับด้วยแทนที่จะส่งเป็นข้อความสถานะแยกต่างหาก ขณะที่พรอมป์การอนุมัติ เพย์โหลดสื่อ และข้อผิดพลาดยังคงถูกกำหนดเส้นทางตามปกติ - หากต้องการคงการสตรีมตัวอย่างไว้แต่ซ่อนบรรทัดความคืบหน้าของเครื่องมือ ให้ตั้งค่า
streaming.preview.toolProgressเป็นfalseสำหรับช่องทางนั้น หากต้องการให้บรรทัดความคืบหน้าของเครื่องมือยังมองเห็นได้ขณะซ่อนข้อความคำสั่ง/การรัน ให้ตั้งค่าstreaming.preview.commandTextเป็น"status"หรือstreaming.progress.commandTextเป็น"status"; ค่าเริ่มต้นคือ"raw"เพื่อรักษาพฤติกรรมที่เผยแพร่ไปแล้ว นโยบายนี้ใช้ร่วมกันโดยช่องทางฉบับร่าง/ความคืบหน้าที่ใช้ตัวเรนเดอร์ความคืบหน้าแบบกะทัดรัดของ OpenClaw ซึ่งรวมถึง Discord, Matrix, Microsoft Teams, Mattermost, ตัวอย่างฉบับร่างของ Slack และ Telegram หากต้องการปิดการแก้ไขตัวอย่างทั้งหมด ให้ตั้งค่าstreaming.modeเป็นoff - การตอบกลับด้วยข้อความอ้างอิงที่เลือกบน Telegram เป็นข้อยกเว้น: เมื่อ
replyToModeไม่ใช่"off"และมีข้อความอ้างอิงที่เลือกอยู่ OpenClaw จะข้ามสตรีมตัวอย่างคำตอบสำหรับรอบนั้น ทำให้บรรทัดตัวอย่างความคืบหน้าของเครื่องมือไม่สามารถเรนเดอร์ได้ การตอบกลับข้อความปัจจุบันที่ไม่มีข้อความอ้างอิงที่เลือกยังคงใช้การสตรีมตัวอย่าง ดูรายละเอียดได้ที่ เอกสารช่องทาง Telegram
คงบรรทัดความคืบหน้าให้มองเห็นได้ แต่ซ่อนข้อความคำสั่ง/การรันแบบดิบ:
{
"channels": {
"telegram": {
"streaming": {
"mode": "partial",
"preview": {
"toolProgress": true,
"commandText": "status"
}
}
}
}
}
ใช้รูปแบบเดียวกันภายใต้คีย์ช่องทางความคืบหน้าแบบกะทัดรัดอื่น เช่น channels.discord, channels.matrix, channels.msteams, channels.mattermost หรือตัวอย่างฉบับร่างของ Slack สำหรับโหมดฉบับร่างความคืบหน้า ให้วางนโยบายเดียวกันไว้ภายใต้ streaming.progress:
{
"channels": {
"telegram": {
"streaming": {
"mode": "progress",
"progress": {
"toolProgress": true,
"commandText": "status"
}
}
}
}
}
ที่เกี่ยวข้อง
- การปรับโครงสร้างวงจรชีวิตข้อความ - ออกแบบตัวอย่าง การแก้ไข การสตรีม และการสรุปผลขั้นสุดท้ายที่ใช้ร่วมกันเป็นเป้าหมาย
- ฉบับร่างความคืบหน้า - ข้อความงานที่กำลังดำเนินอยู่ซึ่งมองเห็นได้และอัปเดตระหว่างรอบที่ใช้เวลานาน
- ข้อความ - วงจรชีวิตข้อความและการส่งมอบ
- ลองใหม่ - พฤติกรรมการลองใหม่เมื่อการส่งมอบล้มเหลว
- ช่องทาง - การรองรับการสตรีมรายช่องทาง