Technical reference

เจาะลึกการจัดการเซสชัน

OpenClaw จัดการเซสชันแบบครบวงจรในพื้นที่เหล่านี้:

  • การกำหนดเส้นทางเซสชัน (วิธีที่ข้อความขาเข้าแมปกับ sessionKey)
  • ที่เก็บเซสชัน (sessions.json) และสิ่งที่ติดตาม
  • การคงอยู่ของทรานสคริปต์ (*.jsonl) และโครงสร้างของมัน
  • สุขอนามัยของทรานสคริปต์ (การแก้ไขเฉพาะผู้ให้บริการก่อนรัน)
  • ขีดจำกัดบริบท (หน้าต่างบริบทเทียบกับโทเค็นที่ติดตาม)
  • Compaction (Compaction แบบแมนนวลและอัตโนมัติ) และตำแหน่งสำหรับผูกงานก่อน Compaction
  • งานดูแลเงียบ (การเขียนหน่วยความจำที่ไม่ควรสร้างเอาต์พุตที่ผู้ใช้เห็นได้)

หากคุณต้องการภาพรวมระดับสูงก่อน ให้เริ่มด้วย:


แหล่งความจริง: Gateway

OpenClaw ถูกออกแบบรอบ กระบวนการ Gateway เดียวที่เป็นเจ้าของสถานะเซสชัน

  • UI (แอป macOS, Control UI บนเว็บ, TUI) ควรสอบถาม Gateway สำหรับรายการเซสชันและจำนวนโทเค็น
  • ในโหมดระยะไกล ไฟล์เซสชันอยู่บนโฮสต์ระยะไกล; "การตรวจไฟล์ Mac ในเครื่องของคุณ" จะไม่สะท้อนสิ่งที่ Gateway กำลังใช้

เลเยอร์การคงอยู่สองชั้น

OpenClaw คงอยู่เซสชันไว้ในสองเลเยอร์:

  1. ที่เก็บเซสชัน (sessions.json)

    • แมปคีย์/ค่า: sessionKey -> SessionEntry
    • ขนาดเล็ก เปลี่ยนแปลงได้ แก้ไขได้ปลอดภัย (หรือลบรายการได้)
    • ติดตามเมตาดาต้าเซสชัน (รหัสเซสชันปัจจุบัน กิจกรรมล่าสุด สวิตช์ ตัวนับโทเค็น ฯลฯ)
  2. ทรานสคริปต์ (<sessionId>.jsonl)

    • ทรานสคริปต์แบบผนวกอย่างเดียวพร้อมโครงสร้างแบบต้นไม้ (รายการมี id + parentId)
    • เก็บบทสนทนาจริง + การเรียกเครื่องมือ + สรุป Compaction
    • ใช้สร้างบริบทโมเดลใหม่สำหรับเทิร์นในอนาคต
    • จุดตรวจดีบักขนาดใหญ่ก่อน Compaction จะถูกข้ามเมื่อทรานสคริปต์ที่ใช้งานอยู่ เกินเพดานขนาดจุดตรวจ เพื่อหลีกเลี่ยงการคัดลอก .checkpoint.*.jsonl ขนาดใหญ่อีกชุด

ตัวอ่านประวัติของ Gateway ควรหลีกเลี่ยงการทำให้ทรานสคริปต์ทั้งหมดอยู่ในหน่วยความจำ เว้นแต่ พื้นผิวนั้นต้องการการเข้าถึงประวัติใดๆ โดยชัดเจน ประวัติหน้าแรก ประวัติแชทแบบฝัง การกู้คืนหลังรีสตาร์ต และการตรวจโทเค็น/การใช้งานใช้การอ่านส่วนท้าย แบบมีขอบเขต การสแกนทรานสคริปต์ทั้งหมดจะผ่านดัชนีทรานสคริปต์แบบ async ซึ่ง แคชด้วยพาธไฟล์บวก mtimeMs/size และแชร์ระหว่างตัวอ่านพร้อมกัน


ตำแหน่งบนดิสก์

ต่อเอเจนต์ บนโฮสต์ Gateway:

  • ที่เก็บ: ~/.openclaw/agents/<agentId>/sessions/sessions.json
  • ทรานสคริปต์: ~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl
    • เซสชันหัวข้อ Telegram: .../<sessionId>-topic-<threadId>.jsonl

OpenClaw แก้ตำแหน่งเหล่านี้ผ่าน src/config/sessions.ts


การบำรุงรักษาที่เก็บและการควบคุมดิสก์

