Technical reference
เจาะลึกการจัดการเซสชัน
OpenClaw จัดการเซสชันแบบครบวงจรในพื้นที่เหล่านี้:
- การกำหนดเส้นทางเซสชัน (วิธีที่ข้อความขาเข้าแมปกับ
sessionKey) - ที่เก็บเซสชัน (
sessions.json) และสิ่งที่ติดตาม - การคงอยู่ของทรานสคริปต์ (
*.jsonl) และโครงสร้างของมัน - สุขอนามัยของทรานสคริปต์ (การแก้ไขเฉพาะผู้ให้บริการก่อนรัน)
- ขีดจำกัดบริบท (หน้าต่างบริบทเทียบกับโทเค็นที่ติดตาม)
- Compaction (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 จะถูกข้ามเมื่อทรานสคริปต์ที่ใช้งานอยู่
เกินเพดานขนาดจุดตรวจ เพื่อหลีกเลี่ยงการคัดลอก
.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:
mode:warn(ค่าเริ่มต้น) หรือenforcepruneAfter: เกณฑ์อายุของรายการที่เก่าเกิน (ค่าเริ่มต้น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"):
- ลบอาร์ติแฟกต์ที่เก็บถาวร ทรานสคริปต์กำพร้า หรือ trajectory กำพร้าที่เก่าที่สุดก่อน
- หากยังเกินเป้าหมาย ให้ขับรายการเซสชันที่เก่าที่สุดและไฟล์ทรานสคริปต์/trajectory ของรายการนั้นออก
- ทำต่อจนกว่าการใช้งานจะอยู่ที่หรือต่ำกว่า
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ปัจจุบัน; ความสดของการรีเซ็ตรายวัน ใช้ค่านี้ แถวเดิมอาจได้ค่านี้จากส่วนหัวเซสชัน JSONLlastInteractionAt: ประทับเวลาของการโต้ตอบผู้ใช้/ช่องจริงครั้งล่าสุด; ความสดของการรีเซ็ต เมื่อไม่มีการใช้งานใช้ค่านี้ เพื่อให้ Heartbeat, Cron และเหตุการณ์ exec ไม่คงเซสชัน ให้มีชีวิตอยู่ แถวเดิมที่ไม่มีฟิลด์นี้จะ fallback ไปยังเวลาเริ่มต้นเซสชันที่กู้คืน สำหรับความสดเมื่อไม่มีการใช้งานupdatedAt: ประทับเวลาการเปลี่ยนแปลงแถวที่เก็บล่าสุด ใช้สำหรับการแสดงรายการ การตัดแต่ง และ bookkeeping ค่านี้ไม่ใช่แหล่งอำนาจสำหรับความสดของการรีเซ็ตรายวัน/ไม่มีการใช้งานsessionFile: การแทนที่พาธทรานสคริปต์ที่ชัดเจนแบบไม่บังคับchatType:direct | group | room(ช่วย UI และนโยบายส่ง)provider,subject,room,space,displayName: เมตาดาต้าสำหรับการติดป้ายกลุ่ม/ช่อง- สวิตช์:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(การแทนที่ต่อเซสชัน)
- การเลือกโมเดล:
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/toolResultcustom_message: ข้อความที่ส่วนขยายแทรกเข้ามาซึ่ง เข้า บริบทโมเดล (ซ่อนได้จาก UI)custom: สถานะส่วนขยายที่ ไม่ เข้าในบริบทโมเดลcompaction: สรุป Compaction ที่คงอยู่พร้อมfirstKeptEntryIdและtokensBeforebranch_summary: สรุปที่คงอยู่เมื่อนำทางกิ่งของต้นไม้
OpenClaw ตั้งใจ ไม่ "แก้ไข" ทรานสคริปต์; Gateway ใช้ SessionManager เพื่ออ่าน/เขียนทรานสคริปต์
หน้าต่างบริบทเทียบกับโทเค็นที่ติดตาม
แนวคิดสองอย่างที่สำคัญ:
- หน้าต่างบริบทของโมเดล: เพดานแข็งต่อโมเดล (โทเค็นที่โมเดลมองเห็น)
- ตัวนับในที่เก็บเซสชัน: สถิติแบบ 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 จะถูกทริกเกอร์ในสองกรณี:
- การกู้คืนจากการล้น: โมเดลคืนข้อผิดพลาดบริบทล้น
(
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 → ลองใหม่ - การบำรุงรักษาตามเกณฑ์: หลังจากเทิร์นสำเร็จ เมื่อ:
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 < reserveTokensFloorOpenClaw จะปรับเพิ่มให้ - ค่าพื้นเริ่มต้นคือ
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.truncateAfterCompactionOpenClaw จะหมุนเวียนทรานสคริปต์ที่ใช้งานอยู่ไปเป็น 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:
- ตรวจสอบการใช้บริบทของเซสชัน
- เมื่อข้าม “soft threshold” (ต่ำกว่าเกณฑ์ Compaction ของ Pi) ให้รันคำสั่ง “write memory now” แบบเงียบไปยังเอเจนต์
- ใช้โทเค็นเงียบที่ตรงตัว
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(โทเค็นตรงตัวแบบไม่คำนึงถึงตัวพิมพ์เล็กใหญ่) และคุณอยู่บนบิลด์ที่มีการแก้ไขการระงับการสตรีมแล้ว