Technical reference

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

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

  • การกำหนดเส้นทางเซสชัน (วิธีที่ข้อความขาเข้าจับคู่กับ sessionKey)
  • ที่จัดเก็บเซสชัน (sessions.json) และสิ่งที่ติดตาม
  • การคงอยู่ของทรานสคริปต์ (*.jsonl) และโครงสร้างของมัน
  • สุขอนามัยของทรานสคริปต์ (การปรับแก้เฉพาะผู้ให้บริการก่อนรัน)
  • ขีดจำกัดบริบท (หน้าต่างบริบทเทียบกับโทเค็นที่ติดตาม)
  • Compaction (แบบกำหนดเองและ auto-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 เป็นเมทาดาทาเหนือทรานสคริปต์ตัวสืบทอดที่ถูกย่อแล้ว การทำ 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 sidecar:

  • mode: enforce (ค่าเริ่มต้น) หรือ warn
  • pruneAfter: จุดตัดอายุรายการที่เก่า (ค่าเริ่มต้น 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"):

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

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

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

bash
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 อาจได้ค่านี้มาจากส่วนหัวเซสชัน JSONL
  • lastInteractionAt: ประทับเวลาการโต้ตอบจริงล่าสุดของผู้ใช้/ช่องทาง; การรีเซ็ตเมื่อไม่ได้ใช้งาน ใช้ค่านี้เพื่อพิจารณาความสดใหม่ เพื่อให้เหตุการณ์ Heartbeat, Cron และ exec ไม่ทำให้เซสชัน ยังมีชีวิตอยู่ แถว legacy ที่ไม่มีฟิลด์นี้จะย้อนกลับไปใช้เวลาเริ่มต้นเซสชันที่กู้คืนได้ สำหรับความสดใหม่เมื่อไม่ได้ใช้งาน
  • updatedAt: ประทับเวลาการเปลี่ยนแปลงแถวในที่เก็บครั้งล่าสุด ใช้สำหรับการแสดงรายการ การตัดทิ้ง และ งานบันทึกบัญชี ค่านี้ไม่ใช่แหล่งอ้างอิงสำหรับความสดใหม่ของการรีเซ็ตรายวัน/เมื่อไม่ได้ใช้งาน
  • archivedAt: ประทับเวลาการเก็บถาวรแบบไม่บังคับ เซสชันที่เก็บถาวรจะยังอยู่ในที่เก็บ โดยทรานสคริปต์ยังคงครบถ้วน และจะถูกยกเว้นจากรายการที่ใช้งานปกติ
  • pinnedAt: ประทับเวลาการปักหมุดแบบไม่บังคับ เซสชันที่ใช้งานและถูกปักหมุดจะเรียงอยู่ก่อน เซสชันที่ไม่ถูกปักหมุด; การเก็บถาวรเซสชันจะล้างการปักหมุดของเซสชันนั้น
  • การทำงานร่วมกันกับเธรด Codex: ทั้งสองฟิลด์ทำตามรูปแบบการจัดการเธรดของ Codex — บูลีน archived/pinned บน wire จะถูกคำนวณจากประทับเวลาเสมอ และประทับฝั่งเซิร์ฟเวอร์ โดยสอดคล้องกับ semantics ของ Codex threads.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, elevatedLevel
    • sendPolicy (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/toolResult
  • custom_message: ข้อความที่ extension แทรกเข้ามาและ เข้าสู่ บริบทโมเดล (สามารถซ่อนจาก UI ได้)
  • custom: สถานะ extension ที่ ไม่ เข้าสู่บริบทโมเดล
  • compaction: สรุป Compaction ที่ persist ไว้พร้อม firstKeptEntryId และ tokensBefore
  • branch_summary: สรุปที่ persist ไว้เมื่อนำทางในกิ่งของ tree

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


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

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

  1. หน้าต่างบริบทของโมเดล: เพดานแข็งต่อโมเดล (โทเค็นที่โมเดลมองเห็น)
  2. ตัวนับในที่เก็บเซสชัน: สถิติแบบ 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 จะทริกเกอร์ในสองกรณี:

  1. การกู้คืนจาก 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 เมื่อ ต้องการเซสชันใหม่
  2. การบำรุงรักษาตาม 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 อยู่ในการตั้งค่าเอเจนต์:

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

OpenClaw ยังบังคับใช้ safety floor สำหรับการรันแบบฝัง:

  • หาก compaction.reserveTokens < reserveTokensFloor OpenClaw จะเพิ่มค่าให้
  • 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.truncateAfterCompaction OpenClaw จะหมุนทรานสคริปต์ที่ใช้งานไปเป็น 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 ใช้วิธี ล้างก่อนถึงเกณฑ์:

  1. ตรวจสอบการใช้บริบทของเซสชัน
  2. เมื่อข้าม "เกณฑ์อ่อน" (ต่ำกว่าเกณฑ์ Compaction ของรันไทม์ OpenClaw) ให้รันคำสั่งแบบเงียบ "เขียนหน่วยความจำตอนนี้" ไปยังเอเจนต์
  3. ใช้โทเค็นเงียบแบบตรงตัว 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 (โทเค็นตรงตัวแบบไม่แยกตัวพิมพ์เล็ก-ใหญ่) และคุณอยู่บนบิลด์ที่รวมการแก้ไขการระงับการสตรีมแล้ว

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

Was this useful?
On this page

On this page