การคงอยู่ของเซสชันมีการควบคุมการบำรุงรักษาอัตโนมัติ (session.maintenance) สำหรับ sessions.json, อาร์ติแฟกต์ทรานสคริปต์ และไซด์คาร์ trajectory:

  • mode: warn (ค่าเริ่มต้น) หรือ enforce
  • pruneAfter: เกณฑ์อายุของรายการที่เก่าเกิน (ค่าเริ่มต้น 30d)
  • maxEntries: จำกัดจำนวนรายการใน sessions.json (ค่าเริ่มต้น 500)
  • resetArchiveRetention: ระยะเวลาเก็บถาวรสำหรับไฟล์เก็บถาวรทรานสคริปต์ *.reset.<timestamp> (ค่าเริ่มต้น: เหมือน pruneAfter; false ปิดการล้าง)
  • maxDiskBytes: งบประมาณไดเรกทอรีเซสชันแบบไม่บังคับ
  • highWaterBytes: เป้าหมายแบบไม่บังคับหลังล้างข้อมูล (ค่าเริ่มต้น 80% ของ maxDiskBytes)

การเขียน Gateway ปกติไหลผ่านตัวเขียนเซสชันต่อที่เก็บที่ทำให้การเปลี่ยนแปลงในกระบวนการเป็นลำดับ โดยไม่ใช้ล็อกไฟล์ขณะรัน ตัวช่วยแพตช์ในเส้นทางร้อนจะยืมแคชที่เปลี่ยนแปลงได้และผ่านการตรวจสอบแล้วในขณะที่ถือสล็อตตัวเขียนนั้น ดังนั้นไฟล์ sessions.json ขนาดใหญ่จะไม่ถูกโคลนหรืออ่านซ้ำสำหรับทุกการอัปเดตเมตาดาต้า โค้ดขณะรันควรใช้ updateSessionStore(...) หรือ updateSessionStoreEntry(...); การบันทึกทั้งที่เก็บโดยตรงเป็นเครื่องมือสำหรับความเข้ากันได้และการบำรุงรักษาแบบออฟไลน์ เมื่อเข้าถึง Gateway ได้ openclaw sessions cleanup และ openclaw agents delete ที่ไม่ใช่ dry-run จะมอบหมายการเปลี่ยนแปลงที่เก็บให้ Gateway เพื่อให้การล้างเข้าคิวตัวเขียนเดียวกัน; --store <path> คือเส้นทางซ่อมออฟไลน์ที่ชัดเจนสำหรับการบำรุงรักษาไฟล์โดยตรง การล้าง maxEntries ยังทำแบบแบตช์สำหรับเพดานขนาดโปรดักชัน ดังนั้นที่เก็บอาจเกินเพดานที่กำหนดไว้ชั่วครู่ก่อนที่การล้าง high-water ครั้งถัดไปจะเขียนกลับลงมา การอ่านที่เก็บเซสชันไม่ตัดแต่งหรือจำกัดรายการระหว่างการเริ่มต้น Gateway; ใช้การเขียนหรือ openclaw sessions cleanup --enforce สำหรับการล้าง openclaw sessions cleanup --enforce ยังคงใช้เพดานที่กำหนดทันที และตัดแต่งอาร์ติแฟกต์ทรานสคริปต์ จุดตรวจ และ trajectory เก่าที่ไม่มีการอ้างอิง แม้ไม่ได้กำหนดงบประมาณดิสก์ไว้

การบำรุงรักษาจะเก็บตัวชี้บทสนทนาภายนอกที่ทนทาน เช่น เซสชันกลุ่ม และเซสชันแชทที่จำกัดตามเธรด แต่รายการรันไทม์สังเคราะห์สำหรับ Cron, hooks, Heartbeat, ACP และซับเอเจนต์ยังถูกลบได้เมื่อเกิน อายุ จำนวน หรืองบประมาณดิสก์ที่กำหนดค่าไว้

OpenClaw ไม่สร้างข้อมูลสำรองหมุนเวียน sessions.json.bak.* อัตโนมัติระหว่างการเขียน Gateway อีกต่อไป คีย์เดิม session.maintenance.rotateBytes จะถูกละเว้น และ openclaw doctor --fix จะลบออกจากคอนฟิกเก่า

การเปลี่ยนแปลงทรานสคริปต์ใช้ล็อกการเขียนเซสชันบนไฟล์ทรานสคริปต์ การขอล็อกรอได้สูงสุด session.writeLock.acquireTimeoutMs ก่อนแสดงข้อผิดพลาดเซสชันไม่ว่าง; ค่าเริ่มต้นคือ 60000 มิลลิวินาที เพิ่มค่านี้เฉพาะเมื่อมีงานเตรียม ล้างข้อมูล Compaction หรือมิเรอร์ทรานสคริปต์ที่ถูกต้อง แย่งล็อกนานกว่าบนเครื่องช้า การตรวจจับล็อกค้างและคำเตือนการถือครองสูงสุดยังคงเป็นนโยบายแยกกัน

