Messages and delivery

คิวคำสั่ง

เราทำให้การรันตอบกลับอัตโนมัติขาเข้า (ทุกช่องทาง) เรียงลำดับผ่านคิวในโปรเซสขนาดเล็ก เพื่อป้องกันไม่ให้การรันเอเจนต์หลายรายการชนกัน ขณะเดียวกันยังอนุญาตให้ทำงานแบบขนานได้อย่างปลอดภัยข้ามเซสชัน

เหตุผล

  • การรันตอบกลับอัตโนมัติอาจมีต้นทุนสูง (การเรียก LLM) และอาจชนกันเมื่อมีข้อความขาเข้าหลายข้อความมาถึงในเวลาใกล้เคียงกัน
  • การเรียงลำดับช่วยหลีกเลี่ยงการแย่งใช้ทรัพยากรร่วมกัน (ไฟล์เซสชัน, บันทึก, stdin ของ CLI) และลดโอกาสที่จะชนกับขีดจำกัดอัตราของต้นทาง

วิธีทำงาน

  • คิว FIFO ที่รับรู้เลนจะระบายแต่ละเลนด้วยขีดจำกัดจำนวนงานพร้อมกันที่กำหนดค่าได้ (ค่าเริ่มต้น 1 สำหรับเลนที่ไม่ได้กำหนดค่า; เลนหลักมีค่าเริ่มต้นเป็น 4, เอเจนต์ย่อยเป็น 8)
  • runEmbeddedAgent เข้าคิวตาม คีย์เซสชัน (เลน session:<key>) เพื่อรับประกันว่ามีการรันที่ทำงานอยู่ได้เพียงหนึ่งรายการต่อเซสชัน
  • จากนั้นการรันแต่ละเซสชันจะถูกเข้าคิวใน เลนส่วนกลาง (main โดยค่าเริ่มต้น) เพื่อให้จำนวนงานพร้อมกันโดยรวมถูกจำกัดโดย agents.defaults.maxConcurrent
  • เมื่อเปิดใช้การบันทึกแบบละเอียด การรันที่อยู่ในคิวจะแสดงประกาศสั้น ๆ หากรอนานกว่า ~2 วินาทีก่อนเริ่ม
  • ตัวบ่งชี้การพิมพ์ยังคงทำงานทันทีเมื่อเข้าคิว (เมื่อช่องทางรองรับ) ดังนั้นประสบการณ์ผู้ใช้จะไม่เปลี่ยนแปลงระหว่างรอถึงรอบของเรา

ค่าเริ่มต้น

เมื่อไม่ได้ตั้งค่า พื้นผิวช่องทางขาเข้าทั้งหมดจะใช้:

  • mode: "steer"
  • debounceMs: 500
  • cap: 20
  • drop: "summarize"

การควบคุมทิศทางในเทิร์นเดียวกันเป็นค่าเริ่มต้น พรอมป์ที่มาถึงระหว่างการรันจะถูกฉีดเข้า รันไทม์ที่ทำงานอยู่เมื่อการรันนั้นรับการควบคุมทิศทางได้ จึงไม่เริ่มการรันเซสชัน ครั้งที่สอง หากการรันที่ทำงานอยู่รับการควบคุมทิศทางไม่ได้ OpenClaw จะรอให้ การรันที่ทำงานอยู่เสร็จก่อนเริ่มพรอมป์

โหมดคิว

