Messages and delivery

คิวคำสั่ง

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

เหตุผล

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

วิธีการทำงาน

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

ค่าเริ่มต้น

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

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

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

โหมดคิว

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

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

สำหรับช่วงเวลาและพฤติกรรมของการขึ้นต่อกันเฉพาะรันไทม์ โปรดดู คิวควบคุมทิศทาง สำหรับคำสั่ง /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. การแทนที่ /queue แบบอินไลน์หรือที่จัดเก็บไว้สำหรับแต่ละเซสชัน
  2. messages.queue.byChannel.<channel>
  3. messages.queue.mode
  4. ค่าเริ่มต้น steer

สำหรับตัวเลือก ตัวเลือก /queue แบบอินไลน์หรือที่จัดเก็บไว้จะมีลำดับความสำคัญเหนือการกำหนดค่า จากนั้นจึงใช้การหน่วงเฉพาะช่องทาง (messages.queue.debounceMsByChannel) ค่าเริ่มต้นการหน่วงของ Plugin ตัวเลือก messages.queue ส่วนกลาง และค่าเริ่มต้นในตัว ตามลำดับดังกล่าว cap และ drop เป็นตัวเลือกส่วนกลาง/เซสชัน ไม่ใช่คีย์การกำหนดค่าเฉพาะช่องทาง

การแทนที่ต่อเซสชัน

  • ส่ง /queue <steer|followup|collect|interrupt> เป็นคำสั่งเดี่ยวเพื่อจัดเก็บโหมดคิวสำหรับเซสชันปัจจุบัน
  • สามารถใช้ตัวเลือกร่วมกันได้: /queue collect debounce:0.5s cap:25 drop:summarize
  • /queue default หรือ /queue reset จะล้างการแทนที่ของเซสชัน

การยกเลิกเทิร์นที่เข้าคิว

ขณะที่พรอมต์อยู่ในคิวติดตามผล/รวบรวม (ตัวอย่างเช่น chat.send จาก TUI หรือ เว็บแชตที่มาถึงขณะที่อีกเทิร์นหนึ่งกำลังทำงาน) Gateway จะเก็บ ข้อมูลประจำตัวสำหรับการยกเลิกที่ Gateway เป็นเจ้าของ สำหรับ runId ของไคลเอนต์นั้นไว้จนกว่าเนื้อหาที่เข้าคิว จะทำงานหรือถูกทิ้ง ข้อมูลประจำตัวนี้จะติดตามเนื้อหาที่ถูกรวมเข้าใน สรุปเมื่อเกินขีดจำกัด

  • chat.abort ที่ระบุ runId จะยกเลิกเทิร์นนั้นขณะที่ยัง อยู่ในคิว หากผู้ร้องขอได้รับอนุญาต (ใช้กฎความเป็นเจ้าของเดียวกับการรันที่ทำงานอยู่)
  • chat.abort สำหรับเซสชันที่ไม่มี runId จะยกเลิก เทิร์นที่เข้าคิวซึ่งได้รับอนุญาต ก่อน แล้วจึงยกเลิกการรันที่ทำงานอยู่ซึ่งได้รับอนุญาต ลำดับนี้ป้องกันไม่ให้การระบายคิว เลื่อนงานเข้าสู่เซสชันที่หยุดเพียงบางส่วน
  • การล้างคิวทั้งเซสชันโดยไม่ตรวจสอบผู้ร้องขอแต่ละรายไม่ใช่ เส้นทางการหยุดสำหรับเซสชันที่มีเจ้าของหลายราย
  • การรอในคิวจะไม่ถูกแสดงเป็นการรันเอเจนต์ที่ทำงานอยู่สำหรับ sessions.list และ ไม่ได้เป็นเจ้าของความหมายด้านการหมดเวลาของการรันที่ทำงานอยู่ มีเพียงระยะที่ทำงานอยู่เท่านั้นที่เป็นเจ้าของ

ไคลเอนต์ที่ใช้ Gateway (รวมถึง openclaw tui) จะส่งต่อพรอมต์ระหว่างการรันและ ให้ Gateway ใช้โหมดคิว Esc//stop ใช้การยกเลิกในขอบเขตเซสชัน เพื่อไม่ให้การสูญเสียแฮนเดิลภายในเครื่องปล่อยให้พรอมต์ที่ยังอยู่ในคิวทำงานต่อไป

openclaw chat และ openclaw tui --local ใช้โหมดทั้งสี่แบบเดียวกันใน รันไทม์แบบฝัง steer ภายในเครื่องจะแทรกเข้าในการรันแบบฝังที่ทำงานอยู่เมื่อ รันไทม์นั้นรองรับการควบคุมทิศทาง มิฉะนั้นจะกลายเป็นรายการติดตามผล ส่วน followup และ collect ยังคงเป็นงานภายในเครื่องที่รอดำเนินการ และ interrupt จะยกเลิกการรันภายในเครื่องที่ทำงานอยู่ ก่อนเริ่มข้อความใหม่ล่าสุด คำสั่ง /steer <message> โดยตรง ไม่ใช่คำสั่งของโหมดภายในเครื่อง