ลำดับการบังคับใช้สำหรับการล้างงบประมาณดิสก์ (mode: "enforce"):

  1. ลบอาร์ติแฟกต์ที่เก็บถาวร ทรานสคริปต์กำพร้า หรือ trajectory กำพร้าที่เก่าที่สุดก่อน
  2. หากยังเกินเป้าหมาย ให้ขับรายการเซสชันที่เก่าที่สุดและไฟล์ทรานสคริปต์/trajectory ของรายการนั้นออก
  3. ทำต่อจนกว่าการใช้งานจะอยู่ที่หรือต่ำกว่า highWaterBytes

ใน mode: "warn" OpenClaw รายงานการขับออกที่อาจเกิดขึ้น แต่ไม่เปลี่ยนแปลงที่เก็บ/ไฟล์

รันการบำรุงรักษาตามต้องการ:

openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce

เซสชัน Cron และบันทึกการรัน

การรัน Cron แบบแยกยังสร้างรายการเซสชัน/ทรานสคริปต์ด้วย และมีการควบคุมการเก็บรักษาเฉพาะ:

  • cron.sessionRetention (ค่าเริ่มต้น 24h) ตัดแต่งเซสชันการรัน Cron แบบแยกที่เก่าจากที่เก็บเซสชัน (false ปิดใช้งาน)
  • cron.runLog.maxBytes + cron.runLog.keepLines ตัดแต่งไฟล์ ~/.openclaw/cron/runs/<jobId>.jsonl (ค่าเริ่มต้น: 2_000_000 ไบต์และ 2000 บรรทัด)

เมื่อ Cron บังคับสร้างเซสชันการรันแบบแยกใหม่ มันจะทำความสะอาดรายการเซสชัน cron:<jobId> ก่อนหน้าก่อนเขียนแถวใหม่ มันนำค่ากำหนดที่ปลอดภัย เช่น การตั้งค่า thinking/fast/verbose ป้ายกำกับ และการแทนที่โมเดล/การยืนยันตัวตน ที่ผู้ใช้เลือกอย่างชัดเจนไปด้วย มันทิ้งบริบทบทสนทนาแวดล้อม เช่น การกำหนดเส้นทางช่อง/กลุ่ม นโยบายส่งหรือคิว elevation, origin และการผูก รันไทม์ ACP เพื่อให้การรันแบบแยกใหม่ไม่สามารถสืบทอดการส่งมอบหรือ อำนาจรันไทม์ที่ค้างจากการรันเก่าได้


คีย์เซสชัน (sessionKey)

sessionKey ระบุว่า คุณอยู่ในบักเก็ตบทสนทนาใด (การกำหนดเส้นทาง + การแยก)

รูปแบบทั่วไป:

  • แชทหลัก/โดยตรง (ต่อเอเจนต์): agent:<agentId>:<mainKey> (ค่าเริ่มต้น main)
  • กลุ่ม: agent:<agentId>:<channel>:group:<id>
  • ห้อง/ช่อง (Discord/Slack): agent:<agentId>:<channel>:channel:<id> หรือ ...:room:<id>
  • Cron: cron:<job.id>
  • Webhook: hook:<uuid> (เว้นแต่ถูกแทนที่)

กฎมาตรฐานมีเอกสารไว้ที่ /concepts/session


รหัสเซสชัน (sessionId)

แต่ละ sessionKey ชี้ไปยัง sessionId ปัจจุบัน (ไฟล์ทรานสคริปต์ที่ดำเนินบทสนทนาต่อ)

