Technical reference
เจาะลึกการจัดการเซสชัน
OpenClaw จัดการเซสชันแบบครบวงจรในส่วนต่างๆ เหล่านี้:
- การกำหนดเส้นทางเซสชัน (วิธีที่ข้อความขาเข้าจับคู่กับ
sessionKey) - ที่จัดเก็บเซสชัน (
sessions.json) และสิ่งที่ติดตาม - การคงอยู่ของทรานสคริปต์ (
*.jsonl) และโครงสร้างของมัน - สุขอนามัยของทรานสคริปต์ (การปรับแก้เฉพาะผู้ให้บริการก่อนรัน)
- ขีดจำกัดบริบท (หน้าต่างบริบทเทียบกับโทเค็นที่ติดตาม)
- Compaction (แบบกำหนดเองและ auto-compaction) และตำแหน่งสำหรับเชื่อมงานก่อน Compaction
- งานดูแลเบื้องหลังแบบเงียบ (การเขียนหน่วยความจำที่ไม่ควรสร้างเอาต์พุตที่ผู้ใช้มองเห็น)
หากต้องการภาพรวมระดับสูงก่อน ให้เริ่มที่:
- การจัดการเซสชัน
- Compaction
- ภาพรวมหน่วยความจำ
- การค้นหาหน่วยความจำ
- การตัดเซสชัน
- สุขอนามัยของทรานสคริปต์
แหล่งข้อมูลจริง: Gateway
OpenClaw ออกแบบโดยมี กระบวนการ Gateway เดียวที่เป็นเจ้าของสถานะเซสชัน
- UI (แอป macOS, Control UI บนเว็บ, TUI) ควรสอบถาม Gateway เพื่อดูรายการเซสชันและจำนวนโทเค็น
- ในโหมดระยะไกล ไฟล์เซสชันอยู่บนโฮสต์ระยะไกล; "การตรวจไฟล์ Mac ในเครื่องของคุณ" จะไม่สะท้อนสิ่งที่ Gateway ใช้อยู่
เลเยอร์การคงอยู่สองชั้น
OpenClaw คงอยู่เซสชันในสองเลเยอร์:
-
ที่จัดเก็บเซสชัน (
sessions.json)- แผนที่คีย์/ค่า:
sessionKey -> SessionEntry - ขนาดเล็ก เปลี่ยนแปลงได้ แก้ไขได้อย่างปลอดภัย (หรือลบรายการได้)
- ติดตามเมทาดาทาของเซสชัน (รหัสเซสชันปัจจุบัน กิจกรรมล่าสุด ตัวสลับ ตัวนับโทเค็น ฯลฯ)
- แผนที่คีย์/ค่า:
-
ทรานสคริปต์ (
<sessionId>.jsonl)- ทรานสคริปต์แบบผนวกอย่างเดียวที่มีโครงสร้างต้นไม้ (รายการมี
id+parentId) - เก็บบทสนทนาจริง + การเรียกเครื่องมือ + สรุป Compaction
- ใช้สร้างบริบทของโมเดลใหม่สำหรับรอบถัดไป
- จุดตรวจ 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
- เซสชันหัวข้อ Telegram:
OpenClaw แก้ตำแหน่งเหล่านี้ผ่าน src/config/sessions.ts
การบำรุงรักษาที่จัดเก็บและการควบคุมดิสก์
การคงอยู่ของเซสชันมีการควบคุมการบำรุงรักษาอัตโนมัติ (session.maintenance) สำหรับ sessions.json, อาร์ติแฟกต์ทรานสคริปต์ และ trajectory sidecar:
mode:enforce(ค่าเริ่มต้น) หรือwarnpruneAfter: จุดตัดอายุรายการที่เก่า (ค่าเริ่มต้น30d)maxEntries: จำกัดจำนวนรายการในsessions.json(ค่าเริ่มต้น500)- การเก็บรักษา probe การรันโมเดลของ Gateway ที่มีอายุสั้นถูกกำหนดไว้ที่
24hแต่ถูกควบคุมด้วยแรงกดดัน: จะลบแถว strict probe ที่เก่าเฉพาะเมื่อถึงแรงกดดันจากการบำรุงรักษา/ขีดจำกัดของรายการเซสชันเท่านั้น ใช้เฉพาะกับคีย์ strict explicit probe ที่ตรงกับagent:*:explicit:model-run-<uuid>และรันก่อนการล้าง/จำกัดรายการเก่าทั่วโลกเมื่อทำงาน resetArchiveRetention: การเก็บรักษาไฟล์เก็บถาวรทรานสคริปต์*.reset.<timestamp>(ค่าเริ่มต้น: เหมือนกับpruneAfter;falseปิดการล้าง)maxDiskBytes: งบประมาณไดเรกทอรีเซสชันแบบไม่บังคับhighWaterBytes: เป้าหมายแบบไม่บังคับหลังการล้าง (ค่าเริ่มต้น80%ของmaxDiskBytes)
การเขียน Gateway ปกติไหลผ่านตัวเขียนเซสชันรายที่จัดเก็บ ซึ่งจัดลำดับการเปลี่ยนแปลงภายในกระบวนการโดยไม่ใช้ runtime file lock ตัวช่วยแพตช์ในเส้นทางร้อนยืมแคชแบบเปลี่ยนแปลงได้ที่ผ่านการตรวจสอบแล้วขณะถือช่องของตัวเขียนนั้น ดังนั้นไฟล์ 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 และเอเจนต์ย่อยยังสามารถถูกลบได้เมื่อเกินอายุ จำนวน หรืองบประมาณดิสก์ที่กำหนด เซสชัน probe การรันโมเดลของ Gateway ใช้การเก็บรักษาการรันโมเดล 24h แยกต่างหากเฉพาะเมื่อคีย์ตรงกับ agent:*:explicit:model-run-<uuid> แบบพอดีเท่านั้น; เซสชัน explicit อื่นไม่เป็นส่วนหนึ่งของการเก็บรักษานั้น การล้างการรันโมเดลจะถูกใช้เฉพาะเมื่อมีแรงกดดันจากขีดจำกัดรายการเซสชัน รัน cron แบบแยกโดดเดี่ยวจะเก็บการควบคุม cron.sessionRetention ของตัวเอง แยกจากการเก็บรักษา probe การรันโมเดล
OpenClaw ไม่สร้างการสำรองแบบหมุนเวียน sessions.json.bak.* อัตโนมัติระหว่างการเขียน Gateway อีกต่อไป คีย์เดิม session.maintenance.rotateBytes จะถูกละเว้น และ openclaw doctor --fix จะลบออกจากคอนฟิกเก่า
การเปลี่ยนแปลงทรานสคริปต์ใช้ session write lock บนไฟล์ทรานสคริปต์ การได้ lock จะรอสูงสุด session.writeLock.acquireTimeoutMs ก่อนแสดงข้อผิดพลาดเซสชันไม่ว่าง; ค่าเริ่มต้นคือ 60000 ms เพิ่มค่านี้เฉพาะเมื่องานเตรียม ล้าง Compaction หรือมิเรอร์ทรานสคริปต์ที่ถูกต้องตามปกติแย่งกันนานกว่าบนเครื่องที่ช้า session.writeLock.staleMs ควบคุมว่าเมื่อใด lock ที่มีอยู่จะถูกเรียกคืนเป็น stale ได้; ค่าเริ่มต้นคือ 1800000 ms session.writeLock.maxHoldMs ควบคุมเกณฑ์การปล่อยของ watchdog ภายในกระบวนการ; ค่าเริ่มต้นคือ 300000 ms การ override ด้วย env ในกรณีฉุกเฉินคือ OPENCLAW_SESSION_WRITE_LOCK_ACQUIRE_TIMEOUT_MS, OPENCLAW_SESSION_WRITE_LOCK_STALE_MS และ OPENCLAW_SESSION_WRITE_LOCK_MAX_HOLD_MS
ลำดับการบังคับใช้สำหรับการล้างงบประมาณดิสก์ (mode: "enforce"):
- ลบอาร์ติแฟกต์ที่เก็บถาวร ทรานสคริปต์กำพร้า หรือ trajectory กำพร้าที่เก่าที่สุดก่อน
- หากยังสูงกว่าเป้าหมาย ให้ขับรายการเซสชันที่เก่าที่สุดและไฟล์ทรานสคริปต์/trajectory ของรายการเหล่านั้นออก
- ทำต่อจนกว่าการใช้งานจะอยู่ที่หรือต่ำกว่า
highWaterBytes
ใน mode: "warn" OpenClaw จะรายงานการขับออกที่อาจเกิดขึ้น แต่จะไม่เปลี่ยนแปลงที่จัดเก็บ/ไฟล์
รันการบำรุงรักษาตามต้องการ:
openclaw sessions cleanup --dry-runopenclaw sessions cleanup --enforceเซสชัน Cron และบันทึกการรัน
รัน cron แบบแยกโดดเดี่ยวจะสร้างรายการเซสชัน/ทรานสคริปต์ด้วย และมีการควบคุมการเก็บรักษาเฉพาะ:
cron.sessionRetention(ค่าเริ่มต้น24h) ตัดเซสชันการรัน cron แบบแยกโดดเดี่ยวเก่าออกจากที่จัดเก็บเซสชัน (falseปิดใช้งาน)cron.runLog.keepLinesตัดแถวประวัติการรัน SQLite ที่เก็บไว้ต่อ cron job (ค่าเริ่มต้น:2000)cron.runLog.maxBytesยังคงยอมรับสำหรับบันทึกการรันแบบไฟล์เดิม
เมื่อ cron บังคับสร้างเซสชันรันแบบแยกโดดเดี่ยวใหม่ มันจะทำให้รายการเซสชัน cron:<jobId> ก่อนหน้าปลอดภัยก่อนเขียนแถวใหม่ โดยนำค่ากำหนดที่ปลอดภัยติดไปด้วย เช่น การตั้งค่า thinking/fast/verbose ป้ายกำกับ และการ override โมเดล/auth ที่ผู้ใช้เลือกอย่างชัดเจน มันจะทิ้งบริบทบทสนทนาแวดล้อม เช่น การกำหนดเส้นทางช่องทาง/กลุ่ม นโยบายส่งหรือคิว การยกระดับ ต้นทาง และการผูก ACP runtime เพื่อให้รันแบบแยกโดดเดี่ยวใหม่ไม่สามารถสืบทอดการส่งที่เก่าค้างหรืออำนาจรันไทม์จากรันเก่าได้
คีย์เซสชัน (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>(เว้นแต่ถูก override)
กฎมาตรฐานมีเอกสารที่ /concepts/session
รหัสเซสชัน (sessionId)
แต่ละ sessionKey ชี้ไปยัง sessionId ปัจจุบัน (ไฟล์ทรานสคริปต์ที่ดำเนินบทสนทนาต่อ)
หลักทั่วไป:
- รีเซ็ต (
/new,/reset) สร้างsessionIdใหม่สำหรับsessionKeyนั้น - รีเซ็ตรายวัน (ค่าเริ่มต้น 4:00 AM ตามเวลาท้องถิ่นบนโฮสต์ Gateway) สร้าง
sessionIdใหม่ในข้อความถัดไปหลังผ่านขอบเขตการรีเซ็ต - หมดอายุเมื่อไม่ได้ใช้งาน (
session.reset.idleMinutesหรือเดิมsession.idleMinutes) สร้างsessionIdใหม่เมื่อมีข้อความมาถึงหลังพ้นหน้าต่างเวลาที่ไม่ได้ใช้งาน เมื่อกำหนดทั้งรายวัน + ไม่ได้ใช้งาน ตัวใดหมดอายุก่อนจะมีผล - การเชื่อมต่อ Control UI ใหม่เพื่อดำเนินต่อ สามารถรักษาเซสชันที่กำลังมองเห็นอยู่ในปัจจุบันไว้สำหรับการส่งหนึ่งครั้งหลังเชื่อมต่อใหม่ เมื่อ Gateway ได้รับ
sessionIdที่ตรงกันจากไคลเอนต์ UI ของผู้ปฏิบัติการ การส่งแบบ stale ตามปกติยังคงสร้างsessionIdใหม่ - เหตุการณ์ระบบ (Heartbeat, การปลุกของ cron, การแจ้งเตือน exec, งานบันทึกของ Gateway) อาจเปลี่ยนแปลงแถวเซสชัน แต่ไม่ขยายความสดใหม่ของการรีเซ็ตรายวัน/เมื่อไม่ได้ใช้งาน การเปลี่ยนรอบรีเซ็ตจะทิ้งการแจ้งเหตุการณ์ระบบที่เข้าคิวไว้สำหรับเซสชันก่อนหน้า ก่อนสร้างพรอมต์ใหม่
- นโยบาย fork จากพาเรนต์ ใช้กิ่ง active ของ OpenClaw เมื่อสร้างเธรดหรือ fork เอเจนต์ย่อย หากกิ่งนั้นใหญ่เกินไป OpenClaw จะเริ่ม child ด้วยบริบทแบบแยกโดดเดี่ยวแทนการล้มเหลวหรือสืบทอดประวัติที่ใช้ไม่ได้ นโยบายการกำหนดขนาดเป็นอัตโนมัติ; คอนฟิกเดิม
session.parentForkMaxTokensจะถูกลบโดยopenclaw doctor --fix
รายละเอียดการใช้งาน: การตัดสินใจเกิดขึ้นใน initSessionState() ใน src/auto-reply/reply/session.ts
สคีมาที่จัดเก็บเซสชัน (sessions.json)
ชนิดค่าของที่จัดเก็บคือ SessionEntry ใน src/config/sessions.ts
ฟิลด์สำคัญ (ไม่ครบทั้งหมด):
sessionId: id ของทรานสคริปต์ปัจจุบัน (ชื่อไฟล์จะได้มาจากค่านี้ เว้นแต่จะตั้งค่าsessionFile)sessionStartedAt: ประทับเวลาเริ่มต้นสำหรับsessionIdปัจจุบัน; การรีเซ็ตรายวัน ใช้ค่านี้เพื่อพิจารณาความสดใหม่ แถว legacy อาจได้ค่านี้มาจากส่วนหัวเซสชัน JSONLlastInteractionAt: ประทับเวลาการโต้ตอบจริงล่าสุดของผู้ใช้/ช่องทาง; การรีเซ็ตเมื่อไม่ได้ใช้งาน ใช้ค่านี้เพื่อพิจารณาความสดใหม่ เพื่อให้เหตุการณ์ Heartbeat, Cron และ exec ไม่ทำให้เซสชัน ยังมีชีวิตอยู่ แถว legacy ที่ไม่มีฟิลด์นี้จะย้อนกลับไปใช้เวลาเริ่มต้นเซสชันที่กู้คืนได้ สำหรับความสดใหม่เมื่อไม่ได้ใช้งานupdatedAt: ประทับเวลาการเปลี่ยนแปลงแถวในที่เก็บครั้งล่าสุด ใช้สำหรับการแสดงรายการ การตัดทิ้ง และ งานบันทึกบัญชี ค่านี้ไม่ใช่แหล่งอ้างอิงสำหรับความสดใหม่ของการรีเซ็ตรายวัน/เมื่อไม่ได้ใช้งานarchivedAt: ประทับเวลาการเก็บถาวรแบบไม่บังคับ เซสชันที่เก็บถาวรจะยังอยู่ในที่เก็บ โดยทรานสคริปต์ยังคงครบถ้วน และจะถูกยกเว้นจากรายการที่ใช้งานปกติpinnedAt: ประทับเวลาการปักหมุดแบบไม่บังคับ เซสชันที่ใช้งานและถูกปักหมุดจะเรียงอยู่ก่อน เซสชันที่ไม่ถูกปักหมุด; การเก็บถาวรเซสชันจะล้างการปักหมุดของเซสชันนั้น- การทำงานร่วมกันกับเธรด Codex: ทั้งสองฟิลด์ทำตามรูปแบบการจัดการเธรดของ Codex —
บูลีน
archived/pinnedบน wire จะถูกคำนวณจากประทับเวลาเสมอ และประทับฝั่งเซิร์ฟเวอร์ โดยสอดคล้องกับ semantics ของ Codexthreads.archived_atและการ serialize แบบ camelCase ประทับเวลาของ OpenClaw เป็นมิลลิวินาทีนับจาก epoch ขณะที่ Codex ใช้วินาทีนับจาก epoch ดังนั้นบริดจ์จะแปลงที่ seam ของ codex plugin Codex ยังไม่มี API สำหรับการปักหมุด (thread/archive/thread/unarchiveเท่านั้น); สถานะปักหมุดจะยังอยู่ฝั่ง OpenClaw จนกว่าจะมี API ดังกล่าว เมื่อถึงเวลานั้น รูปแบบที่ตรงกันจะทำให้เซสชันที่ผูกไว้ round-trip สถานะปักหมุดได้แบบกลไก sessionFile: การ override เส้นทางทรานสคริปต์อย่างชัดเจนแบบไม่บังคับchatType:direct | group | room(ช่วย UI และนโยบายการส่ง)provider,subject,room,space,displayName: เมตาดาทาสำหรับการติดป้ายกำกับกลุ่ม/ช่องทาง- ตัวสลับ:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(override รายเซสชัน)
- การเลือกโมเดล:
providerOverride,modelOverride,authProfileOverride
- ตัวนับโทเค็น (ตามความพยายามที่ดีที่สุด / ขึ้นอยู่กับผู้ให้บริการ):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: จำนวนครั้งที่ auto-Compaction เสร็จสมบูรณ์สำหรับคีย์เซสชันนี้memoryFlushAt: ประทับเวลาของการ flush หน่วยความจำก่อน Compaction ครั้งล่าสุดmemoryFlushCompactionCount: จำนวน Compaction ตอนที่ flush ครั้งล่าสุดทำงาน
ที่เก็บนี้แก้ไขได้อย่างปลอดภัย แต่ Gateway เป็นแหล่งอ้างอิง: มันอาจเขียนใหม่หรือ rehydrate รายการเมื่อเซสชันทำงาน
โครงสร้างทรานสคริปต์ (*.jsonl)
ทรานสคริปต์ถูกจัดการโดย SessionManager ของ openclaw/plugin-sdk/agent-sessions
ไฟล์เป็น JSONL:
- บรรทัดแรก: ส่วนหัวเซสชัน (
type: "session"มีid,cwd,timestamp,parentSessionแบบไม่บังคับ) - จากนั้น: รายการเซสชันที่มี
id+parentId(tree)
ประเภทรายการที่น่าสังเกต:
message: ข้อความ user/assistant/toolResultcustom_message: ข้อความที่ extension แทรกเข้ามาและ เข้าสู่ บริบทโมเดล (สามารถซ่อนจาก UI ได้)custom: สถานะ extension ที่ ไม่ เข้าสู่บริบทโมเดลcompaction: สรุป Compaction ที่ persist ไว้พร้อมfirstKeptEntryIdและtokensBeforebranch_summary: สรุปที่ persist ไว้เมื่อนำทางในกิ่งของ tree
OpenClaw ตั้งใจ ไม่ "แก้แต่ง" ทรานสคริปต์; Gateway ใช้ SessionManager เพื่ออ่าน/เขียนทรานสคริปต์เหล่านั้น
หน้าต่างบริบทเทียบกับโทเค็นที่ติดตาม
มีแนวคิดต่างกันสองอย่างที่สำคัญ:
- หน้าต่างบริบทของโมเดล: เพดานแข็งต่อโมเดล (โทเค็นที่โมเดลมองเห็น)
- ตัวนับในที่เก็บเซสชัน: สถิติแบบ rolling ที่เขียนลงใน
sessions.json(ใช้สำหรับ /status และแดชบอร์ด)
หากคุณกำลังปรับแต่งขีดจำกัด:
- หน้าต่างบริบทมาจากแคตตาล็อกโมเดล (และสามารถ override ผ่าน config ได้)
contextTokensในที่เก็บเป็นค่าประมาณ/ค่ารายงานระหว่างรันไทม์; อย่าถือว่าเป็นการรับประกันที่เข้มงวด
ดูเพิ่มเติมที่ /token-use
Compaction: คืออะไร
Compaction จะสรุปบทสนทนาเก่าเป็นรายการ compaction ที่ persist ไว้ในทรานสคริปต์ และเก็บข้อความล่าสุดไว้ครบถ้วน
หลังจาก Compaction เทิร์นในอนาคตจะเห็น:
- สรุป Compaction
- ข้อความหลัง
firstKeptEntryId
การแทรกส่วน AGENTS.md ซ้ำหลัง Compaction เป็นแบบ opt-in ผ่าน
agents.defaults.compaction.postCompactionSections; เมื่อไม่ได้ตั้งค่าหรือเป็น []
OpenClaw จะไม่ผนวกข้อความตัดตอนจาก AGENTS.md เพิ่มบนสรุป Compaction
Compaction เป็นแบบ persistent (ต่างจากการตัดทิ้งเซสชัน) ดู /concepts/session-pruning
ขอบเขต chunk ของ Compaction และการจับคู่เครื่องมือ
เมื่อ OpenClaw แบ่งทรานสคริปต์ยาวเป็น chunk สำหรับ Compaction มันจะเก็บ
การเรียกเครื่องมือของ assistant ให้จับคู่กับรายการ toolResult ที่ตรงกัน
- หากการแบ่งตามสัดส่วนโทเค็นตกอยู่ระหว่างการเรียกเครื่องมือกับผลลัพธ์ OpenClaw จะเลื่อนขอบเขตไปที่ข้อความเรียกเครื่องมือของ assistant แทนการแยก คู่ออกจากกัน
- หากบล็อก tool-result ท้ายสุดจะทำให้ chunk เกินเป้าหมาย OpenClaw จะรักษาบล็อกเครื่องมือที่รออยู่นั้นไว้ และคงส่วนท้ายที่ยังไม่ถูกสรุป ไว้ครบถ้วน
- บล็อก tool-call ที่ถูกยกเลิก/เกิดข้อผิดพลาดจะไม่ตรึงการแบ่งที่รออยู่ให้เปิดต่อ
เมื่อ auto-Compaction เกิดขึ้น (รันไทม์ OpenClaw)
ในเอเจนต์ OpenClaw แบบฝัง auto-Compaction จะทริกเกอร์ในสองกรณี:
- การกู้คืนจาก overflow: โมเดลส่งคืนข้อผิดพลาด context overflow
(
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 → retry เมื่อผู้ให้บริการรายงานจำนวนโทเค็นที่พยายามใช้ OpenClaw จะส่งต่อ จำนวนที่สังเกตได้นั้นเข้าไปยัง Compaction สำหรับการกู้คืนจาก overflow หากผู้ให้บริการยืนยัน overflow แต่ไม่เปิดเผยจำนวนที่ parse ได้ OpenClaw จะส่งจำนวนสังเคราะห์ที่เกินงบประมาณ เพียงเล็กน้อยให้เครื่องยนต์ Compaction และ diagnostics หากการกู้คืนจาก overflow ยังล้มเหลว OpenClaw จะแสดงคำแนะนำที่ชัดเจนแก่ ผู้ใช้ และรักษาการแมปเซสชันปัจจุบันไว้แทนที่จะหมุนคีย์เซสชัน ไปเป็น id เซสชันใหม่อย่างเงียบ ๆ ขั้นตอนถัดไปอยู่ภายใต้การควบคุมของผู้ปฏิบัติการ: retry ข้อความ, เรียก/compactหรือเรียก/newเมื่อ ต้องการเซสชันใหม่ - การบำรุงรักษาตาม threshold: หลังจากเทิร์นสำเร็จ เมื่อ:
contextTokens > contextWindow - reserveTokens
โดยที่:
contextWindowคือหน้าต่างบริบทของโมเดลreserveTokensคือพื้นที่เผื่อที่สงวนไว้สำหรับ prompt + output โมเดลถัดไป
สิ่งเหล่านี้คือ semantics ของรันไทม์ OpenClaw
OpenClaw ยังสามารถทริกเกอร์ Compaction แบบ local preflight ก่อนเปิดการรันถัดไป
เมื่อมีการตั้งค่า agents.defaults.compaction.maxActiveTranscriptBytes และไฟล์ทรานสคริปต์
ที่ใช้งานถึงขนาดนั้น นี่เป็น guard ตามขนาดไฟล์สำหรับต้นทุนการ reopen แบบ local
ไม่ใช่การเก็บถาวรดิบ: OpenClaw ยังรัน Compaction เชิง semantic ตามปกติ
และต้องใช้ truncateAfterCompaction เพื่อให้สรุปที่ compact แล้วกลายเป็น
ทรานสคริปต์ successor ใหม่ได้
สำหรับการรัน OpenClaw แบบฝัง agents.defaults.compaction.midTurnPrecheck.enabled: true
จะเพิ่ม guard วงรอบเครื่องมือแบบ opt-in หลังจากผนวกผลลัพธ์เครื่องมือและก่อน
การเรียกโมเดลถัดไป OpenClaw จะประมาณแรงกดดันต่อ prompt โดยใช้ตรรกะงบประมาณ preflight
เดียวกับที่ใช้ตอนเริ่มเทิร์น หากบริบทไม่พออีกต่อไป guard จะ
ไม่ compact ภายใน hook transformContext ของรันไทม์ OpenClaw มันจะส่งสัญญาณ
mid-turn precheck แบบมีโครงสร้าง หยุดการส่ง prompt ปัจจุบัน และให้
ลูปการรันภายนอกใช้เส้นทางกู้คืนที่มีอยู่: truncate ผลลัพธ์เครื่องมือที่ใหญ่เกินไป
เมื่อเพียงพอ หรือทริกเกอร์โหมด Compaction ที่กำหนดค่าไว้แล้ว retry ตัวเลือกนี้
ปิดอยู่โดยค่าเริ่มต้น และทำงานได้กับทั้งโหมด Compaction default และ safeguard
รวมถึง Compaction แบบ safeguard ที่มีผู้ให้บริการหนุนหลัง
สิ่งนี้เป็นอิสระจาก maxActiveTranscriptBytes: guard ตามขนาด byte จะทำงาน
ก่อนเปิดเทิร์น ขณะที่ mid-turn precheck จะทำงานภายหลังในวงรอบเครื่องมือ OpenClaw แบบฝัง
หลังจากผนวกผลลัพธ์เครื่องมือใหม่แล้ว
การตั้งค่า Compaction (reserveTokens, keepRecentTokens)
การตั้งค่า Compaction ของรันไทม์ OpenClaw อยู่ในการตั้งค่าเอเจนต์:
{ compaction: { enabled: true, reserveTokens: 16384, keepRecentTokens: 20000, },}OpenClaw ยังบังคับใช้ safety floor สำหรับการรันแบบฝัง:
- หาก
compaction.reserveTokens < reserveTokensFloorOpenClaw จะเพิ่มค่าให้ - floor ค่าเริ่มต้นคือ
20000โทเค็น - ตั้งค่า
agents.defaults.compaction.reserveTokensFloor: 0เพื่อปิด floor - หากค่าสูงกว่าอยู่แล้ว OpenClaw จะปล่อยไว้ตามเดิม
/compactแบบแมนนวลจะเคารพagents.defaults.compaction.keepRecentTokensที่ระบุชัดเจน และเก็บจุดตัด recent-tail ของรันไทม์ OpenClaw หากไม่มีงบประมาณ keep ที่ชัดเจน Compaction แบบแมนนวลจะยังเป็น checkpoint แบบแข็ง และบริบทที่สร้างใหม่จะเริ่มจาก สรุปใหม่- ตั้งค่า
agents.defaults.compaction.midTurnPrecheck.enabled: trueเพื่อรัน precheck วงรอบเครื่องมือแบบไม่บังคับหลังผลลัพธ์เครื่องมือใหม่และก่อนการเรียกโมเดล ถัดไป นี่เป็นเพียงทริกเกอร์; การสร้างสรุปยังใช้เส้นทาง Compaction ที่กำหนดค่าไว้ สิ่งนี้เป็นอิสระจากmaxActiveTranscriptBytesซึ่งเป็น guard ตามขนาด byte ของทรานสคริปต์ที่ใช้งานตอนเริ่มเทิร์น - ตั้งค่า
agents.defaults.compaction.maxActiveTranscriptBytesเป็นค่า byte หรือ string เช่น"20mb"เพื่อรัน Compaction แบบ local ก่อนเทิร์นเมื่อทรานสคริปต์ที่ใช้งาน มีขนาดใหญ่ guard นี้ใช้งานเฉพาะเมื่อ เปิดใช้truncateAfterCompactionด้วยเท่านั้น ปล่อยว่างไว้หรือตั้ง0เพื่อ ปิดใช้งาน - เมื่อเปิดใช้
agents.defaults.compaction.truncateAfterCompactionOpenClaw จะหมุนทรานสคริปต์ที่ใช้งานไปเป็น JSONL successor ที่ compact แล้วหลัง Compaction การกระทำ checkpoint ของ branch/restore จะใช้ successor ที่ compact แล้วนั้น; ไฟล์ checkpoint legacy ก่อน Compaction จะยังอ่านได้ขณะยังถูกอ้างอิง
เหตุผล: เว้นพื้นที่เผื่อให้เพียงพอสำหรับ "housekeeping" หลายเทิร์น (เช่น การเขียนหน่วยความจำ) ก่อนที่ Compaction จะหลีกเลี่ยงไม่ได้
การใช้งาน: applyAgentCompactionSettingsFromConfig() ใน src/agents/agent-settings.ts
(ถูกเรียกจากเส้นทางตั้งค่าเทิร์นของ embedded-runner และ Compaction)
ผู้ให้บริการ Compaction แบบเสียบเปลี่ยนได้
Plugin สามารถลงทะเบียนผู้ให้บริการ Compaction ผ่าน registerCompactionProvider() บน plugin API เมื่อ agents.defaults.compaction.provider ถูกตั้งค่าเป็น id ผู้ให้บริการที่ลงทะเบียนไว้ extension safeguard จะมอบหมายการสรุปให้ผู้ให้บริการนั้นแทน pipeline summarizeInStages ในตัว
provider: id ของ Plugin ผู้ให้บริการ Compaction ที่ลงทะเบียนไว้ ปล่อยว่างเพื่อใช้การสรุป LLM ค่าเริ่มต้น- การตั้งค่า
providerจะบังคับmode: "safeguard" - ผู้ให้บริการจะได้รับคำสั่ง Compaction และนโยบายการรักษาตัวระบุเดียวกับเส้นทางในตัว
- safeguard ยังคงรักษาบริบท suffix ของ recent-turn และ split-turn หลัง output ของผู้ให้บริการ
- การสรุป safeguard ในตัวจะ re-distill สรุปก่อนหน้าร่วมกับข้อความใหม่ แทนการรักษาสรุปก่อนหน้าทั้งหมดไว้ตามตัวอักษร
- โหมด safeguard เปิดใช้งานการ audit คุณภาพสรุปโดยค่าเริ่มต้น; ตั้งค่า
qualityGuard.enabled: falseเพื่อข้ามพฤติกรรม retry-on-malformed-output - หากผู้ให้บริการล้มเหลวหรือส่งคืนผลลัพธ์ว่าง OpenClaw จะ fallback ไปใช้การสรุป LLM ในตัวโดยอัตโนมัติ
- สัญญาณ abort/timeout จะถูกโยนซ้ำ (ไม่ถูกกลืน) เพื่อเคารพการยกเลิกของผู้เรียก
แหล่งที่มา: src/plugins/compaction-provider.ts, src/agents/agent-hooks/compaction-safeguard.ts
พื้นผิวที่ผู้ใช้มองเห็น
คุณสามารถสังเกต Compaction และสถานะเซสชันได้ผ่าน:
/status(ในเซสชันแชตใดก็ได้)openclaw status(CLI)openclaw sessions/sessions --json- log ของ Gateway (
pnpm gateway:watchหรือopenclaw logs --follow):embedded run auto-compaction start+complete - โหมด verbose:
🧹 Auto-compaction complete+ จำนวน Compaction
งาน housekeeping แบบเงียบ (NO_REPLY)
OpenClaw รองรับเทิร์นแบบ "เงียบ" สำหรับงานเบื้องหลังที่ผู้ใช้ไม่ควรเห็น output ระหว่างทาง
ข้อตกลง:
- ผู้ช่วยเริ่มต้นเอาต์พุตด้วยโทเค็นเงียบแบบตรงตัว
NO_REPLY/no_replyเพื่อระบุว่า "ไม่ต้องส่งคำตอบให้ผู้ใช้" - OpenClaw จะตัด/ระงับสิ่งนี้ในเลเยอร์การส่งมอบ
- การระงับโทเค็นเงียบแบบตรงตัวไม่แยกตัวพิมพ์เล็ก-ใหญ่ ดังนั้น
NO_REPLYและno_replyจะนับทั้งคู่เมื่อเพย์โหลดทั้งหมดเป็นเพียงโทเค็นเงียบ - สิ่งนี้ใช้สำหรับรอบการทำงานเบื้องหลัง/ไม่ส่งมอบจริงเท่านั้น ไม่ใช่ทางลัดสำหรับ คำขอผู้ใช้ทั่วไปที่ต้องดำเนินการ
ตั้งแต่ 2026.1.10 เป็นต้นไป OpenClaw ยังระงับ การสตรีมแบบร่าง/กำลังพิมพ์ เมื่อ
chunk บางส่วนขึ้นต้นด้วย NO_REPLY ดังนั้นการทำงานแบบเงียบจะไม่รั่วไหลเอาต์พุตบางส่วน
กลางรอบการทำงาน
"การล้างหน่วยความจำ" ก่อน Compaction (นำไปใช้แล้ว)
เป้าหมาย: ก่อนเกิด Compaction อัตโนมัติ ให้รันรอบการทำงานเชิงเอเจนต์แบบเงียบที่เขียนสถานะ
ถาวรลงดิสก์ (เช่น memory/YYYY-MM-DD.md ในพื้นที่ทำงานของเอเจนต์) เพื่อให้ Compaction ไม่สามารถ
ลบบริบทสำคัญได้
OpenClaw ใช้วิธี ล้างก่อนถึงเกณฑ์:
- ตรวจสอบการใช้บริบทของเซสชัน
- เมื่อข้าม "เกณฑ์อ่อน" (ต่ำกว่าเกณฑ์ Compaction ของรันไทม์ OpenClaw) ให้รันคำสั่งแบบเงียบ "เขียนหน่วยความจำตอนนี้" ไปยังเอเจนต์
- ใช้โทเค็นเงียบแบบตรงตัว
NO_REPLY/no_replyเพื่อให้ผู้ใช้ไม่เห็น อะไรเลย
การกำหนดค่า (agents.defaults.compaction.memoryFlush):
enabled(ค่าเริ่มต้น:true)model(การแทนที่ provider/model แบบตรงตัวที่ไม่บังคับสำหรับรอบการล้าง เช่นollama/qwen3:8b)softThresholdTokens(ค่าเริ่มต้น:4000)prompt(ข้อความผู้ใช้สำหรับรอบการล้าง)systemPrompt(พรอมป์ระบบเพิ่มเติมที่ต่อท้ายสำหรับรอบการล้าง)
หมายเหตุ:
- พรอมป์/พรอมป์ระบบค่าเริ่มต้นมีคำใบ้
NO_REPLYเพื่อระงับ การส่งมอบ - เมื่อตั้งค่า
modelรอบการล้างจะใช้โมเดลนั้นโดยไม่สืบทอด fallback chain ของเซสชันที่ใช้งานอยู่ ดังนั้นงานดูแลระบบที่ใช้เฉพาะเครื่องจะไม่แอบ fallback ไปยังโมเดลสนทนาแบบเสียเงิน - การล้างจะรันหนึ่งครั้งต่อรอบ Compaction (ติดตามใน
sessions.json) - การล้างจะรันเฉพาะเซสชัน OpenClaw แบบฝังตัวเท่านั้น (แบ็กเอนด์ CLI จะข้าม)
- การล้างจะถูกข้ามเมื่อพื้นที่ทำงานของเซสชันเป็นแบบอ่านอย่างเดียว (
workspaceAccess: "ro"หรือ"none") - ดู หน่วยความจำ สำหรับเลย์เอาต์ไฟล์พื้นที่ทำงานและรูปแบบการเขียน
OpenClaw ยังเปิดเผย hook session_before_compact ใน API ส่วนขยายด้วย แต่ตรรกะการล้างของ OpenClaw
อยู่ฝั่ง Gateway ในปัจจุบัน
เช็กลิสต์การแก้ปัญหา
- คีย์เซสชันผิดหรือไม่ เริ่มจาก /concepts/session และยืนยัน
sessionKeyใน/status - ที่จัดเก็บกับทรานสคริปต์ไม่ตรงกันหรือไม่ ยืนยันโฮสต์ Gateway และพาธที่จัดเก็บจาก
openclaw status - Compaction ถี่เกินไปหรือไม่ ตรวจสอบ:
- หน้าต่างบริบทของโมเดล (เล็กเกินไป)
- การตั้งค่า Compaction (
reserveTokensสูงเกินไปสำหรับหน้าต่างของโมเดลอาจทำให้เกิด Compaction เร็วขึ้น) - ผลลัพธ์จากเครื่องมือบวมเกินไป: เปิดใช้/ปรับแต่งการตัดแต่งเซสชัน
- รอบการทำงานแบบเงียบรั่วไหลหรือไม่ ยืนยันว่าคำตอบเริ่มต้นด้วย
NO_REPLY(โทเค็นตรงตัวแบบไม่แยกตัวพิมพ์เล็ก-ใหญ่) และคุณอยู่บนบิลด์ที่รวมการแก้ไขการระงับการสตรีมแล้ว