/queue ควบคุมว่าข้อความขาเข้าปกติจะทำอะไรเมื่อเซสชันมี การรันที่ทำงานอยู่แล้ว:

  • steer: ฉีดข้อความเข้าไปในรันไทม์ที่ทำงานอยู่ OpenClaw จะส่งข้อความควบคุมทิศทางที่ค้างอยู่ทั้งหมด หลังจากเทิร์นผู้ช่วยปัจจุบันรันการเรียกเครื่องมือเสร็จแล้ว ก่อนการเรียก LLM ถัดไป; app-server ของ Codex จะได้รับ turn/steer ที่รวมเป็นชุดเดียว หากการรันไม่ได้กำลังสตรีมอยู่หรือการควบคุมทิศทางไม่พร้อมใช้งาน OpenClaw จะรอจนกว่าการรันที่ทำงานอยู่จบลงก่อนเริ่มพรอมป์
  • followup: ไม่ควบคุมทิศทาง เข้าคิวแต่ละข้อความไว้สำหรับเทิร์นเอเจนต์ภายหลังหลังจากการรันปัจจุบันจบลง
  • collect: ไม่ควบคุมทิศทาง รวมข้อความที่เข้าคิวไว้เป็นเทิร์นติดตามผล รายการเดียว หลังช่วงเวลาสงบ หากข้อความกำหนดเป้าหมายไปยังช่องทาง/เธรดต่างกัน ข้อความเหล่านั้นจะถูกระบายแยกกันเพื่อรักษาการกำหนดเส้นทาง
  • interrupt: ยกเลิกการรันที่ทำงานอยู่ของเซสชันนั้น แล้วรันข้อความล่าสุด

สำหรับจังหวะเวลาที่เฉพาะกับรันไทม์และพฤติกรรมของ dependency โปรดดู คิวการควบคุมทิศทาง สำหรับคำสั่ง /steer <message> โดยตรง โปรดดู ควบคุมทิศทาง

กำหนดค่าทั่วทั้งระบบหรือต่อช่องทางผ่าน messages.queue:

json5
{  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 และ d
  • cap: จำนวนข้อความที่เข้าคิวได้สูงสุดต่อเซสชัน ค่าต่ำกว่า 1 จะถูกละเว้น
  • drop: "summarize": ค่าเริ่มต้น ทิ้งรายการที่เข้าคิวเก่าที่สุดตามความจำเป็น เก็บสรุปแบบกระชับ และฉีดสรุปเหล่านั้นเป็นพรอมป์ติดตามผลสังเคราะห์
  • drop: "old": ทิ้งรายการที่เข้าคิวเก่าที่สุดตามความจำเป็น โดยไม่เก็บสรุปไว้
  • drop: "new": ปฏิเสธข้อความล่าสุดเมื่อคิวเต็มอยู่แล้ว

ค่าเริ่มต้น: debounceMs: 500, cap: 20, drop: summarize

ควบคุมทิศทางและการสตรีม

เมื่อการสตรีมของช่องทางเป็น partial หรือ block การควบคุมทิศทางอาจดูเหมือนเป็น การตอบกลับสั้น ๆ ที่มองเห็นได้หลายครั้ง ขณะที่การรันที่ทำงานอยู่ไปถึงขอบเขตรันไทม์:

  • partial: ตัวอย่างแสดงผลอาจสิ้นสุดก่อน จากนั้นตัวอย่างใหม่จะเริ่มหลังจาก ยอมรับการควบคุมทิศทางแล้ว
  • block: บล็อกขนาดร่างสามารถสร้างลักษณะต่อเนื่องแบบเดียวกันได้
  • หากไม่มีการสตรีม การควบคุมทิศทางจะถอยกลับเป็นติดตามผลหลังการรันที่ทำงานอยู่เมื่อ รันไทม์รับการควบคุมทิศทางในเทิร์นเดียวกันไม่ได้

steer ไม่ยกเลิกเครื่องมือที่กำลังทำงานอยู่ ใช้ /queue interrupt เมื่อข้อความ ล่าสุดควรยกเลิกการรันปัจจุบัน

ลำดับความสำคัญ

สำหรับการเลือกโหมด OpenClaw จะใช้ลำดับดังนี้:

  1. การ override /queue แบบอินไลน์หรือที่จัดเก็บไว้ต่อเซสชัน
  2. messages.queue.byChannel.<channel>
  3. messages.queue.mode
  4. ค่าเริ่มต้น 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 ขณะที่เซสชันยังไม่เปลี่ยนแปลง

ที่เกี่ยวข้อง

Was this useful?
On this page

On this page