หลักทั่วไป:

  • รีเซ็ต (/new, /reset) สร้าง sessionId ใหม่สำหรับ sessionKey นั้น
  • รีเซ็ตรายวัน (ค่าเริ่มต้น 4:00 น. ตามเวลาท้องถิ่นบนโฮสต์ Gateway) สร้าง sessionId ใหม่ในข้อความถัดไปหลังจากขอบเขตรีเซ็ต
  • หมดอายุเมื่อไม่มีการใช้งาน (session.reset.idleMinutes หรือเดิม session.idleMinutes) สร้าง sessionId ใหม่เมื่อข้อความมาถึงหลังหน้าต่างไม่มีการใช้งาน เมื่อกำหนดค่าทั้งรายวัน + ไม่มีการใช้งาน ตัวที่หมดอายุก่อนจะชนะ
  • เหตุการณ์ระบบ (Heartbeat, การปลุก Cron, การแจ้งเตือน exec, งาน bookkeeping ของ Gateway) อาจเปลี่ยนแถวเซสชัน แต่ไม่ขยายความสดของการรีเซ็ตรายวัน/ไม่มีการใช้งาน การเลื่อนรีเซ็ตจะทิ้งประกาศเหตุการณ์ระบบที่อยู่ในคิวสำหรับเซสชันก่อนหน้า ก่อนสร้างพรอมป์ใหม่
  • นโยบาย fork จากพาเรนต์ ใช้กิ่งที่ใช้งานอยู่ของ PI เมื่อสร้าง fork ของเธรดหรือซับเอเจนต์ หากกิ่งนั้นใหญ่เกินไป OpenClaw จะเริ่มลูกด้วยบริบทแบบแยก แทนที่จะล้มเหลวหรือสืบทอดประวัติที่ใช้งานไม่ได้ นโยบายการวัดขนาดเป็นอัตโนมัติ; คอนฟิกเดิม session.parentForkMaxTokens ถูกลบโดย openclaw doctor --fix

รายละเอียดการใช้งาน: การตัดสินใจเกิดขึ้นใน initSessionState() ใน src/auto-reply/reply/session.ts


สคีมาที่เก็บเซสชัน (sessions.json)

ชนิดค่าของที่เก็บคือ SessionEntry ใน src/config/sessions.ts

ฟิลด์สำคัญ (ไม่ครบทั้งหมด):

  • sessionId: รหัสทรานสคริปต์ปัจจุบัน (ชื่อไฟล์ได้มาจากค่านี้ เว้นแต่ตั้งค่า sessionFile)
  • sessionStartedAt: ประทับเวลาเริ่มต้นสำหรับ sessionId ปัจจุบัน; ความสดของการรีเซ็ตรายวัน ใช้ค่านี้ แถวเดิมอาจได้ค่านี้จากส่วนหัวเซสชัน JSONL
  • lastInteractionAt: ประทับเวลาของการโต้ตอบผู้ใช้/ช่องจริงครั้งล่าสุด; ความสดของการรีเซ็ต เมื่อไม่มีการใช้งานใช้ค่านี้ เพื่อให้ Heartbeat, Cron และเหตุการณ์ exec ไม่คงเซสชัน ให้มีชีวิตอยู่ แถวเดิมที่ไม่มีฟิลด์นี้จะ fallback ไปยังเวลาเริ่มต้นเซสชันที่กู้คืน สำหรับความสดเมื่อไม่มีการใช้งาน
  • updatedAt: ประทับเวลาการเปลี่ยนแปลงแถวที่เก็บล่าสุด ใช้สำหรับการแสดงรายการ การตัดแต่ง และ bookkeeping ค่านี้ไม่ใช่แหล่งอำนาจสำหรับความสดของการรีเซ็ตรายวัน/ไม่มีการใช้งาน
  • sessionFile: การแทนที่พาธทรานสคริปต์ที่ชัดเจนแบบไม่บังคับ
  • chatType: direct | group | room (ช่วย UI และนโยบายส่ง)
  • provider, subject, room, space, displayName: เมตาดาต้าสำหรับการติดป้ายกลุ่ม/ช่อง
  • สวิตช์:
    • thinkingLevel, verboseLevel, reasoningLevel, elevatedLevel
    • sendPolicy (การแทนที่ต่อเซสชัน)
  • การเลือกโมเดล:
    • providerOverride, modelOverride, authProfileOverride
  • ตัวนับโทเค็น (best-effort / ขึ้นกับผู้ให้บริการ):
    • inputTokens, outputTokens, totalTokens, contextTokens
  • compactionCount: จำนวนครั้งที่ auto-compaction เสร็จสมบูรณ์สำหรับคีย์เซสชันนี้
  • memoryFlushAt: ประทับเวลาสำหรับการ flush หน่วยความจำก่อน Compaction ครั้งล่าสุด
  • memoryFlushCompactionCount: จำนวน Compaction เมื่อการ flush ครั้งล่าสุดรัน

ที่เก็บแก้ไขได้ปลอดภัย แต่ Gateway คือแหล่งอำนาจ: มันอาจเขียนใหม่หรือเติมข้อมูลรายการอีกครั้งขณะเซสชันรัน


โครงสร้างทรานสคริปต์ (*.jsonl)

ทรานสคริปต์จัดการโดย SessionManager ของ @mariozechner/pi-coding-agent

