การจัดการเซสชันและการคอมแพคชัน(เจาะลึก)¶
เอกสารนี้อธิบายวิธีที่ OpenClaw จัดการเซสชันแบบครบวงจร:
- การกำหนดเส้นทางเซสชัน (ข้อความขาเข้าถูกแมปไปยัง
sessionKeyอย่างไร) - ที่เก็บเซสชัน (
sessions.json) และสิ่งที่ติดตาม - การคงอยู่ของทรานสคริปต์ (
*.jsonl) และโครงสร้าง - สุขอนามัยของทรานสคริปต์ (การปรับแก้เฉพาะผู้ให้บริการก่อนรัน)
- ขีดจำกัดบริบท (หน้าต่างบริบทเทียบกับโทเคนที่ติดตาม)
- การคอมแพคชัน (แบบแมนนวล+อัตโนมัติ) และตำแหน่งสำหรับเชื่อมงานก่อนการคอมแพคชัน
- งานดูแลแบบเงียบ (เช่น การเขียนหน่วยความจำที่ไม่ควรแสดงผลต่อผู้ใช้)
หากต้องการภาพรวมระดับสูงก่อน ให้เริ่มที่:
แหล่งอ้างอิงหลัก: Gateway¶
OpenClaw ถูกออกแบบโดยมี กระบวนการ Gateway เพียงหนึ่งเดียว ที่เป็นเจ้าของสถานะเซสชัน
- UI ต่างๆ(แอปmacOS, Control UI บนเว็บ, TUI) ควรถาม Gateway เพื่อดึงรายการเซสชันและจำนวนโทเคน
- ในโหมดระยะไกล ไฟล์เซสชันจะอยู่บนโฮสต์ระยะไกล การ “ตรวจดูไฟล์บน Mac ของคุณ” จะไม่สะท้อนสิ่งที่ Gateway ใช้งานอยู่
ชั้นการคงอยู่สองชั้น¶
OpenClaw คงอยู่เซสชันในสองชั้น:
-
ที่เก็บเซสชัน (
sessions.json) - แผนที่คีย์/ค่า:sessionKey -> SessionEntry- ขนาดเล็ก เปลี่ยนแปลงได้ ปลอดภัยต่อการแก้ไข(หรือลบรายการ) - ติดตามเมทาดาทาเซสชัน(session id ปัจจุบัน กิจกรรมล่าสุด สวิตช์ ตัวนับโทเคน ฯลฯ) -
ทรานสคริปต์ (
<sessionId>.jsonl) - ทรานสคริปต์แบบต่อท้ายอย่างเดียวพร้อมโครงสร้างแบบต้นไม้(รายการมีid+parentId) - เก็บการสนทนาจริง+การเรียกเครื่องมือ+สรุปการคอมแพคชัน - ใช้สร้างบริบทของโมเดลใหม่สำหรับรอบถัดไป
ตำแหน่งบนดิสก์¶
ต่อเอเจนต์ บนโฮสต์Gateway:
- ที่เก็บ:
~/.openclaw/agents/<agentId>/sessions/sessions.json - บันทึกการสนทนา:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl - เซสชันหัวข้อของTelegram:
.../<sessionId>-topic-<threadId>.jsonl
OpenClaw แก้ไขเส้นทางเหล่านี้ผ่าน src/config/sessions.ts.
คีย์เซสชัน (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.
session id (sessionId)¶
แต่ละ sessionKey ชี้ไปยัง sessionId ปัจจุบัน(ไฟล์ทรานสคริปต์ที่ใช้สานต่อการสนทนา)
กฎโดยสรุป:
- รีเซ็ต (
/new,/reset) จะสร้างsessionIdใหม่สำหรับsessionKeyนั้น - รีเซ็ตรายวัน (ค่าเริ่มต้น 04:00 น. ตามเวลาท้องถิ่นบนโฮสต์Gateway) จะสร้าง
sessionIdใหม่ในข้อความถัดไปหลังเส้นแบ่งการรีเซ็ต - หมดอายุจากความไม่ใช้งาน (
session.reset.idleMinutesหรือแบบเดิมsession.idleMinutes) จะสร้างsessionIdใหม่เมื่อมีข้อความเข้ามาหลังพ้นช่วงไม่ใช้งาน เมื่อกำหนดทั้งรายวัน+ไม่ใช้งาน กรณีที่หมดอายุก่อนจะถูกใช้ ประเภทเอนทรีที่น่าสนใจ:
รายละเอียดการทำงาน: การตัดสินใจเกิดขึ้นใน initSessionState() ใน src/auto-reply/reply/session.ts.
สคีมาที่เก็บเซสชัน (sessions.json)¶
ชนิดค่าของ store คือ SessionEntry ใน src/config/sessions.ts.
ฟิลด์สำคัญ(ไม่ครบถ้วน):
sessionId: id ทรานสคริปต์ปัจจุบัน(ชื่อไฟล์ได้จากค่านี้เว้นแต่ตั้งsessionFile)updatedAt: เวลาประทับกิจกรรมล่าสุดsessionFile: การแทนที่เส้นทางทรานสคริปต์แบบชัดเจน(ไม่บังคับ)chatType:direct | group | room(ช่วย UI และนโยบายการส่ง)provider,subject,room,space,displayName: เมทาดาทาสำหรับการติดป้ายกลุ่ม/ช่องทาง- สวิตช์:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(แทนที่ระดับต่อเซสชัน)- การเลือกโมเดล:
providerOverride,modelOverride,authProfileOverride- ตัวนับโทเคน(ดีที่สุดเท่าที่ทำได้/ขึ้นกับผู้ให้บริการ):
inputTokens,outputTokens,totalTokens,contextTokenscompactionCount: ความถี่ที่การคอมแพคชันอัตโนมัติสำเร็จสำหรับคีย์เซสชันนี้memoryFlushAt: เวลาประทับของการฟลัชหน่วยความจำก่อนคอมแพคชันครั้งล่าสุดmemoryFlushCompactionCount: จำนวนครั้งการคอมแพคชันเมื่อการฟลัชครั้งล่าสุดรัน
ที่เก็บสามารถแก้ไขได้อย่างปลอดภัย แต่ Gateway เป็นผู้มีอำนาจ: อาจเขียนทับหรือเติมข้อมูลรายการใหม่เมื่อเซสชันรัน
โครงสร้างทรานสคริปต์ (*.jsonl)¶
ทรานสคริปต์ถูกจัดการโดย @mariozechner/pi-coding-agent ของ SessionManager.
ไฟล์เป็น JSONL:
- บรรทัดแรก: ส่วนหัวเซสชัน(
type: "session"รวมid,cwd,timestamp, และparentSessionแบบไม่บังคับ) - จากนั้น: รายการเซสชันที่มี
id+parentId(โครงสร้างต้นไม้)
Compaction เป็นแบบ ถาวร (ไม่เหมือนกับ session pruning)
message: ข้อความผู้ใช้/ผู้ช่วย/ผลลัพธ์เครื่องมือcustom_message: ข้อความที่ส่วนขยายแทรกและ เข้าสู่ บริบทโมเดล(ซ่อนจาก UI ได้)custom: สถานะส่วนขยายที่ ไม่เข้าสู่ บริบทโมเดลcompaction: สรุปการคอมแพคชันที่ถูกคงอยู่พร้อมfirstKeptEntryIdและtokensBeforebranch_summary: สรุปที่ถูกคงอยู่เมื่อสลับสาขาของต้นไม้
OpenClaw ตั้งใจ ไม่ “แก้ไข” ทรานสคริปต์; Gateway ใช้ SessionManager เพื่ออ่าน/เขียน
หน้าต่างบริบทเทียบกับโทเคนที่ติดตาม¶
มีสองแนวคิดที่ต่างกัน:
- หน้าต่างบริบทของโมเดล: ขีดจำกัดตายตัวต่อโมเดล(โทเคนที่มองเห็นโดยโมเดล)
- ตัวนับในที่เก็บเซสชัน: สถิติแบบกลิ้งที่เขียนลงใน
sessions.json(ใช้สำหรับ /status และแดชบอร์ด)
หากคุณกำลังปรับจูนขีดจำกัด:
- หน้าต่างบริบทมาจากแคตตาล็อกโมเดล(และสามารถแทนที่ผ่านคอนฟิก)
contextTokensใน store เป็นค่าประมาณ/รายงานระหว่างรัน อย่าถือเป็นการรับประกันแบบเข้มงวด
ดูเพิ่มเติมที่ /token-use.
การคอมแพคชัน: คืออะไร¶
การคอมแพคชันจะสรุปการสนทนาเก่าเป็นรายการ compaction ที่ถูกคงอยู่ในทรานสคริปต์ และคงข้อความล่าสุดไว้ครบถ้วน
หลังการคอมแพคชัน รอบถัดไปจะเห็น:
- สรุปการคอมแพคชัน
- ข้อความหลัง
firstKeptEntryId
ธรรมเนียมปฏิบัติ: การคอมแพคชันเป็นแบบ คงอยู่ถาวร (ต่างจากการตัดแต่งเซสชัน) ดู /concepts/session-pruning.
เมื่อใดที่การคอมแพคชันอัตโนมัติเกิดขึ้น (รันไทม์Pi)¶
ในเอเจนต์Piแบบฝัง การคอมแพคชันอัตโนมัติจะทริกเกอร์ในสองกรณี:
- กู้คืนจากโอเวอร์โฟลว์: โมเดลส่งข้อผิดพลาดบริบทล้น → คอมแพค → ลองใหม่
- บำรุงรักษาตามเกณฑ์: หลังรอบที่สำเร็จ เมื่อ:
contextTokens > contextWindow - reserveTokens
โดยที่:
contextWindowคือหน้าต่างบริบทของโมเดลreserveTokensคือพื้นที่เผื่อสำหรับพรอมป์ต์+เอาต์พุตโมเดลถัดไป
นี่คือความหมายเชิงรันไทม์ของPi(OpenClaw รับอีเวนต์ แต่Piเป็นผู้ตัดสินใจว่าจะคอมแพคเมื่อใด)
การตั้งค่าการคอมแพคชัน (reserveTokens, keepRecentTokens)¶
การตั้งค่าการคอมแพคชันของPiอยู่ใน Pi settings:
{
compaction: {
enabled: true,
reserveTokens: 16384,
keepRecentTokens: 20000,
},
}
OpenClaw ยังบังคับใช้ค่า safety floor สำหรับการรันแบบฝัง:
- หาก
compaction.reserveTokens < reserveTokensFloor, OpenClaw จะปรับเพิ่ม - ค่าเริ่มต้นของ floor คือ
20000โทเคน - ตั้ง
agents.defaults.compaction.reserveTokensFloor: 0เพื่อปิด floor - หากค่าสูงกว่าอยู่แล้ว OpenClaw จะไม่เปลี่ยน
เหตุผล: เหลือพื้นที่เผื่อพอสำหรับ “งานดูแล” หลายรอบ(เช่น การเขียนหน่วยความจำ) ก่อนที่การคอมแพคชันจะหลีกเลี่ยงไม่ได้
การติดตั้ง: ensurePiCompactionReserveTokens() ใน src/agents/pi-settings.ts
(ถูกเรียกจาก src/agents/pi-embedded-runner.ts).
พื้นผิวที่ผู้ใช้มองเห็น¶
คุณสามารถสังเกตการคอมแพคชันและสถานะเซสชันได้ผ่าน:
/status(ในทุกเซสชันแชต)openclaw status(CLI)openclaw sessions/sessions --json- โหมด verbose:
🧹 Auto-compaction complete+ จำนวนครั้งการคอมแพคชัน
งานดูแลแบบเงียบ (NO_REPLY)¶
OpenClaw รองรับรอบแบบ “เงียบ” สำหรับงานเบื้องหลังที่ผู้ใช้ไม่ควรเห็นเอาต์พุตระหว่างทาง
นี่คือ Clawd ผู้ให้กำเนิดกุ้งล็อบสเตอร์ของคุณ
- ผู้ช่วยเริ่มเอาต์พุตด้วย
NO_REPLYเพื่อระบุว่า “อย่าส่งคำตอบให้ผู้ใช้” - OpenClaw จะตัด/ระงับสิ่งนี้ในชั้นการส่งมอบ
ตั้งแต่ 2026.1.10 เป็นต้นมา OpenClaw ยังระงับ การสตรีมแบบร่าง/ตัวบ่งชี้การพิมพ์ เมื่อชังก์บางส่วนเริ่มด้วย NO_REPLY เพื่อไม่ให้การทำงานเงียบรั่วเอาต์พุตระหว่างรอบ
“การฟลัชหน่วยความจำ” ก่อนการคอมแพคชัน (ติดตั้งแล้ว)¶
เป้าหมาย: ก่อนการคอมแพคชันอัตโนมัติ จะรันรอบเอเจนต์แบบเงียบเพื่อเขียนสถานะที่คงทน
ลงดิสก์(เช่น memory/YYYY-MM-DD.md ในเวิร์กสเปซเอเจนต์) เพื่อไม่ให้การคอมแพคชัน
ลบบริบทสำคัญ
OpenClaw ใช้วิธี pre-threshold flush:
- เฝ้าดูการใช้บริบทของเซสชัน
- เมื่อข้าม “soft threshold”(ต่ำกว่าเกณฑ์คอมแพคชันของPi) ให้รันคำสั่งเงียบ “เขียนหน่วยความจำเดี๋ยวนี้” ไปยังเอเจนต์
- ใช้
NO_REPLYเพื่อให้ผู้ใช้ไม่เห็นอะไร
คอนฟิก (agents.defaults.compaction.memoryFlush):
enabled(ค่าเริ่มต้น:true)softThresholdTokens(ค่าเริ่มต้น:4000)prompt(ข้อความผู้ใช้สำหรับรอบฟลัช)systemPrompt(system prompt เพิ่มเติมที่ต่อท้ายสำหรับรอบฟลัช)
หมายเหตุ:
- พรอมป์ต์เริ่มต้น/system prompt มีคำใบ้
NO_REPLYเพื่อระงับการส่งมอบ - การฟลัชจะรันหนึ่งครั้งต่อรอบการคอมแพคชัน(ติดตามใน
sessions.json) - การฟลัชจะรันเฉพาะเซสชันPiแบบฝัง(แบ็กเอนด์CLIจะข้าม)
- จะข้ามการฟลัชเมื่อเวิร์กสเปซเซสชันเป็นแบบอ่านอย่างเดียว(
workspaceAccess: "ro"หรือ"none") - ดู Memory สำหรับเลย์เอาต์ไฟล์เวิร์กสเปซและรูปแบบการเขียน
Pi ยังเปิดเผยฮุก session_before_compact ใน API ของส่วนขยาย แต่ตรรกะการฟลัชของ OpenClaw
อยู่ฝั่ง Gateway ในปัจจุบัน
เช็กลิสต์การแก้ไขปัญหา¶
- คีย์เซสชันผิด? เริ่มที่ /concepts/session และยืนยัน
sessionKeyใน/status. - Store กับทรานสคริปต์ไม่ตรงกัน? ยืนยันโฮสต์Gatewayและเส้นทาง store จาก
openclaw status. - การคอมแพคถี่เกิน? ตรวจสอบ:
- หน้าต่างบริบทของโมเดล(เล็กเกินไป)
- การตั้งค่าการคอมแพคชัน(
reserveTokensสูงเกินไปเมื่อเทียบกับหน้าต่างโมเดลอาจทำให้คอมแพคเร็วขึ้น) - บวมจากผลลัพธ์เครื่องมือ: เปิด/ปรับการตัดแต่งเซสชัน
- รอบเงียบรั่วเอาต์พุต? ยืนยันว่าคำตอบเริ่มด้วย
NO_REPLY(โทเคนตรงตัว) และคุณใช้บิลด์ที่มีการแก้ไขการระงับสตรีมมิงแล้ว