Messages and delivery
คิวคำสั่ง
เราทำให้การรันตอบกลับอัตโนมัติขาเข้า (ทุกช่องทาง) เรียงลำดับผ่านคิวในโปรเซสขนาดเล็ก เพื่อป้องกันไม่ให้การรันเอเจนต์หลายรายการชนกัน ขณะเดียวกันยังอนุญาตให้ทำงานแบบขนานได้อย่างปลอดภัยข้ามเซสชัน
เหตุผล
- การรันตอบกลับอัตโนมัติอาจมีต้นทุนสูง (การเรียก LLM) และอาจชนกันเมื่อมีข้อความขาเข้าหลายข้อความมาถึงในเวลาใกล้เคียงกัน
- การเรียงลำดับช่วยหลีกเลี่ยงการแย่งใช้ทรัพยากรร่วมกัน (ไฟล์เซสชัน, บันทึก, stdin ของ CLI) และลดโอกาสที่จะชนกับขีดจำกัดอัตราของต้นทาง
วิธีทำงาน
- คิว FIFO ที่รับรู้เลนจะระบายแต่ละเลนด้วยขีดจำกัดจำนวนงานพร้อมกันที่กำหนดค่าได้ (ค่าเริ่มต้น 1 สำหรับเลนที่ไม่ได้กำหนดค่า; เลนหลักมีค่าเริ่มต้นเป็น 4, เอเจนต์ย่อยเป็น 8)
runEmbeddedAgentเข้าคิวตาม คีย์เซสชัน (เลนsession:<key>) เพื่อรับประกันว่ามีการรันที่ทำงานอยู่ได้เพียงหนึ่งรายการต่อเซสชัน- จากนั้นการรันแต่ละเซสชันจะถูกเข้าคิวใน เลนส่วนกลาง (
mainโดยค่าเริ่มต้น) เพื่อให้จำนวนงานพร้อมกันโดยรวมถูกจำกัดโดยagents.defaults.maxConcurrent - เมื่อเปิดใช้การบันทึกแบบละเอียด การรันที่อยู่ในคิวจะแสดงประกาศสั้น ๆ หากรอนานกว่า ~2 วินาทีก่อนเริ่ม
- ตัวบ่งชี้การพิมพ์ยังคงทำงานทันทีเมื่อเข้าคิว (เมื่อช่องทางรองรับ) ดังนั้นประสบการณ์ผู้ใช้จะไม่เปลี่ยนแปลงระหว่างรอถึงรอบของเรา
ค่าเริ่มต้น
เมื่อไม่ได้ตั้งค่า พื้นผิวช่องทางขาเข้าทั้งหมดจะใช้:
mode: "steer"debounceMs: 500cap: 20drop: "summarize"
การควบคุมทิศทางในเทิร์นเดียวกันเป็นค่าเริ่มต้น พรอมป์ที่มาถึงระหว่างการรันจะถูกฉีดเข้า รันไทม์ที่ทำงานอยู่เมื่อการรันนั้นรับการควบคุมทิศทางได้ จึงไม่เริ่มการรันเซสชัน ครั้งที่สอง หากการรันที่ทำงานอยู่รับการควบคุมทิศทางไม่ได้ OpenClaw จะรอให้ การรันที่ทำงานอยู่เสร็จก่อนเริ่มพรอมป์
โหมดคิว
/queue ควบคุมว่าข้อความขาเข้าปกติจะทำอะไรเมื่อเซสชันมี
การรันที่ทำงานอยู่แล้ว:
steer: ฉีดข้อความเข้าไปในรันไทม์ที่ทำงานอยู่ OpenClaw จะส่งข้อความควบคุมทิศทางที่ค้างอยู่ทั้งหมด หลังจากเทิร์นผู้ช่วยปัจจุบันรันการเรียกเครื่องมือเสร็จแล้ว ก่อนการเรียก LLM ถัดไป; app-server ของ Codex จะได้รับturn/steerที่รวมเป็นชุดเดียว หากการรันไม่ได้กำลังสตรีมอยู่หรือการควบคุมทิศทางไม่พร้อมใช้งาน OpenClaw จะรอจนกว่าการรันที่ทำงานอยู่จบลงก่อนเริ่มพรอมป์followup: ไม่ควบคุมทิศทาง เข้าคิวแต่ละข้อความไว้สำหรับเทิร์นเอเจนต์ภายหลังหลังจากการรันปัจจุบันจบลงcollect: ไม่ควบคุมทิศทาง รวมข้อความที่เข้าคิวไว้เป็นเทิร์นติดตามผล รายการเดียว หลังช่วงเวลาสงบ หากข้อความกำหนดเป้าหมายไปยังช่องทาง/เธรดต่างกัน ข้อความเหล่านั้นจะถูกระบายแยกกันเพื่อรักษาการกำหนดเส้นทางinterrupt: ยกเลิกการรันที่ทำงานอยู่ของเซสชันนั้น แล้วรันข้อความล่าสุด
สำหรับจังหวะเวลาที่เฉพาะกับรันไทม์และพฤติกรรมของ dependency โปรดดู
คิวการควบคุมทิศทาง สำหรับคำสั่ง /steer <message>
โดยตรง โปรดดู ควบคุมทิศทาง
กำหนดค่าทั่วทั้งระบบหรือต่อช่องทางผ่าน messages.queue:
{ messages: { queue: { mode: "steer", debounceMs: 500, cap: 20, drop: "summarize", byChannel: { discord: "collect" }, }, },}ตัวเลือกคิว
ตัวเลือกมีผลกับการส่งที่เข้าคิวไว้ debounceMs ยังตั้งค่าช่วงเวลาสงบของการควบคุมทิศทาง
ของ Codex ในโหมด steer ด้วย:
debounceMs: ช่วงเวลาสงบก่อนระบายติดตามผลที่เข้าคิวหรือชุดที่รวบรวมไว้; ในโหมดsteerของ Codex คือช่วงเวลาสงบก่อนส่งturn/steerที่รวมเป็นชุด ตัวเลขล้วนคือมิลลิวินาที; ตัวเลือก/queueยอมรับหน่วยms,s,m,hและdcap: จำนวนข้อความที่เข้าคิวได้สูงสุดต่อเซสชัน ค่าต่ำกว่า1จะถูกละเว้นdrop: "summarize": ค่าเริ่มต้น ทิ้งรายการที่เข้าคิวเก่าที่สุดตามความจำเป็น เก็บสรุปแบบกระชับ และฉีดสรุปเหล่านั้นเป็นพรอมป์ติดตามผลสังเคราะห์drop: "old": ทิ้งรายการที่เข้าคิวเก่าที่สุดตามความจำเป็น โดยไม่เก็บสรุปไว้drop: "new": ปฏิเสธข้อความล่าสุดเมื่อคิวเต็มอยู่แล้ว
ค่าเริ่มต้น: debounceMs: 500, cap: 20, drop: summarize
ควบคุมทิศทางและการสตรีม
เมื่อการสตรีมของช่องทางเป็น partial หรือ block การควบคุมทิศทางอาจดูเหมือนเป็น
การตอบกลับสั้น ๆ ที่มองเห็นได้หลายครั้ง ขณะที่การรันที่ทำงานอยู่ไปถึงขอบเขตรันไทม์:
partial: ตัวอย่างแสดงผลอาจสิ้นสุดก่อน จากนั้นตัวอย่างใหม่จะเริ่มหลังจาก ยอมรับการควบคุมทิศทางแล้วblock: บล็อกขนาดร่างสามารถสร้างลักษณะต่อเนื่องแบบเดียวกันได้- หากไม่มีการสตรีม การควบคุมทิศทางจะถอยกลับเป็นติดตามผลหลังการรันที่ทำงานอยู่เมื่อ รันไทม์รับการควบคุมทิศทางในเทิร์นเดียวกันไม่ได้
steer ไม่ยกเลิกเครื่องมือที่กำลังทำงานอยู่ ใช้ /queue interrupt เมื่อข้อความ
ล่าสุดควรยกเลิกการรันปัจจุบัน
ลำดับความสำคัญ
สำหรับการเลือกโหมด OpenClaw จะใช้ลำดับดังนี้:
- การ override
/queueแบบอินไลน์หรือที่จัดเก็บไว้ต่อเซสชัน messages.queue.byChannel.<channel>messages.queue.mode- ค่าเริ่มต้น
steer
สำหรับตัวเลือก ตัวเลือก /queue แบบอินไลน์หรือที่จัดเก็บไว้จะชนะ config จากนั้นจะใช้
debounce เฉพาะช่องทาง (messages.queue.debounceMsByChannel), ค่าเริ่มต้น debounce
ของ Plugin, ตัวเลือก messages.queue ส่วนกลาง และค่าเริ่มต้นในตัวตามลำดับ cap และ drop
เป็นตัวเลือกระดับส่วนกลาง/เซสชัน ไม่ใช่คีย์ config ต่อช่องทาง
การ override ต่อเซสชัน
- ส่ง
/queue <steer|followup|collect|interrupt>เป็นคำสั่งเดี่ยวเพื่อจัดเก็บโหมดคิวสำหรับเซสชันปัจจุบัน - สามารถรวมตัวเลือกได้:
/queue collect debounce:0.5s cap:25 drop:summarize /queue defaultหรือ/queue resetจะล้างการ override ของเซสชัน
ขอบเขตและการรับประกัน
- ใช้กับการรันเอเจนต์ตอบกลับอัตโนมัติในทุกช่องทางขาเข้าที่ใช้ไปป์ไลน์การตอบกลับของ Gateway (เว็บ WhatsApp, Telegram, Slack, Discord, Signal, iMessage, เว็บแชต ฯลฯ)
- เลนเริ่มต้น (
main) ครอบคลุมทั้งโปรเซสสำหรับขาเข้า + Heartbeat หลัก; ตั้งค่าagents.defaults.maxConcurrentเพื่ออนุญาตให้หลายเซสชันทำงานแบบขนาน - อาจมีเลนเพิ่มเติม (เช่น
cron,cron-nested,nested,subagent) เพื่อให้งานเบื้องหลังทำงานแบบขนานได้โดยไม่บล็อกการตอบกลับขาเข้า เทิร์นเอเจนต์ Cron แบบแยกจะถือสล็อตcronขณะที่การรันเอเจนต์ภายในใช้cron-nested; ทั้งสองใช้cron.maxConcurrentRunsโฟลว์nestedที่ใช้ร่วมกันและไม่ใช่ Cron จะคงพฤติกรรมเลนของตัวเองไว้ การรันที่แยกออกเหล่านี้ถูกติดตามเป็น งานเบื้องหลัง - เลนต่อเซสชันรับประกันว่ามีการรันเอเจนต์เพียงหนึ่งรายการเท่านั้นที่แตะเซสชันหนึ่งในเวลาเดียวกัน
- ไม่มี dependency ภายนอกหรือเธรด worker เบื้องหลัง; เป็น TypeScript + promise ล้วน
การแก้ไขปัญหา
- หากคำสั่งดูเหมือนค้าง ให้เปิดใช้บันทึกแบบละเอียดและมองหาบรรทัด "queued for ...ms" เพื่อยืนยันว่าคิวกำลังระบาย
- หากคุณต้องการความลึกของคิว ให้เปิดใช้บันทึกแบบละเอียดและดูบรรทัดเวลาของคิว
- การรัน app-server ของ Codex ที่รับเทิร์นแล้วหยุดส่งความคืบหน้า จะถูก adapter ของ Codex ขัดจังหวะ เพื่อให้เลนเซสชันที่ทำงานอยู่ปล่อยได้แทนที่จะรอหมดเวลาการรันภายนอก
- เมื่อเปิดใช้การวินิจฉัย เซสชันที่ยังอยู่ใน
processingเกินdiagnostics.stuckSessionWarnMsโดยไม่พบการตอบกลับ เครื่องมือ สถานะ บล็อก หรือความคืบหน้าของ ACP จะถูกจัดประเภทตามกิจกรรมปัจจุบัน งานที่ทำงานอยู่จะบันทึกเป็นsession.long_running; การเรียกโมเดลแบบเงียบที่มีเจ้าของจะยังคงเป็นsession.long_runningจนถึงdiagnostics.stuckSessionAbortMsด้วย เพื่อไม่ให้รายงาน provider ที่ช้าหรือไม่สตรีมว่าค้างเร็วเกินไป งานที่ทำงานอยู่แต่ไม่มีความคืบหน้าล่าสุดจะบันทึกเป็นsession.stalled; การเรียกโมเดลที่มีเจ้าของจะเปลี่ยนเป็นsession.stalledเมื่อถึงหรือหลังเกณฑ์ยกเลิก และกิจกรรมโมเดล/เครื่องมือเก่าที่ไม่มีเจ้าของจะไม่ถูกซ่อนไว้เป็นงานที่รันยาวsession.stuckสงวนไว้สำหรับ bookkeeping ของเซสชันเก่าที่กู้คืนได้ รวมถึงเซสชันที่เข้าคิวและ idle ซึ่งมีกิจกรรมโมเดล/เครื่องมือเก่าที่ไม่มีเจ้าของ และมีเพียงเส้นทางนั้นเท่านั้นที่ปล่อยเลนเซสชันที่ได้รับผลกระทบเพื่อให้งานที่เข้าคิวระบายต่อได้ การวินิจฉัยsession.stuckซ้ำ ๆ จะ back off ขณะที่เซสชันยังไม่เปลี่ยนแปลง