ไฟล์เป็น JSONL:

  • บรรทัดแรก: ส่วนหัวเซสชัน (type: "session", มี id, cwd, timestamp, parentSession แบบไม่บังคับ)
  • จากนั้น: รายการเซสชันที่มี id + parentId (ต้นไม้)

ชนิดรายการที่น่าสนใจ:

  • message: ข้อความ user/assistant/toolResult
  • custom_message: ข้อความที่ส่วนขยายแทรกเข้ามาซึ่ง เข้า บริบทโมเดล (ซ่อนได้จาก UI)
  • custom: สถานะส่วนขยายที่ ไม่ เข้าในบริบทโมเดล
  • compaction: สรุป Compaction ที่คงอยู่พร้อม firstKeptEntryId และ tokensBefore
  • branch_summary: สรุปที่คงอยู่เมื่อนำทางกิ่งของต้นไม้

OpenClaw ตั้งใจ ไม่ "แก้ไข" ทรานสคริปต์; Gateway ใช้ SessionManager เพื่ออ่าน/เขียนทรานสคริปต์


หน้าต่างบริบทเทียบกับโทเค็นที่ติดตาม

แนวคิดสองอย่างที่สำคัญ:

  1. หน้าต่างบริบทของโมเดล: เพดานแข็งต่อโมเดล (โทเค็นที่โมเดลมองเห็น)
  2. ตัวนับในที่เก็บเซสชัน: สถิติแบบ rolling ที่เขียนลง sessions.json (ใช้สำหรับ /status และแดชบอร์ด)

หากคุณกำลังปรับขีดจำกัด:

  • หน้าต่างบริบทมาจากแค็ตตาล็อกโมเดล (และแทนที่ได้ผ่านคอนฟิก)
  • contextTokens ในที่เก็บคือค่าประมาณ/ค่ารายงานขณะรัน; อย่าถือเป็นการรับประกันที่เข้มงวด

สำหรับข้อมูลเพิ่มเติม ดู /token-use


Compaction: คืออะไร

Compaction สรุปบทสนทนาเก่าลงในรายการ compaction ที่คงอยู่ในทรานสคริปต์ และคงข้อความล่าสุดไว้เหมือนเดิม

หลัง Compaction เทิร์นในอนาคตจะเห็น:

  • สรุป Compaction
  • ข้อความหลัง firstKeptEntryId

Compaction เป็นแบบ persistent (ต่างจากการตัดแต่งเซสชัน) ดู /concepts/session-pruning

ขอบเขตชังก์ Compaction และการจับคู่เครื่องมือ

เมื่อ OpenClaw แยกทรานสคริปต์ยาวออกเป็นชังก์ Compaction จะเก็บ การเรียกเครื่องมือของผู้ช่วยให้จับคู่กับรายการ toolResult ที่ตรงกัน

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

เมื่อเกิด auto-compaction (รันไทม์ Pi)

ในเอเจนต์ Pi แบบฝังตัว auto-compaction จะถูกทริกเกอร์ในสองกรณี:

  1. การกู้คืนจากการล้น: โมเดลคืนข้อผิดพลาดบริบทล้น (request_too_large, context length exceeded, input exceeds the maximum number of tokens, input token count exceeds the maximum number of input tokens, input is too long for the model, ollama error: context length exceeded และตัวแปรลักษณะเดียวกันตามรูปแบบของผู้ให้บริการ) → compact → ลองใหม่
  2. การบำรุงรักษาตามเกณฑ์: หลังจากเทิร์นสำเร็จ เมื่อ:

contextTokens > contextWindow - reserveTokens

โดยที่:

  • contextWindow คือหน้าต่างบริบทของโมเดล
  • reserveTokens คือพื้นที่เผื่อที่สงวนไว้สำหรับพรอมป์ + เอาต์พุตโมเดลถัดไป

นี่คือซีแมนติกของรันไทม์ Pi (OpenClaw ใช้อีเวนต์ แต่ Pi เป็นผู้ตัดสินใจว่าจะ compact เมื่อใด)

OpenClaw ยังสามารถทริกเกอร์ Compaction เฉพาะเครื่องแบบ preflight ก่อนเปิดการรันถัดไป เมื่อมีการตั้งค่า agents.defaults.compaction.maxActiveTranscriptBytes และไฟล์ทรานสคริปต์ ที่ใช้งานอยู่ถึงขนาดนั้น นี่เป็นการ์ดขนาดไฟล์สำหรับต้นทุนการเปิดใหม่เฉพาะเครื่อง ไม่ใช่การเก็บถาวรแบบดิบ: OpenClaw ยังคงรัน semantic compaction ตามปกติ และต้องใช้ truncateAfterCompaction เพื่อให้สรุปที่ compact แล้วกลายเป็น ทรานสคริปต์ตัวสืบทอดใหม่ได้

