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 - เล็ก เปลี่ยนแปลงได้ แก้ไขได้อย่างปลอดภัย (หรือลบรายการได้)
- ติดตามเมทาดาทาเซสชัน (id เซสชันปัจจุบัน, กิจกรรมล่าสุด, ตัวสลับ, ตัวนับโทเค็น ฯลฯ)
- แมปคีย์/ค่า:
-
บันทึกบทสนทนา (
<sessionId>.jsonl)- บันทึกบทสนทนาแบบ append-only พร้อมโครงสร้างต้นไม้ (รายการมี
id+parentId) - เก็บบทสนทนาจริง + การเรียกเครื่องมือ + สรุปการ Compaction
- ใช้สร้างบริบทโมเดลขึ้นใหม่สำหรับเทิร์นในอนาคต
- เช็กพอยต์ Compaction เป็นเมทาดาทาบนบันทึกบทสนทนาตัวสืบทอดที่ถูกบีบอัดแล้ว
การ Compaction ใหม่จะไม่เขียนสำเนา
.checkpoint.*.jsonlชุดที่สอง
- บันทึกบทสนทนาแบบ append-only พร้อมโครงสร้างต้นไม้ (รายการมี
ตัวอ่านประวัติ Gateway ควรหลีกเลี่ยงการ materialize บันทึกบทสนทนาทั้งหมด เว้นแต่
พื้นผิวนั้นต้องการการเข้าถึงประวัติแบบกำหนดเองได้จริง ๆ ประวัติหน้าแรก,
ประวัติแชตแบบฝัง, การกู้คืนหลังรีสตาร์ต, และการตรวจสอบโทเค็น/การใช้งาน ใช้การอ่านท้ายไฟล์แบบมีขอบเขต
การสแกนบันทึกบทสนทนาแบบเต็มจะผ่านดัชนีบันทึกบทสนทนาแบบ 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, artifact ของบันทึกบทสนทนา, และ sidecar ของ trajectory:
mode:enforce(ค่าเริ่มต้น) หรือwarnpruneAfter: เกณฑ์อายุรายการเก่า (ค่าเริ่มต้น30d)maxEntries: จำกัดจำนวนรายการในsessions.json(ค่าเริ่มต้น500)- การเก็บรักษา probe การรันโมเดลของ Gateway อายุสั้นถูกกำหนดไว้ที่
24hแต่มีการควบคุมตามแรงกดดัน: จะลบแถว strict probe ที่เก่าแล้วเฉพาะเมื่อถึงแรงกดดันด้านการบำรุงรักษา/เพดานของรายการเซสชันเท่านั้น สิ่งนี้ใช้เฉพาะกับคีย์ explicit probe แบบ strict ที่ตรงกับagent:*:explicit:model-run-<uuid>และจะรันก่อนการล้าง/จำกัดเพดานรายการเก่าทั่วโลกเมื่อมันรัน resetArchiveRetention: การเก็บรักษาไฟล์เก็บถาวรบันทึกบทสนทนา*.reset.<timestamp>(ค่าเริ่มต้น: เหมือนpruneAfter;falseปิดการล้าง)maxDiskBytes: งบประมาณไดเรกทอรีเซสชันแบบไม่บังคับhighWaterBytes: เป้าหมายแบบไม่บังคับหลังล้าง (ค่าเริ่มต้น80%ของmaxDiskBytes)
การเขียน Gateway ปกติไหลผ่านตัวเขียนเซสชันต่อที่เก็บ ซึ่งทำให้การเปลี่ยนแปลงในกระบวนการเป็นลำดับโดยไม่ต้องใช้ runtime file lock ตัวช่วยแพตช์ hot-path ยืมแคช mutable ที่ผ่านการตรวจสอบแล้วในขณะที่ถือช่องตัวเขียนนั้นอยู่ ดังนั้นไฟล์ sessions.json ขนาดใหญ่จะไม่ถูกโคลนหรืออ่านซ้ำสำหรับทุกการอัปเดตเมทาดาทา โค้ดรันไทม์ควรใช้ updateSessionStore(...) หรือ updateSessionStoreEntry(...); การบันทึกทั้งที่เก็บโดยตรงเป็นเครื่องมือสำหรับความเข้ากันได้และการบำรุงรักษาออฟไลน์ เมื่อเข้าถึง Gateway ได้ openclaw sessions cleanup และ openclaw agents delete ที่ไม่ใช่ dry run จะมอบหมายการเปลี่ยนแปลงที่เก็บให้ Gateway เพื่อให้การล้างเข้าคิวตัวเขียนเดียวกัน; --store <path> คือพาธซ่อมแซมออฟไลน์ที่ชัดเจนสำหรับการบำรุงรักษาไฟล์โดยตรง การล้าง maxEntries ยังคงถูก batch สำหรับเพดานขนาดโปรดักชัน ดังนั้นที่เก็บอาจเกินเพดานที่กำหนดชั่วครู่ก่อนที่การล้าง high-water ครั้งถัดไปจะเขียนกลับลงมา การอ่านที่เก็บเซสชันจะไม่ prune หรือจำกัดเพดานรายการระหว่างการเริ่มต้น Gateway; ใช้การเขียนหรือ openclaw sessions cleanup --enforce สำหรับการล้าง openclaw sessions cleanup --enforce ยังคงใช้เพดานที่กำหนดทันทีและ prune artifact ของบันทึกบทสนทนา เช็กพอยต์ และ trajectory เก่าที่ไม่มีการอ้างอิง แม้ไม่ได้กำหนดงบประมาณดิสก์ไว้
การบำรุงรักษาจะเก็บตัวชี้บทสนทนาภายนอกที่ทนทาน เช่น เซสชันกลุ่ม
และเซสชันแชตที่จำกัดตามเธรด แต่รายการรันไทม์สังเคราะห์สำหรับ cron, hooks,
Heartbeat, ACP, และ sub-agents ยังสามารถถูกลบได้เมื่อเกิน
อายุ จำนวน หรืองบประมาณดิสก์ที่กำหนดไว้ เซสชัน probe การรันโมเดลของ Gateway ใช้การเก็บรักษา model-run
แยกต่างหาก 24h เฉพาะเมื่อคีย์ตรงกับ
agent:*:explicit:model-run-<uuid> เท่านั้น; เซสชัน explicit อื่นไม่อยู่ใน
การเก็บรักษานั้น การล้าง model-run จะถูกใช้เฉพาะภายใต้แรงกดดันเพดานรายการเซสชัน
การรัน Cron แบบแยกเดี่ยวจะมีการควบคุม cron.sessionRetention ของตัวเอง
แยกจากการเก็บรักษา probe การรันโมเดล
OpenClaw ไม่สร้างการสำรองแบบหมุนเวียน sessions.json.bak.* อัตโนมัติระหว่างการเขียน Gateway อีกต่อไป คีย์ legacy session.maintenance.rotateBytes จะถูกละเว้น และ openclaw doctor --fix จะลบออกจากคอนฟิกเก่า
การเปลี่ยนแปลงบันทึกบทสนทนาใช้ session write lock บนไฟล์บันทึกบทสนทนา การขอ lock จะรอสูงสุด
session.writeLock.acquireTimeoutMs ก่อนแสดงข้อผิดพลาดว่าเซสชันไม่ว่าง; ค่าเริ่มต้นคือ 60000
ms เพิ่มค่านี้เฉพาะเมื่อมีงานเตรียม ล้าง Compaction หรือ mirror บันทึกบทสนทนาที่ถูกต้องตามจริงชนกัน
นานกว่านี้บนเครื่องที่ช้า session.writeLock.staleMs ควบคุมว่า lock ที่มีอยู่จะถูก
ยึดคืนเป็น stale ได้เมื่อใด; ค่าเริ่มต้นคือ 1800000 ms session.writeLock.maxHoldMs ควบคุม
เกณฑ์ปล่อย watchdog ในกระบวนการ; ค่าเริ่มต้นคือ 300000 ms env override ฉุกเฉินคือ
OPENCLAW_SESSION_WRITE_LOCK_ACQUIRE_TIMEOUT_MS, OPENCLAW_SESSION_WRITE_LOCK_STALE_MS, และ
OPENCLAW_SESSION_WRITE_LOCK_MAX_HOLD_MS
ลำดับการบังคับใช้สำหรับการล้างงบประมาณดิสก์ (mode: "enforce"):
- ลบ artifact ที่เก็บถาวรเก่าที่สุด บันทึกบทสนทนาที่ orphan หรือ trajectory ที่ orphan ก่อน
- หากยังเกินเป้าหมาย ให้ขับรายการเซสชันเก่าที่สุดและไฟล์บันทึกบทสนทนา/trajectory ของรายการนั้นออก
- ทำต่อจนกว่าการใช้งานจะอยู่ที่หรือต่ำกว่า
highWaterBytes
ใน mode: "warn" OpenClaw จะรายงานการขับออกที่อาจเกิดขึ้น แต่ไม่เปลี่ยนแปลงที่เก็บ/ไฟล์
รันการบำรุงรักษาตามต้องการ:
openclaw sessions cleanup --dry-runopenclaw sessions cleanup --enforceเซสชัน Cron และบันทึกการรัน
การรัน Cron แบบแยกเดี่ยวจะสร้างรายการเซสชัน/บันทึกบทสนทนาด้วย และมีการควบคุมการเก็บรักษาเฉพาะ:
cron.sessionRetention(ค่าเริ่มต้น24h) prune เซสชันการรัน Cron แบบแยกเดี่ยวเก่าออกจากที่เก็บเซสชัน (falseปิดใช้งาน)cron.runLog.keepLinesprune แถวประวัติการรัน SQLite ที่เก็บไว้ต่อหนึ่งงาน cron (ค่าเริ่มต้น:2000)cron.runLog.maxBytesยังคงยอมรับสำหรับบันทึกการรันแบบ file-backed เก่า
เมื่อ cron บังคับสร้างเซสชันการรันแบบแยกเดี่ยวใหม่ จะ sanitize รายการเซสชัน
cron:<jobId> ก่อนหน้าก่อนเขียนแถวใหม่ มันนำค่ากำหนดที่ปลอดภัย
เช่น การตั้งค่า thinking/fast/verbose, ป้ายกำกับ, และการ override โมเดล/auth ที่ผู้ใช้เลือกอย่างชัดเจน
ติดไปด้วย มันตัดบริบทบทสนทนาแวดล้อมออก เช่น
การกำหนดเส้นทาง channel/group, นโยบาย send หรือ queue, elevation, origin, และการผูก ACP
runtime เพื่อให้การรันแบบแยกเดี่ยวใหม่ไม่สามารถสืบทอด delivery หรือ
authority ของ runtime ที่ stale จากการรันเก่า
คีย์เซสชัน (sessionKey)
sessionKey ระบุว่า คุณอยู่ใน bucket บทสนทนาใด (การกำหนดเส้นทาง + การแยก)
รูปแบบทั่วไป:
- แชตหลัก/โดยตรง (ต่อเอเจนต์):
agent:<agentId>:<mainKey>(ค่าเริ่มต้นmain) - กลุ่ม:
agent:<agentId>:<channel>:group:<id> - ห้อง/channel (Discord/Slack):
agent:<agentId>:<channel>:channel:<id>หรือ...:room:<id> - Cron:
cron:<job.id> - Webhook:
hook:<uuid>(เว้นแต่ถูก override)
กฎ canonical ถูกบันทึกไว้ที่ /concepts/session
id เซสชัน (sessionId)
แต่ละ sessionKey ชี้ไปยัง sessionId ปัจจุบัน (ไฟล์บันทึกบทสนทนาที่ดำเนินบทสนทนาต่อ)
หลักทั่วไป:
- Reset (
/new,/reset) สร้างsessionIdใหม่สำหรับsessionKeyนั้น - การรีเซ็ตรายวัน (ค่าเริ่มต้น 4:00 AM ตามเวลาท้องถิ่นบนโฮสต์ gateway) สร้าง
sessionIdใหม่ในข้อความถัดไปหลังขอบเขตการรีเซ็ต - การหมดอายุเมื่อไม่ได้ใช้งาน (
session.reset.idleMinutesหรือ legacysession.idleMinutes) สร้างsessionIdใหม่เมื่อมีข้อความมาถึงหลังหน้าต่าง idle เมื่อกำหนดทั้งรายวัน + idle ไว้ ตัวที่หมดอายุก่อนจะชนะ - การ resume เมื่อ Control UI เชื่อมต่อใหม่ สามารถคงเซสชันที่มองเห็นอยู่ปัจจุบันไว้สำหรับการส่งหลังเชื่อมต่อใหม่หนึ่งครั้ง เมื่อ Gateway ได้รับ
sessionIdที่ตรงกันจากไคลเอนต์ UI ของผู้ปฏิบัติงาน การส่ง stale แบบปกติยังคงสร้างsessionIdใหม่ - เหตุการณ์ระบบ (Heartbeat, การปลุก cron, การแจ้งเตือน exec, งาน bookkeeping ของ gateway) อาจเปลี่ยนแปลงแถวเซสชันแต่ไม่ขยายความสดของการรีเซ็ตรายวัน/idle การ rollover ของการรีเซ็ตจะทิ้ง notice เหตุการณ์ระบบที่เข้าคิวไว้สำหรับเซสชันก่อนหน้า ก่อนสร้าง prompt ใหม่
- นโยบาย parent fork ใช้ active branch ของ OpenClaw เมื่อสร้างเธรดหรือ fork ของ subagent หาก branch นั้นใหญ่เกินไป OpenClaw จะเริ่ม child ด้วยบริบทแบบแยกแทนการล้มเหลวหรือสืบทอดประวัติที่ใช้ไม่ได้ นโยบายการกำหนดขนาดเป็นแบบอัตโนมัติ; คอนฟิก legacy
session.parentForkMaxTokensถูกลบโดยopenclaw doctor --fix
รายละเอียดการใช้งาน: การตัดสินใจเกิดขึ้นใน initSessionState() ใน src/auto-reply/reply/session.ts
สคีมาที่เก็บเซสชัน (sessions.json)
ชนิดค่าของที่เก็บคือ SessionEntry ใน src/config/sessions.ts
ฟิลด์สำคัญ (ไม่ครบทั้งหมด):
sessionId: id บันทึกบทสนทนาปัจจุบัน (ชื่อไฟล์ถูก derive จากค่านี้ เว้นแต่ตั้งค่าsessionFile)sessionStartedAt: timestamp เริ่มต้นสำหรับsessionIdปัจจุบัน; ความสดของการรีเซ็ตรายวัน ใช้ค่านี้ แถว legacy อาจ derive จาก header เซสชัน JSONLlastInteractionAt: timestamp การโต้ตอบจริงล่าสุดของผู้ใช้/channel; ความสดของการรีเซ็ตเมื่อ idle ใช้ค่านี้เพื่อให้ Heartbeat, cron, และ exec events ไม่ทำให้เซสชัน ยังมีชีวิตอยู่ แถว legacy ที่ไม่มีฟิลด์นี้จะ fallback ไปยังเวลาเริ่มเซสชันที่กู้คืน สำหรับความสดของ idleupdatedAt: timestamp การเปลี่ยนแปลงแถวที่เก็บล่าสุด ใช้สำหรับการแสดงรายการ การ pruning และ bookkeeping ค่านี้ไม่ใช่ authority สำหรับความสดของการรีเซ็ตรายวัน/idlesessionFile: override พาธบันทึกบทสนทนาแบบชัดเจนที่เป็นตัวเลือกchatType:direct | group | room(ช่วย UI และนโยบายการส่ง)provider,subject,room,space,displayName: เมทาดาทาสำหรับการตั้งป้ายกำกับ group/channel- ตัวสลับ:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(override ต่อเซสชัน)
- การเลือกโมเดล:
providerOverride,modelOverride,authProfileOverride
- ตัวนับโทเค็น (best-effort / ขึ้นกับผู้ให้บริการ):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: จำนวนครั้งที่ auto-compaction เสร็จสิ้นสำหรับคีย์เซสชันนี้memoryFlushAt: timestamp สำหรับการ flush หน่วยความจำก่อน Compaction ครั้งล่าสุดmemoryFlushCompactionCount: จำนวน Compaction เมื่อตอนที่ flush ล่าสุดรัน
ที่เก็บสามารถแก้ไขได้อย่างปลอดภัย แต่ Gateway คือ authority: มันอาจเขียนใหม่หรือ rehydrate รายการเมื่อเซสชันรัน
โครงสร้างบันทึกบทสนทนา (*.jsonl)
บันทึกบทสนทนาถูกจัดการโดย SessionManager ของ openclaw/plugin-sdk/agent-sessions
ไฟล์เป็น JSONL:
- บรรทัดแรก: header เซสชัน (
type: "session", มีid,cwd,timestamp,parentSessionแบบไม่บังคับ) - จากนั้น: รายการเซสชันที่มี
id+parentId(ต้นไม้)
ชนิดรายการที่น่าสนใจ:
message: ข้อความ user/assistant/toolResultcustom_message: ข้อความที่ส่วนขยายแทรกเข้ามาซึ่ง เข้าสู่ บริบทของโมเดล (สามารถซ่อนจาก UI ได้)custom: สถานะของส่วนขยายที่ ไม่ เข้าสู่บริบทของโมเดลcompaction: สรุป Compaction ที่คงอยู่ พร้อมfirstKeptEntryIdและtokensBeforebranch_summary: สรุปที่คงอยู่เมื่อนำทางไปยังสาขาของต้นไม้
OpenClaw ตั้งใจ ไม่ "แก้แต่ง" ทรานสคริปต์; Gateway ใช้ SessionManager เพื่ออ่าน/เขียนทรานสคริปต์เหล่านั้น
หน้าต่างบริบทเทียบกับโทเค็นที่ติดตาม
มีสองแนวคิดที่สำคัญต่างกัน:
- หน้าต่างบริบทของโมเดล: ขีดจำกัดตายตัวต่อโมเดล (โทเค็นที่โมเดลมองเห็น)
- ตัวนับของที่เก็บเซสชัน: สถิติแบบต่อเนื่องที่เขียนลงใน
sessions.json(ใช้สำหรับ /status และแดชบอร์ด)
หากคุณกำลังปรับแต่งขีดจำกัด:
- หน้าต่างบริบทมาจากแคตตาล็อกโมเดล (และสามารถเขียนทับผ่าน config ได้)
contextTokensในที่เก็บเป็นค่าประมาณ/ค่ารายงานขณะรันไทม์; อย่าถือว่าเป็นการรับประกันที่เข้มงวด
ดูเพิ่มเติมที่ /token-use
Compaction: คืออะไร
Compaction สรุปบทสนทนาเก่าลงในรายการ compaction ที่คงอยู่ในทรานสคริปต์ และเก็บข้อความล่าสุดไว้ตามเดิม
หลังจาก Compaction เทิร์นในอนาคตจะเห็น:
- สรุป Compaction
- ข้อความหลัง
firstKeptEntryId
การฉีดส่วน AGENTS.md กลับเข้าไปหลัง Compaction เป็นแบบเลือกเปิดผ่าน
agents.defaults.compaction.postCompactionSections; เมื่อไม่ได้ตั้งค่าหรือเป็น []
OpenClaw จะไม่ผนวกข้อความตัดตอนจาก AGENTS.md ทับบนสรุป Compaction
Compaction เป็นแบบ คงอยู่ (ต่างจากการตัดแต่งเซสชัน) ดู /concepts/session-pruning
ขอบเขตชังก์ของ Compaction และการจับคู่เครื่องมือ
เมื่อ OpenClaw แบ่งทรานสคริปต์ยาวออกเป็นชังก์ Compaction จะคงการจับคู่
การเรียกใช้เครื่องมือของ assistant กับรายการ toolResult ที่ตรงกันไว้
- หากการแบ่งตามสัดส่วนโทเค็นตกอยู่ระหว่างการเรียกใช้เครื่องมือกับผลลัพธ์ OpenClaw จะเลื่อนขอบเขตไปที่ข้อความเรียกใช้เครื่องมือของ assistant แทนที่จะแยก คู่นั้นออกจากกัน
- หากบล็อกผลลัพธ์เครื่องมือท้ายสุดจะทำให้ชังก์เกินเป้าหมาย OpenClaw จะรักษาบล็อกเครื่องมือที่รออยู่นั้นไว้ และคงส่วนท้ายที่ยังไม่ได้สรุปไว้ ตามเดิม
- บล็อกการเรียกใช้เครื่องมือที่ถูกยกเลิก/เกิดข้อผิดพลาดจะไม่เปิดการแบ่งที่รออยู่ค้างไว้
เมื่อใดที่ auto-compaction เกิดขึ้น (รันไทม์ OpenClaw)
ในเอเจนต์ OpenClaw แบบฝัง 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 → ลองใหม่ เมื่อผู้ให้บริการรายงานจำนวนโทเค็นที่พยายามใช้ OpenClaw จะส่งต่อ จำนวนที่สังเกตได้นั้นเข้าสู่ Compaction เพื่อกู้คืนจากการล้น หากผู้ให้บริการยืนยัน การล้นแต่ไม่เปิดเผยจำนวนที่แยกวิเคราะห์ได้ OpenClaw จะส่งจำนวนสังเคราะห์ ที่เกินงบประมาณขั้นต่ำไปยังเอนจิน Compaction และ diagnostics หากการกู้คืนเมื่อเกินขีดจำกัดยังล้มเหลว OpenClaw จะแสดงคำแนะนำที่ชัดเจนแก่ ผู้ใช้ และรักษาการแมปเซสชันปัจจุบันไว้ แทนที่จะหมุนคีย์เซสชันไปยัง id เซสชันใหม่ อย่างเงียบ ๆ ขั้นตอนถัดไปอยู่ภายใต้การควบคุมของผู้ปฏิบัติงาน: ลองส่งข้อความอีกครั้ง, รัน/compact, หรือรัน/newเมื่อต้องการเซสชันใหม่ - การบำรุงรักษาตามเกณฑ์: หลังเทิร์นสำเร็จ เมื่อ:
contextTokens > contextWindow - reserveTokens
โดยที่:
contextWindowคือหน้าต่างบริบทของโมเดลreserveTokensคือพื้นที่เผื่อที่สำรองไว้สำหรับพรอมป์ + เอาต์พุตโมเดลถัดไป
สิ่งเหล่านี้คือซีแมนติกของรันไทม์ OpenClaw
OpenClaw ยังสามารถทริกเกอร์ Compaction แบบ local ก่อนเปิดการรันถัดไป
ได้เมื่อมีการตั้งค่า agents.defaults.compaction.maxActiveTranscriptBytes และไฟล์
ทรานสคริปต์ที่ใช้งานอยู่มีขนาดถึงค่านั้น นี่เป็นตัวป้องกันตามขนาดไฟล์สำหรับต้นทุน
การเปิดซ้ำแบบ local ไม่ใช่การเก็บถาวรแบบดิบ: OpenClaw ยังคงรัน Compaction
เชิงความหมายตามปกติ และต้องใช้ truncateAfterCompaction เพื่อให้สรุปที่ถูก compact
กลายเป็นทรานสคริปต์ตัวสืบทอดใหม่ได้
สำหรับการรัน OpenClaw แบบฝัง agents.defaults.compaction.midTurnPrecheck.enabled: true
จะเพิ่มตัวป้องกันลูปเครื่องมือแบบเลือกเปิด หลังจากผนวกผลลัพธ์เครื่องมือและก่อนการเรียก
โมเดลถัดไป OpenClaw จะประมาณแรงกดดันของพรอมป์โดยใช้ตรรกะงบประมาณ preflight
เดียวกับที่ใช้ตอนเริ่มเทิร์น หากบริบทไม่พอดีอีกต่อไป ตัวป้องกันจะไม่ compact ภายใน hook
transformContext ของรันไทม์ OpenClaw แต่จะส่งสัญญาณ precheck กลางเทิร์นแบบมีโครงสร้าง
หยุดการส่งพรอมป์ปัจจุบัน และให้ลูปการรันด้านนอกใช้เส้นทางกู้คืนที่มีอยู่: ตัดผลลัพธ์เครื่องมือ
ที่ใหญ่เกินไปเมื่อเพียงพอ หรือทริกเกอร์โหมด Compaction ที่กำหนดค่าไว้แล้วลองใหม่ ตัวเลือกนี้
ปิดไว้ตามค่าเริ่มต้น และทำงานได้กับโหมด Compaction ทั้ง default และ safeguard
รวมถึง safeguard Compaction ที่มีผู้ให้บริการหนุนหลัง
สิ่งนี้เป็นอิสระจาก maxActiveTranscriptBytes: ตัวป้องกันตามขนาดไบต์จะรัน
ก่อนเปิดเทิร์น ขณะที่ precheck กลางเทิร์นจะรันภายหลังในลูปเครื่องมือ OpenClaw แบบฝัง
หลังจากผนวกผลลัพธ์เครื่องมือใหม่แล้ว
การตั้งค่า Compaction (reserveTokens, keepRecentTokens)
การตั้งค่า Compaction ของรันไทม์ OpenClaw อยู่ในการตั้งค่าเอเจนต์:
{ compaction: { enabled: true, reserveTokens: 16384, keepRecentTokens: 20000, },}OpenClaw ยังบังคับใช้ค่าขั้นต่ำเพื่อความปลอดภัยสำหรับการรันแบบฝัง:
- หาก
compaction.reserveTokens < reserveTokensFloorOpenClaw จะเพิ่มค่านั้น - ค่าขั้นต่ำเริ่มต้นคือ
20000โทเค็น - ตั้งค่า
agents.defaults.compaction.reserveTokensFloor: 0เพื่อปิดใช้ค่าขั้นต่ำ - หากค่านั้นสูงกว่าอยู่แล้ว OpenClaw จะปล่อยไว้ตามเดิม
/compactแบบ manual จะเคารพagents.defaults.compaction.keepRecentTokensที่ระบุชัดเจน และคงจุดตัดส่วนท้ายล่าสุดของรันไทม์ OpenClaw ไว้ หากไม่มีงบประมาณ keep ที่ระบุชัดเจน manual Compaction จะยังคงเป็นเช็คพอยต์แบบแข็ง และบริบทที่สร้างใหม่จะเริ่มจาก สรุปใหม่- ตั้งค่า
agents.defaults.compaction.midTurnPrecheck.enabled: trueเพื่อรัน precheck ลูปเครื่องมือแบบไม่บังคับหลังผลลัพธ์เครื่องมือใหม่และก่อนการเรียกโมเดล ถัดไป สิ่งนี้เป็นเพียงทริกเกอร์; การสร้างสรุปยังคงใช้เส้นทาง Compaction ที่กำหนดค่าไว้ สิ่งนี้เป็นอิสระจากmaxActiveTranscriptBytesซึ่งเป็น ตัวป้องกันขนาดไบต์ของทรานสคริปต์ที่ใช้งานอยู่ตอนเริ่มเทิร์น - ตั้งค่า
agents.defaults.compaction.maxActiveTranscriptBytesเป็นค่าไบต์หรือ สตริง เช่น"20mb"เพื่อรัน Compaction แบบ local ก่อนเริ่มเทิร์นเมื่อทรานสคริปต์ ที่ใช้งานอยู่มีขนาดใหญ่ ตัวป้องกันนี้ทำงานเฉพาะเมื่อเปิดใช้truncateAfterCompactionด้วยเท่านั้น ปล่อยว่างไว้หรือตั้งค่า0เพื่อ ปิดใช้ - เมื่อเปิดใช้
agents.defaults.compaction.truncateAfterCompactionOpenClaw จะหมุนทรานสคริปต์ที่ใช้งานอยู่ไปเป็น JSONL ตัวสืบทอดที่ถูก compact หลัง Compaction การดำเนินการเช็คพอยต์ branch/restore จะใช้ตัวสืบทอดที่ถูก compact นั้น; ไฟล์เช็คพอยต์ pre-compaction แบบ legacy ยังคงอ่านได้ขณะยังถูกอ้างอิง
เหตุผล: เหลือพื้นที่เผื่อให้เพียงพอสำหรับ "งานดูแลระบบ" หลายเทิร์น (เช่น การเขียน memory) ก่อนที่ Compaction จะหลีกเลี่ยงไม่ได้
การใช้งาน: applyAgentCompactionSettingsFromConfig() ใน src/agents/agent-settings.ts
(ถูกเรียกจากเส้นทางเทิร์นของ embedded-runner และการตั้งค่า Compaction)
ผู้ให้บริการ Compaction แบบเสียบได้
Plugins สามารถลงทะเบียนผู้ให้บริการ Compaction ผ่าน registerCompactionProvider() บน API ของ plugin ได้ เมื่อ agents.defaults.compaction.provider ถูกตั้งค่าเป็น id ของผู้ให้บริการที่ลงทะเบียน ส่วนขยาย safeguard จะมอบหมายการสรุปให้ผู้ให้บริการนั้นแทน pipeline summarizeInStages ในตัว
provider: id ของ plugin ผู้ให้บริการ Compaction ที่ลงทะเบียน ปล่อยว่างไว้เพื่อใช้การสรุป LLM เริ่มต้น- การตั้งค่า
providerจะบังคับmode: "safeguard" - ผู้ให้บริการจะได้รับคำสั่ง Compaction และนโยบายการรักษาตัวระบุเหมือนกับเส้นทางในตัว
- safeguard ยังคงรักษาบริบท suffix ของเทิร์นล่าสุดและเทิร์นที่ถูกแบ่งหลังเอาต์พุตของผู้ให้บริการ
- การสรุป safeguard ในตัวจะกลั่นสรุปก่อนหน้าซ้ำด้วยข้อความใหม่ แทนที่จะรักษาสรุปก่อนหน้าเต็มรูปแบบไว้ตามตัวอักษร
- โหมด safeguard เปิดใช้การตรวจสอบคุณภาพสรุปตามค่าเริ่มต้น; ตั้งค่า
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- บันทึก Gateway (
pnpm gateway:watchหรือopenclaw logs --follow):embedded run auto-compaction start+complete - โหมด verbose:
🧹 Auto-compaction complete+ จำนวน Compaction
งานดูแลระบบแบบเงียบ (NO_REPLY)
OpenClaw รองรับเทิร์นแบบ "เงียบ" สำหรับงานเบื้องหลังที่ผู้ใช้ไม่ควรเห็นเอาต์พุตระหว่างทาง
ข้อตกลง:
- assistant เริ่มเอาต์พุตด้วยโทเค็นเงียบที่ตรงกันทุกตัวอักษร
NO_REPLY/no_replyเพื่อระบุว่า "อย่าส่งคำตอบให้ผู้ใช้" - OpenClaw จะลบ/ระงับสิ่งนี้ในเลเยอร์การส่ง
- การระงับโทเค็นเงียบแบบตรงกันทุกตัวอักษรไม่สนใจตัวพิมพ์เล็กใหญ่ ดังนั้น
NO_REPLYและno_replyนับทั้งคู่เมื่อ payload ทั้งหมดเป็นเพียงโทเค็นเงียบ - สิ่งนี้มีไว้สำหรับเทิร์นเบื้องหลัง/ไม่ส่งมอบจริงเท่านั้น; ไม่ใช่ทางลัดสำหรับ คำขอผู้ใช้ที่ต้องดำเนินการตามปกติ
ตั้งแต่ 2026.1.10 OpenClaw ยังระงับ การสตรีม draft/typing เมื่อ
ชังก์บางส่วนเริ่มด้วย NO_REPLY เพื่อไม่ให้การทำงานแบบเงียบรั่วเอาต์พุตบางส่วน
ระหว่างเทิร์น
"memory flush" ก่อน Compaction (ใช้งานแล้ว)
เป้าหมาย: ก่อนเกิด auto-compaction ให้รันเทิร์น agentic แบบเงียบที่เขียนสถานะถาวร
ลงดิสก์ (เช่น memory/YYYY-MM-DD.md ในพื้นที่ทำงานของเอเจนต์) เพื่อไม่ให้ Compaction
ลบบริบทสำคัญ
OpenClaw ใช้แนวทาง pre-threshold flush:
- ตรวจสอบการใช้บริบทของเซสชัน
- เมื่อข้าม "soft threshold" (ต่ำกว่าเกณฑ์ Compaction ของรันไทม์ OpenClaw) ให้รัน directive แบบเงียบ "write memory now" ไปยังเอเจนต์
- ใช้โทเค็นเงียบที่ตรงกันทุกตัวอักษร
NO_REPLY/no_replyเพื่อให้ผู้ใช้ไม่เห็น อะไรเลย
Config (agents.defaults.compaction.memoryFlush):
enabled(ค่าเริ่มต้น:true)model(การเขียนทับ provider/model ที่ตรงกันทุกตัวอักษรแบบไม่บังคับสำหรับเทิร์น flush เช่นollama/qwen3:8b)softThresholdTokens(ค่าเริ่มต้น:4000)prompt(ข้อความผู้ใช้สำหรับเทิร์น flush)systemPrompt(พรอมป์ระบบเพิ่มเติมที่ผนวกสำหรับเทิร์น flush)
หมายเหตุ:
- พรอมป์/พรอมป์ระบบเริ่มต้นมีคำใบ้
NO_REPLYเพื่อระงับ การส่งมอบ - เมื่อมีการตั้งค่า
modelเทิร์น flush จะใช้โมเดลนั้นโดยไม่สืบทอด fallback chain ของเซสชันที่ใช้งานอยู่ ดังนั้นงานดูแลระบบแบบ local-only จะไม่ fallback ไปยังโมเดลสนทนาแบบเสียเงินอย่างเงียบ ๆ - flush จะรันหนึ่งครั้งต่อรอบ Compaction (ติดตามใน
sessions.json) - flush จะรันเฉพาะสำหรับเซสชัน OpenClaw แบบฝังเท่านั้น (แบ็กเอนด์ CLI จะข้าม)
- flush จะถูกข้ามเมื่อพื้นที่ทำงานของเซสชันเป็นแบบอ่านอย่างเดียว (
workspaceAccess: "ro"หรือ"none") - ดู Memory สำหรับเลย์เอาต์ไฟล์พื้นที่ทำงานและรูปแบบการเขียน
OpenClaw ยังเปิดเผย hook session_before_compact ใน API ของส่วนขยายด้วย แต่ตรรกะ
flush ของ OpenClaw อยู่ฝั่ง Gateway ในปัจจุบัน
เช็กลิสต์การแก้ปัญหา
- คีย์เซสชันผิดหรือไม่ เริ่มจาก /concepts/session และยืนยัน
sessionKeyใน/status - ที่เก็บกับทรานสคริปต์ไม่ตรงกันหรือไม่ ยืนยันโฮสต์ Gateway และเส้นทางที่เก็บจาก
openclaw status - Compaction เกิดถี่เกินไปหรือไม่ ตรวจสอบ:
- หน้าต่างบริบทของโมเดล (เล็กเกินไป)
- การตั้งค่า Compaction (
reserveTokensสูงเกินไปสำหรับหน้าต่างโมเดลอาจทำให้ Compaction เกิดเร็วขึ้น) - ผลลัพธ์เครื่องมือบวม: เปิดใช้/ปรับแต่งการตัดแต่งเซสชัน
- เทิร์นเงียบรั่วหรือไม่ ยืนยันว่าคำตอบเริ่มด้วย
NO_REPLY(โทเค็นตรงกันทุกตัวอักษรแบบไม่สนใจตัวพิมพ์เล็กใหญ่) และคุณอยู่บนบิลด์ที่มีการแก้ไขการระงับสตรีมมิง