docs/docs/th/concepts/queue.md
2026-05-04 02:30:14 +00:00

16 KiB

read_when summary title x-i18n
การเปลี่ยนการดำเนินการหรือการทำงานพร้อมกันของการตอบกลับอัตโนมัติ
อธิบายโหมดของ /queue หรือพฤติกรรมการกำหนดทิศทางข้อความ
โหมดคิวการตอบกลับอัตโนมัติ ค่าเริ่มต้น และการแทนที่ต่อเซสชัน คิวคำสั่ง
generated_at model provider source_hash source_path workflow
2026-05-04T02:23:43Z gpt-5.5 openai 085aebe7059020f027eb08bb382cce2d253ea117eed0ca77d6ffd208f295acb1 concepts/queue.md 16

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

เหตุผล

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

วิธีทำงาน

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

ค่าเริ่มต้น

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

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

steer เป็นค่าเริ่มต้นเพราะช่วยให้รอบของโมเดลที่กำลังทำงานตอบสนองได้ดี โดยไม่เริ่มการรันเซสชันที่สอง ระบบจะระบายข้อความ steering ทั้งหมดที่มาถึงก่อน boundary ของโมเดลถัดไป หากการรันปัจจุบันรับ steering ไม่ได้ OpenClaw จะ fallback ไปยังรายการคิว followup

โหมดคิว

ข้อความขาเข้าสามารถ steer การรันปัจจุบัน, รอรอบ followup หรือทำทั้งสองอย่างได้:

  • steer: เข้าคิวข้อความ steering เข้าไปใน runtime ที่กำลังทำงานอยู่ Pi จะส่งข้อความ steering ที่รออยู่ทั้งหมด หลังจากรอบ assistant ปัจจุบันเรียกใช้เครื่องมือเสร็จสิ้นแล้ว ก่อนการเรียก LLM ครั้งถัดไป; Codex app-server จะได้รับ turn/steer แบบแบตช์หนึ่งรายการ หากการรันไม่ได้ streaming อยู่จริงหรือ steering ไม่พร้อมใช้งาน OpenClaw จะ fallback ไปยังรายการคิว followup
  • queue (เดิม): steering แบบทีละรายการเก่า Pi จะส่งข้อความ steering ที่เข้าคิวไว้หนึ่งข้อความที่แต่ละ boundary ของโมเดล; Codex app-server จะได้รับคำขอ turn/steer แยกกัน ควรใช้ steer เว้นแต่คุณต้องการพฤติกรรมแบบเรียงลำดับเดิม
  • followup: เข้าคิวแต่ละข้อความสำหรับรอบเอเจนต์ภายหลังหลังจากการรันปัจจุบันสิ้นสุด
  • collect: รวมข้อความที่เข้าคิวไว้เป็นรอบ followup เดียว หลังช่วงเวลาที่เงียบลง หากข้อความชี้ไปยังช่องทาง/เธรดต่างกัน จะระบายแยกกันเพื่อรักษาการกำหนดเส้นทาง
  • steer-backlog (หรือ steer+backlog): steer ทันที และ เก็บข้อความเดียวกันไว้สำหรับรอบ followup
  • interrupt (เดิม): ยกเลิกการรันที่กำลังทำงานอยู่สำหรับเซสชันนั้น แล้วรันข้อความล่าสุด

Steer-backlog หมายความว่าคุณอาจได้รับการตอบกลับ followup หลังการรันที่ถูก steer ดังนั้นพื้นผิว streaming อาจดูเหมือนมีรายการซ้ำ ควรใช้ collect/steer หากคุณต้องการการตอบกลับหนึ่งรายการต่อข้อความขาเข้าหนึ่งข้อความ

สำหรับ timing และพฤติกรรม dependency เฉพาะ runtime โปรดดู คิว Steering สำหรับคำสั่ง /steer <message> แบบชัดเจน โปรดดู Steer

กำหนดค่าแบบส่วนกลางหรือต่อช่องทางผ่าน messages.queue:

{
  messages: {
    queue: {
      mode: "steer",
      debounceMs: 500,
      cap: 20,
      drop: "summarize",
      byChannel: { discord: "collect" },
    },
  },
}

ตัวเลือกคิว

ตัวเลือกใช้กับ followup, collect และ steer-backlog (และกับ steer หรือ queue เดิมเมื่อ steering fallback ไปเป็น followup):

  • debounceMs: ช่วงเวลาที่เงียบลงก่อนระบาย followup ที่เข้าคิวไว้ ตัวเลขล้วนคือมิลลิวินาที; ตัวเลือก /queue รับหน่วย ms, s, m, h และ d
  • cap: จำนวนข้อความสูงสุดที่เข้าคิวได้ต่อเซสชัน ค่าต่ำกว่า 1 จะถูกละเว้น
  • drop: "summarize": ค่าเริ่มต้น ทิ้งรายการที่เข้าคิวเก่าที่สุดตามจำเป็น เก็บสรุปแบบย่อไว้ และฉีดเข้าไปเป็นพรอมป์ followup สังเคราะห์
  • drop: "old": ทิ้งรายการที่เข้าคิวเก่าที่สุดตามจำเป็น โดยไม่เก็บสรุปไว้
  • drop: "new": ปฏิเสธข้อความล่าสุดเมื่อคิวเต็มอยู่แล้ว

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

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

สำหรับการเลือกโหมด OpenClaw จะ resolve ตามลำดับ:

  1. override /queue แบบ inline หรือที่จัดเก็บไว้ต่อเซสชัน
  2. messages.queue.byChannel.<channel>
  3. messages.queue.mode
  4. ค่าเริ่มต้น steer

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

override ต่อเซสชัน

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

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

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

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

  • หากคำสั่งดูเหมือนค้าง ให้เปิดใช้บันทึกแบบละเอียดแล้วมองหาบรรทัด “queued for …ms” เพื่อยืนยันว่าคิวกำลังระบาย
  • หากคุณต้องการความลึกของคิว ให้เปิดใช้บันทึกแบบละเอียดแล้วดูบรรทัด timing ของคิว
  • การรัน Codex app-server ที่รับ turn แล้วหยุดส่ง progress จะถูก interrupt โดย Codex adapter เพื่อให้ lane ของเซสชันที่กำลังทำงานอยู่ปล่อยได้ แทนที่จะรอ timeout ของการรันชั้นนอก
  • เมื่อเปิดใช้ diagnostics เซสชันที่ยังอยู่ใน processing เกิน diagnostics.stuckSessionWarnMs โดยไม่พบ reply, tool, status, block หรือ progress ของ ACP จะถูกจัดประเภทตามกิจกรรมปัจจุบัน งานที่ยัง active จะบันทึกเป็น session.long_running; งานที่ยัง active แต่ไม่มี progress ล่าสุดจะบันทึกเป็น session.stalled; session.stuck สงวนไว้สำหรับ bookkeeping ของเซสชันที่ค้างเก่าโดยไม่มีงาน active และมีเพียงเส้นทางนั้นเท่านั้นที่ปล่อย lane ของเซสชันที่ได้รับผลกระทบได้ เพื่อให้งานที่เข้าคิวไว้ระบายต่อ diagnostics session.stuck ที่เกิดซ้ำจะ back off ขณะที่เซสชันยังไม่เปลี่ยนแปลง

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