สำหรับการรัน Pi แบบฝังตัว agents.defaults.compaction.midTurnPrecheck.enabled: true จะเพิ่มการ์ดลูปเครื่องมือแบบเลือกเปิดใช้ หลังจากเพิ่มผลลัพธ์เครื่องมือแล้วและก่อนการเรียก โมเดลครั้งถัดไป OpenClaw จะประเมินแรงกดดันของพรอมป์โดยใช้ตรรกะงบประมาณ preflight เดียวกับที่ใช้ตอนเริ่มเทิร์น หากบริบทไม่พอดีอีกต่อไป การ์ดจะไม่ compact ภายใน hook transformContext ของ Pi แต่จะส่งสัญญาณ precheck กลางเทิร์นแบบมีโครงสร้าง หยุดการส่งพรอมป์ปัจจุบัน และปล่อยให้ลูปการรันภายนอกใช้เส้นทางกู้คืนเดิม: ตัดผลลัพธ์เครื่องมือที่ใหญ่เกินเมื่อเพียงพอ หรือทริกเกอร์โหมด Compaction ที่กำหนดค่าไว้แล้วลองใหม่ ตัวเลือกนี้ปิดอยู่ตามค่าเริ่มต้นและทำงานได้กับโหมด Compaction ทั้ง default และ safeguard รวมถึง Compaction แบบ safeguard ที่มีผู้ให้บริการรองรับ สิ่งนี้เป็นอิสระจาก maxActiveTranscriptBytes: การ์ดขนาดไบต์จะรัน ก่อนเปิดเทิร์น ขณะที่ precheck กลางเทิร์นจะรันภายหลังในลูปเครื่องมือ Pi แบบฝังตัว หลังจากมีการเพิ่มผลลัพธ์เครื่องมือใหม่แล้ว


การตั้งค่า Compaction (reserveTokens, keepRecentTokens)

การตั้งค่า Compaction ของ Pi อยู่ในการตั้งค่า Pi:

{
  compaction: {
    enabled: true,
    reserveTokens: 16384,
    keepRecentTokens: 20000,
  },
}

OpenClaw ยังบังคับใช้ค่าพื้นความปลอดภัยสำหรับการรันแบบฝังตัวด้วย:

  • หาก compaction.reserveTokens < reserveTokensFloor OpenClaw จะปรับเพิ่มให้
  • ค่าพื้นเริ่มต้นคือ 20000 โทเค็น
  • ตั้งค่า agents.defaults.compaction.reserveTokensFloor: 0 เพื่อปิดค่าพื้น
  • หากค่าสูงกว่าอยู่แล้ว OpenClaw จะปล่อยไว้ตามเดิม
  • /compact แบบแมนนวลจะเคารพ agents.defaults.compaction.keepRecentTokens ที่กำหนดชัดเจน และคงจุดตัดส่วนท้ายล่าสุดของ Pi ไว้ หากไม่มีงบประมาณการเก็บไว้ที่กำหนดชัดเจน Compaction แบบแมนนวลจะยังคงเป็นจุดตรวจสอบแบบแข็ง และบริบทที่สร้างใหม่จะเริ่มจาก สรุปใหม่
  • ตั้งค่า agents.defaults.compaction.midTurnPrecheck.enabled: true เพื่อรัน precheck ลูปเครื่องมือแบบเลือกเปิดใช้หลังจากผลลัพธ์เครื่องมือใหม่และก่อนการเรียกโมเดลถัดไป นี่เป็นเพียงทริกเกอร์เท่านั้น การสร้างสรุปยังคงใช้เส้นทาง Compaction ที่กำหนดค่าไว้ เป็นอิสระจาก maxActiveTranscriptBytes ซึ่งเป็น การ์ดขนาดไบต์ของทรานสคริปต์ที่ใช้งานอยู่ตอนเริ่มเทิร์น
  • ตั้งค่า agents.defaults.compaction.maxActiveTranscriptBytes เป็นค่าไบต์หรือ สตริงเช่น "20mb" เพื่อรัน Compaction เฉพาะเครื่องก่อนเทิร์น เมื่อทรานสคริปต์ ที่ใช้งานอยู่มีขนาดใหญ่ขึ้น การ์ดนี้ทำงานเฉพาะเมื่อ เปิดใช้ truncateAfterCompaction ด้วย ปล่อยไว้ไม่ตั้งค่าหรือตั้ง 0 เพื่อ ปิดใช้
  • เมื่อเปิดใช้ agents.defaults.compaction.truncateAfterCompaction OpenClaw จะหมุนเวียนทรานสคริปต์ที่ใช้งานอยู่ไปเป็น JSONL ตัวสืบทอดที่ compact แล้วหลังจาก Compaction ทรานสคริปต์ฉบับเต็มเดิมยังคงถูกเก็บถาวรและลิงก์จาก จุดตรวจสอบ Compaction แทนการเขียนทับในที่เดิม