ขอบเขตและการรับประกัน

  • ใช้กับการรันเอเจนต์ตอบกลับอัตโนมัติในทุกช่องทางขาเข้าที่ใช้ไปป์ไลน์ตอบกลับของ Gateway (เว็บ WhatsApp, Telegram, Slack, Discord, Signal, iMessage, เว็บแชต เป็นต้น)
  • เลนเริ่มต้น (main) ใช้ทั่วทั้งโปรเซสสำหรับขาเข้าและ Heartbeat หลัก ตั้งค่า agents.defaults.maxConcurrent เพื่ออนุญาตให้หลายเซสชันทำงานแบบขนาน
  • อาจมีเลนเพิ่มเติม (เช่น cron, cron-nested, nested, subagent) เพื่อให้งานเบื้องหลังทำงานแบบขนานได้โดยไม่ปิดกั้นการตอบกลับขาเข้า เทิร์นเอเจนต์ Cron แบบแยกจะครองสล็อต cron ขณะที่การทำงานของเอเจนต์ภายในใช้ cron-nested โฟลว์ nested ที่ใช้ร่วมกันและไม่ใช่ Cron จะรักษาพฤติกรรมเลนของตนเอง การรันที่แยกออกมาเหล่านี้จะถูกติดตามเป็น งานเบื้องหลัง
  • เลนต่อเซสชันรับประกันว่าจะมีการรันเอเจนต์เพียงหนึ่งรายการที่แตะเซสชันหนึ่งๆ ในแต่ละครั้ง
  • ไม่มีการขึ้นต่อกันภายนอกหรือเธรดผู้ปฏิบัติงานเบื้องหลัง ใช้เพียง TypeScript และพรอมิส

การแก้ไขปัญหา

  • หากคำสั่งดูเหมือนค้าง ให้เปิดใช้บันทึกแบบละเอียดและค้นหาบรรทัด "queued for ...ms" เพื่อยืนยันว่าคิวกำลังระบาย
  • การรัน Codex app-server ที่ยอมรับเทิร์นแล้วหยุดส่งความคืบหน้าจะถูกอะแดปเตอร์ Codex ขัดจังหวะ เพื่อให้เลนเซสชันที่ทำงานอยู่ถูกปล่อยแทนที่จะรอจนการรันภายนอกหมดเวลา
  • เมื่อเปิดใช้การวินิจฉัย เซสชันที่ยังคงอยู่ใน processing เกินเกณฑ์การเตือนในตัวโดยไม่พบการตอบกลับ เครื่องมือ สถานะ บล็อก หรือความคืบหน้าของ ACP จะถูกจำแนกตามกิจกรรมปัจจุบัน:
    • งานที่ทำงานอยู่และมีความคืบหน้าเมื่อไม่นานมานี้จะบันทึกเป็น session.long_running การเรียกโมเดลแบบเงียบที่มีเจ้าของจะยังคงเป็น session.long_running จนถึงเกณฑ์การยกเลิกในตัวเช่นกัน เพื่อไม่ให้รายงานผู้ให้บริการที่ช้าหรือไม่สตรีมว่าหยุดชะงักเร็วเกินไป
    • งานที่ทำงานอยู่แต่ไม่มีความคืบหน้าเมื่อไม่นานมานี้จะบันทึกเป็น session.stalled ส่วนการเรียกโมเดลที่มีเจ้าของ การเรียกเครื่องมือที่ถูกปิดกั้น และการรันแบบฝังที่หยุดชะงักจะเปลี่ยนเป็น session.stalled เมื่อถึงหรือเกินเกณฑ์การยกเลิก กิจกรรมโมเดล/เครื่องมือเก่าที่ไม่มีเจ้าของจะไม่ถูกซ่อนในฐานะงานที่ทำงานเป็นเวลานาน
    • session.stuck สงวนไว้สำหรับข้อมูลบันทึกสถานะเซสชันเก่าที่กู้คืนได้ รวมถึงเซสชันที่เข้าคิวแต่ไม่ได้ทำงานซึ่งมีกิจกรรมโมเดล/เครื่องมือเก่าที่ไม่มีเจ้าของ
    • session.stuck จะทริกเกอร์การกู้คืนที่สามารถปล่อยเลนเซสชันที่ได้รับผลกระทบเสมอ การจำแนกเป็น session.stalled หลังเกินเกณฑ์การยกเลิก (การเรียกเครื่องมือที่ถูกปิดกั้น การเรียกโมเดลที่หยุดชะงัก หรือการรันแบบฝังที่หยุดชะงัก) ยังสามารถทริกเกอร์การกู้คืนด้วยการยกเลิกงานที่ทำงานอยู่ได้ ดังนั้นการจำแนกทั้งสองประเภทจึงสามารถแก้คิวที่ค้างได้ ไม่ใช่เฉพาะ session.stuck
    • บรรทัดบันทึกคำเตือน session.stuck และ session.long_running ที่เกิดซ้ำจะเพิ่มช่วงหน่วงแบบเอ็กซ์โพเนนเชียลตราบใดที่เซสชันยังไม่เปลี่ยนแปลง อย่างไรก็ตาม ความพยายามกู้คืนยังคงทำงานในทุกจังหวะ Heartbeat โดยไม่ขึ้นกับช่วงหน่วงดังกล่าว

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

Was this useful?
On this page

On this page