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

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

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

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

Was this useful?
On this page

On this page