เหตุผล: เว้นพื้นที่เผื่อให้เพียงพอสำหรับ “งานดูแลระบบ” หลายเทิร์น (เช่น การเขียนหน่วยความจำ) ก่อนที่ Compaction จะหลีกเลี่ยงไม่ได้

การใช้งานจริง: ensurePiCompactionReserveTokens() ใน src/agents/pi-settings.ts (ถูกเรียกจาก src/agents/pi-embedded-runner.ts)


ผู้ให้บริการ Compaction แบบเสียบเพิ่มได้

Plugins สามารถลงทะเบียนผู้ให้บริการ Compaction ผ่าน registerCompactionProvider() บน API ของ Plugin ได้ เมื่อ agents.defaults.compaction.provider ถูกตั้งค่าเป็น id ของผู้ให้บริการที่ลงทะเบียนแล้ว ส่วนขยาย safeguard จะมอบหมายการสรุปให้ผู้ให้บริการนั้นแทนไปป์ไลน์ summarizeInStages ในตัว

  • provider: id ของ Plugin ผู้ให้บริการ Compaction ที่ลงทะเบียนแล้ว ปล่อยไว้ไม่ตั้งค่าสำหรับการสรุปด้วย LLM เริ่มต้น
  • การตั้งค่า provider จะบังคับ mode: "safeguard"
  • ผู้ให้บริการจะได้รับคำสั่ง Compaction และนโยบายการรักษาตัวระบุเดียวกับเส้นทางในตัว
  • safeguard ยังคงรักษาบริบท suffix ของเทิร์นล่าสุดและเทิร์นที่ถูกแบ่งหลังเอาต์พุตจากผู้ให้บริการ
  • การสรุป safeguard ในตัวจะกลั่นสรุปก่อนหน้าใหม่พร้อมกับข้อความใหม่ แทนการรักษาสรุปก่อนหน้าทั้งหมดไว้แบบคำต่อคำ
  • โหมด safeguard เปิดใช้การตรวจสอบคุณภาพสรุปตามค่าเริ่มต้น; ตั้งค่า qualityGuard.enabled: false เพื่อข้ามพฤติกรรมลองใหม่เมื่อเอาต์พุตผิดรูปแบบ
  • หากผู้ให้บริการล้มเหลวหรือคืนผลลัพธ์ว่าง OpenClaw จะถอยกลับไปใช้การสรุปด้วย LLM ในตัวโดยอัตโนมัติ
  • สัญญาณ abort/timeout จะถูกโยนซ้ำ (ไม่ถูกกลืน) เพื่อเคารพการยกเลิกของผู้เรียก

แหล่งที่มา: src/plugins/compaction-provider.ts, src/agents/pi-hooks/compaction-safeguard.ts


พื้นผิวที่ผู้ใช้มองเห็น

คุณสามารถสังเกต Compaction และสถานะเซสชันได้ผ่าน:

  • /status (ในเซสชันแชตใดก็ได้)
  • openclaw status (CLI)
  • openclaw sessions / sessions --json
  • โหมดละเอียด: 🧹 Auto-compaction complete + จำนวน Compaction

งานดูแลระบบแบบเงียบ (NO_REPLY)

OpenClaw รองรับเทิร์น “เงียบ” สำหรับงานเบื้องหลังที่ผู้ใช้ไม่ควรเห็นเอาต์พุตระหว่างทาง

แนวปฏิบัติ:

  • ผู้ช่วยเริ่มเอาต์พุตด้วยโทเค็นเงียบที่ตรงตัว NO_REPLY / no_reply เพื่อระบุว่า “อย่าส่งคำตอบให้ผู้ใช้”
  • OpenClaw จะตัด/ระงับสิ่งนี้ในเลเยอร์การส่งมอบ
  • การระงับโทเค็นเงียบแบบตรงตัวไม่คำนึงถึงตัวพิมพ์เล็กใหญ่ ดังนั้น NO_REPLY และ no_reply จึงนับทั้งคู่เมื่อ payload ทั้งหมดเป็นเพียงโทเค็นเงียบ
  • สิ่งนี้มีไว้สำหรับเทิร์นเบื้องหลัง/ไม่ส่งมอบจริงเท่านั้น ไม่ใช่ทางลัดสำหรับ คำขอผู้ใช้ทั่วไปที่ต้องดำเนินการ

ตั้งแต่ 2026.1.10 OpenClaw ยังระงับ การสตรีมฉบับร่าง/กำลังพิมพ์ เมื่อ ชังก์บางส่วนเริ่มต้นด้วย NO_REPLY เพื่อให้การทำงานแบบเงียบไม่รั่วเอาต์พุตบางส่วน กลางเทิร์น


“การล้างหน่วยความจำ” ก่อน Compaction (ใช้งานแล้ว)

เป้าหมาย: ก่อนเกิด auto-compaction ให้รันเทิร์น agentic แบบเงียบที่เขียนสถานะถาวร ลงดิสก์ (เช่น memory/YYYY-MM-DD.md ในพื้นที่ทำงานของเอเจนต์) เพื่อให้ Compaction ไม่สามารถ ลบบริบทสำคัญได้

OpenClaw ใช้แนวทาง pre-threshold flush:

  1. ตรวจสอบการใช้บริบทของเซสชัน
  2. เมื่อข้าม “soft threshold” (ต่ำกว่าเกณฑ์ Compaction ของ Pi) ให้รันคำสั่ง “write memory now” แบบเงียบไปยังเอเจนต์
  3. ใช้โทเค็นเงียบที่ตรงตัว NO_REPLY / no_reply เพื่อให้ผู้ใช้ไม่เห็น อะไรเลย

การกำหนดค่า (agents.defaults.compaction.memoryFlush):

  • enabled (ค่าเริ่มต้น: true)
  • model (การ override ผู้ให้บริการ/โมเดลแบบตรงตัวที่เป็นทางเลือกสำหรับเทิร์น flush เช่น ollama/qwen3:8b)
  • softThresholdTokens (ค่าเริ่มต้น: 4000)
  • prompt (ข้อความผู้ใช้สำหรับเทิร์น flush)
  • systemPrompt (พรอมป์ระบบเพิ่มเติมที่ผนวกสำหรับเทิร์น flush)

หมายเหตุ:

  • พรอมป์/พรอมป์ระบบเริ่มต้นมีคำใบ้ NO_REPLY เพื่อระงับ การส่งมอบ
  • เมื่อมีการตั้งค่า model เทิร์น flush จะใช้โมเดลนั้นโดยไม่สืบทอด เชน fallback ของเซสชันที่ใช้งานอยู่ เพื่อให้งานดูแลระบบเฉพาะเครื่องไม่ fallback อย่างเงียบ ๆ ไปยังโมเดลสนทนาแบบชำระเงิน
  • flush จะรันหนึ่งครั้งต่อรอบ Compaction (ติดตามใน sessions.json)
  • flush จะรันเฉพาะสำหรับเซสชัน Pi แบบฝังตัว (แบ็กเอนด์ CLI จะข้าม)
  • flush จะถูกข้ามเมื่อพื้นที่ทำงานของเซสชันเป็นแบบอ่านอย่างเดียว (workspaceAccess: "ro" หรือ "none")
  • ดู หน่วยความจำ สำหรับเลย์เอาต์ไฟล์พื้นที่ทำงานและรูปแบบการเขียน

Pi ยังเปิดเผย hook session_before_compact ใน API ของส่วนขยายด้วย แต่ตรรกะ flush ของ OpenClaw อยู่ฝั่ง Gateway ในปัจจุบัน


เช็กลิสต์การแก้ปัญหา

  • คีย์เซสชันผิดหรือไม่ เริ่มที่ /concepts/session และยืนยัน sessionKey ใน /status
  • store กับทรานสคริปต์ไม่ตรงกันหรือไม่ ยืนยันโฮสต์ Gateway และพาธ store จาก openclaw status
  • Compaction ถี่เกินไปหรือไม่ ตรวจสอบ:
    • หน้าต่างบริบทของโมเดล (เล็กเกินไป)
    • การตั้งค่า Compaction (reserveTokens สูงเกินไปสำหรับหน้าต่างโมเดลอาจทำให้ Compaction เกิดเร็วขึ้น)
    • ผลลัพธ์เครื่องมือบวม: เปิดใช้/ปรับแต่งการตัดแต่งเซสชัน
  • เทิร์นเงียบรั่วหรือไม่ ยืนยันว่าคำตอบเริ่มต้นด้วย NO_REPLY (โทเค็นตรงตัวแบบไม่คำนึงถึงตัวพิมพ์เล็กใหญ่) และคุณอยู่บนบิลด์ที่มีการแก้ไขการระงับการสตรีมแล้ว

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