---
read_when:
    - คุณต้องแก้ไขข้อบกพร่องเกี่ยวกับรหัสเซสชัน เหตุการณ์ในบันทึกบทสนทนา หรือฟิลด์แถวของเซสชัน
    - คุณกำลังเปลี่ยนพฤติกรรมการทำ Compaction อัตโนมัติหรือเพิ่มการจัดการเตรียมความพร้อม "ก่อนทำ Compaction"
    - คุณต้องการใช้การล้างหน่วยความจำหรือรอบการทำงานของระบบแบบเงียบ
summary: 'เจาะลึก: กลไกภายในของที่เก็บเซสชันและบทถอดความ วงจรชีวิต และ Compaction (อัตโนมัติ)'
title: เจาะลึกการจัดการเซสชัน
x-i18n:
    generated_at: "2026-07-20T06:09:15Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 32
    provider: openai
    source_hash: ce3f4d5bc40f454f98950ec88230ad5caadb224e25c779f26a7b87f3349de47b
    source_path: reference/session-management-compaction.md
    workflow: 16
---

กระบวนการ **Gateway เพียงกระบวนการเดียว** เป็นเจ้าของสถานะเซสชันตั้งแต่ต้นจนจบ UI ต่างๆ (แอป macOS, Control UI บนเว็บ, TUI) จะสอบถามรายการเซสชันและจำนวนโทเค็นจาก Gateway ในโหมดระยะไกล ไฟล์เซสชันจะอยู่บนโฮสต์ระยะไกล ดังนั้นการตรวจสอบไฟล์ใน Mac เครื่องของคุณจะไม่สะท้อนสิ่งที่ Gateway กำลังใช้งาน

เริ่มจากเอกสารภาพรวม: [การจัดการเซสชัน](/th/concepts/session), [Compaction](/th/concepts/compaction), [ภาพรวมหน่วยความจำ](/th/concepts/memory), [การค้นหาหน่วยความจำ](/th/concepts/memory-search), [การตัดแต่งเซสชัน](/th/concepts/session-pruning), [การดูแลความสะอาดของบันทึกบทสนทนา](/th/reference/transcript-hygiene), และข้อมูลอ้างอิงการกำหนดค่าฉบับเต็มที่ [การกำหนดค่าเอเจนต์](/th/gateway/config-agents)

## ชั้นการจัดเก็บถาวรสองชั้น

1. **แถวเซสชัน (SQLite ต่อเอเจนต์)** - แมปคีย์/ค่า `sessionKey -> SessionEntry` สถานะรันไทม์ที่เปลี่ยนแปลงได้ซึ่ง Gateway เป็นเจ้าของ ติดตามเมทาดาทา ได้แก่ ID เซสชันปัจจุบัน กิจกรรมล่าสุด ตัวเลือกเปิด/ปิด ตัวนับโทเค็น
2. **เหตุการณ์บันทึกบทสนทนา (SQLite ต่อเอเจนต์)** - เพิ่มต่อท้ายเท่านั้นและมีโครงสร้างแบบต้นไม้ (รายการมี `id` + `parentId`) จัดเก็บบทสนทนา การเรียกใช้เครื่องมือ และสรุป Compaction รวมถึงสร้างบริบทโมเดลขึ้นใหม่สำหรับรอบถัดไป จุดตรวจสอบ Compaction เป็นเมทาดาทาที่ครอบทับบันทึกบทสนทนาตัวสืบทอดซึ่งผ่านการ Compaction แล้ว การ Compaction ครั้งใหม่จะไม่เขียนสำเนา `.checkpoint.*.jsonl` ชุดที่สอง

การติดตั้งรุ่นเก่าอาจยังมีไฟล์ `sessions.json` อยู่ภายใต้ไดเรกทอรี `sessions/`
ของเอเจนต์ ให้ถือว่าไฟล์เหล่านั้นเป็นอินพุตสำหรับการย้ายแถวเซสชันแบบเดิมหรือเป็น
เป้าหมายการบำรุงรักษาแบบออฟไลน์อย่างชัดเจน การเริ่มต้น Gateway และ `openclaw doctor --fix`
จะนำเข้าแถวเดิมที่ใช้งานอยู่และประวัติบันทึกบทสนทนาไปยังที่เก็บ SQLite ต่อเอเจนต์
โดยอัตโนมัติ เรียกใช้ `openclaw doctor --session-sqlite inspect
--session-sqlite-all-agents` แล้วทำตาม[ลำดับการย้ายข้อมูลของ
Doctor](/th/cli/doctor#session-sqlite-migration) เมื่อต้องการหลักฐานการตรวจสอบ
หรือการยืนยันอย่างชัดเจน หากการย้ายข้อมูลล้มเหลวหลังจากเก็บอาร์ติแฟกต์บันทึกบทสนทนา
แบบเดิมเข้าคลังแล้ว ให้ใช้โหมดกู้คืนของ Doctor จากลำดับดังกล่าว
การกู้คืนจะใช้ไฟล์รายการการย้ายข้อมูล คืนค่าเฉพาะอาร์ติแฟกต์สนับสนุนที่เก็บถาวร
และได้รับผลกระทบ จัดเตรียมรายงานปัญหา GitHub ที่ผ่านการล้างข้อมูลเมื่อมีการร้องขอ
และไม่ทำให้รันไทม์ที่ใช้งานอยู่กลับมาอ่านไฟล์ JSONL อีกครั้ง

ตัวอ่านประวัติของ Gateway จะหลีกเลี่ยงการโหลดบันทึกบทสนทนาทั้งหมดไว้ในหน่วยความจำ เว้นแต่พื้นผิวนั้นต้องเข้าถึงประวัติส่วนใดก็ได้ ประวัติหน้าแรก ประวัติแชตที่ฝังอยู่ การกู้คืนหลังรีสตาร์ต และการตรวจสอบโทเค็น/การใช้งาน ใช้การอ่านส่วนท้ายแบบจำกัดจาก SQLite การสแกนบันทึกบทสนทนาทั้งหมดจะผ่านดัชนีบันทึกบทสนทนาแบบอะซิงโครนัสและใช้ร่วมกันระหว่างตัวอ่านที่ทำงานพร้อมกัน

## ตำแหน่งบนดิสก์

สำหรับแต่ละเอเจนต์ บนโฮสต์ Gateway (แก้ไขตำแหน่งผ่าน `src/config/sessions.ts`):

- ที่เก็บแถวเซสชันรันไทม์: `~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite`
- แถวบันทึกบทสนทนารันไทม์: `~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite`
- อาร์ติแฟกต์บันทึกบทสนทนาแบบเดิม/ที่เก็บถาวร: `~/.openclaw/agents/<agentId>/sessions/`
- อินพุตการย้ายแถวแบบเดิม: `~/.openclaw/agents/<agentId>/sessions/sessions.json`

## การบำรุงรักษาที่เก็บและการควบคุมดิสก์

`session.maintenance` ควบคุมการบำรุงรักษาอัตโนมัติสำหรับแถวเซสชัน SQLite แถวบันทึกบทสนทนา SQLite อาร์ติแฟกต์ที่เก็บถาวร และไฟล์ประกอบวิถีการทำงาน:

| คีย์                     | ค่าเริ่มต้น               | หมายเหตุ                                                                                       |
| ----------------------- | --------------------- | ------------------------------------------------------------------------------------------- |
| `mode`                  | `"enforce"`           | หรือ `"warn"` (รายงานเท่านั้น ไม่มีการแก้ไข)                                                      |
| `pruneAfter`            | `"30d"`               | เกณฑ์อายุของรายการที่ล้าสมัย                                                                      |
| `maxEntries`            | `500`                 | ขีดจำกัดจำนวนรายการเซสชัน                                                                      |
| `resetArchiveRetention` | เก็บไว้ (ไม่มีเกณฑ์อายุ)  | เกณฑ์อายุสำหรับคลังบันทึกบทสนทนา `*.reset.*`/`*.deleted.*`; การระบุระยะเวลาจะเปิดใช้การลบ |
| `maxDiskBytes`          | `10gb`                | งบประมาณดิสก์สำหรับเซสชันต่อเอเจนต์; `false` ปิดใช้งาน                                            |
| `highWaterBytes`        | 80% ของ `maxDiskBytes` | เป้าหมายหลังการล้างข้อมูลตามงบประมาณ                                                                 |

การรีเซ็ตจะเลื่อนแมปปิง `sessionKey -> sessionId` ที่ใช้งานอยู่ไปข้างหน้า แต่เก็บเซสชัน บันทึกบทสนทนา วิถีการทำงาน และแถวการค้นหา SQLite ก่อนหน้าไว้ ประวัตินั้นยังคงค้นหาได้ภายใต้คีย์เซสชันเดิม รายการทั่วไปของรายการและเซสชันจะแสดงเฉพาะแมปปิงใหม่ที่ใช้งานอยู่ ประวัติการรีเซ็ตที่เก็บไว้จะถูกจำกัดด้วยงบประมาณดิสก์ ไม่ใช่ `resetArchiveRetention` ซึ่งกำหนดอายุเฉพาะอาร์ติแฟกต์ที่เก็บถาวรเท่านั้น การลบอย่างชัดเจนแตกต่างออกไป โดยจะเขียนและตรวจสอบคลังบันทึกบทสนทนาแบบบีบอัด (`*.jsonl.deleted.<timestamp>.zst` เมื่อมี zstd) ก่อนลบแถวของเซสชันที่ถูกลบ

การบังคับใช้ `maxDiskBytes` ใช้จำนวนไบต์จริง ได้แก่ ไฟล์หลัก SQLite ต่อเอเจนต์ ไฟล์ `-wal` ของไฟล์ดังกล่าว และไฟล์ที่นับรวมในไดเรกทอรีเซสชันของเอเจนต์ ระบบจะไม่ประเมินขนาด JSON ของแถวหรือหักขนาดเชิงตรรกะของแถวออกจากยอดรวมนั้น

เซสชันตรวจสอบการรันโมเดลของ Gateway (คีย์ที่ตรงกับ `agent:*:explicit:model-run-<uuid>`) มีระยะเวลาการเก็บรักษา `24h` แบบคงที่แยกต่างหาก การตัดแต่งนี้จะทำงานเมื่อมีแรงกดดันเท่านั้น กล่าวคือจะทำงานเฉพาะเมื่อถึงจุดที่ต้องบำรุงรักษา/จำกัดรายการเซสชัน และเฉพาะก่อนขั้นตอนล้างข้อมูล/จำกัดรายการล้าสมัยทั่วระบบ เซสชันแบบชัดเจนอื่นๆ จะไม่ใช้ระยะเวลาการเก็บรักษานี้

เมื่อการใช้งานจริงรวมเกิน `maxDiskBytes` ขั้นตอน `mode: "enforce"` จะเรียกคืนพื้นที่ฐานข้อมูลที่สร้างจุดตรวจสอบได้ก่อน จากนั้นจึงลบคลังการรีเซ็ต/การลบที่เก็บไว้ซึ่งเก่าที่สุด หากการใช้งานยังสูงกว่า `highWaterBytes` ระบบจะไล่ตรวจเซสชัน SQLite ในอดีตตาม `sessions.updated_at` โดยเริ่มจากรายการเก่าที่สุด “ในอดีต” หมายถึง ID เซสชันไม่ได้ถูกอ้างอิงโดยรายการเซสชันที่ใช้งานอยู่ เป้าหมายเส้นทาง หรือการรันที่รับแล้ว/กำลังดำเนินการ สำหรับแต่ละรายการเป้าหมาย การล้างข้อมูลจะเขียน เรียก fsync และอ่านคลังแบบบีบอัดกลับมาตรวจสอบ ก่อนที่ธุรกรรมการเขียนจะลบแถวเซสชันและการฉายภาพบันทึกบทสนทนา วิถีการทำงาน สถานะใช้งาน ดัชนี และ FTS ของเซสชันนั้น ซึ่งรวมถึงเซสชันที่มีเหตุการณ์วิถีการทำงานแต่ไม่มีเหตุการณ์บันทึกบทสนทนา การล้างข้อมูลจะตรวจสอบการอ้างอิงเส้นทาง รายการ และการรับงานอีกครั้งขณะลบ วัดการใช้งานจริงใหม่หลังจากลบคลังหรือเซสชันเป้าหมายแต่ละรายการ และหยุดที่ `highWaterBytes`

การเขียนที่ยืนยันแล้วและการลบจะลงใน WAL ก่อน การล้างข้อมูลจะสร้างจุดตรวจสอบเพื่อให้ WAL ย่อขนาดได้ทันที จากนั้นใช้ incremental vacuum เพื่อคืนหน้าส่วนท้ายที่ว่างและมีสิทธิ์เรียกคืนจากไฟล์หลัก หน้าที่ยังเรียกคืนไม่ได้จะคงอยู่ในไฟล์หลักและจึงยังถูกนับในการวัดจริงครั้งถัดไป `mode: "warn"` รายงานปริมาณจริงที่เกินอยู่ในปัจจุบันโดยไม่สร้างจุดตรวจสอบ ไม่เขียนคลัง และไม่ลบแถว

เรียกใช้การบำรุงรักษาเมื่อต้องการ:

```bash
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce
```

การบำรุงรักษาจะเก็บตัวชี้บทสนทนาภายนอกที่คงทน เช่น เซสชันกลุ่มและเซสชันแชตที่จำกัดขอบเขตตามเธรด แต่รายการรันไทม์สังเคราะห์ (cron, hooks, heartbeat, ACP, เอเจนต์ย่อย) ยังสามารถถูกลบได้เมื่อเกินอายุ จำนวน หรืองบประมาณดิสก์ที่กำหนด การรัน cron แบบแยกใช้การควบคุม `cron.sessionRetention` แยกต่างหาก โดยไม่ขึ้นกับระยะเวลาการเก็บรักษาของเซสชันตรวจสอบการรันโมเดล

การเขียนปกติของ Gateway จะไหลผ่านตัวเข้าถึงเซสชัน ซึ่งจัดลำดับการแก้ไข SQLite ต่อเอเจนต์ผ่านเส้นทางตัวเขียนรันไทม์ โค้ดรันไทม์ควรใช้ตัวช่วยของตัวเข้าถึงใน `src/config/sessions/session-accessor.ts` เป็นหลัก ส่วนตัวช่วย `sessions.json` แบบเดิมเป็นเครื่องมือสำหรับการย้ายข้อมูลและการบำรุงรักษาแบบออฟไลน์ เมื่อเข้าถึง Gateway ได้ `openclaw sessions cleanup` และ `openclaw agents delete` ที่ไม่ใช่การทดลองทำงานจะมอบหมายการแก้ไขที่เก็บให้ Gateway เพื่อให้การล้างข้อมูลเข้าร่วมคิวตัวเขียนเดียวกัน ส่วน `--store <path>` เป็นเส้นทางซ่อมแซมแบบออฟไลน์ที่ชัดเจนสำหรับที่เก็บแบบเดิมที่เลือกและจะทำงานในเครื่องเสมอ (เช่นเดียวกับ `--dry-run`) การล้างข้อมูล `maxEntries` จะแบ่งเป็นชุดสำหรับที่เก็บขนาดระดับโปรดักชัน ดังนั้นที่เก็บอาจเกินขีดจำกัดที่กำหนดชั่วครู่ก่อนที่การล้างข้อมูลเมื่อถึงค่าสูงสุดครั้งถัดไปจะเขียนใหม่ให้ลดลง การอ่านจะไม่ตัดแต่งหรือจำกัดรายการระหว่างการเริ่มต้น Gateway การดำเนินการดังกล่าวทำได้เฉพาะการเขียนหรือ `openclaw sessions cleanup --enforce` เท่านั้น โดยอย่างหลังจะบังคับใช้ขีดจำกัดทันที และตัดแต่งอาร์ติแฟกต์บันทึกบทสนทนา จุดตรวจสอบ และวิถีการทำงานแบบเดิมที่เก่าและไม่มีการอ้างอิง แม้ไม่ได้กำหนดงบประมาณดิสก์ไว้

OpenClaw จะไม่สร้างข้อมูลสำรองหมุนเวียน `sessions.json.bak.*` โดยอัตโนมัติระหว่างการเขียนของ Gateway อีกต่อไป สคีมาปัจจุบันปฏิเสธคีย์ `session.maintenance.rotateBytes` แบบเดิม และ `openclaw doctor --fix` จะลบคีย์ดังกล่าวออกจากการกำหนดค่ารุ่นเก่า

การแก้ไขบันทึกบทสนทนาใช้คิวการเขียนเซสชันสำหรับเป้าหมายบันทึกบทสนทนา SQLite:

การล็อกการเขียนเซสชันใช้ค่าเริ่มต้นแบบคงที่สำหรับโปรดักชัน ตัวแปรสภาพแวดล้อม
`OPENCLAW_SESSION_WRITE_LOCK_*` ที่เกี่ยวข้องยังคงพร้อมใช้งานสำหรับ
การวินิจฉัยระดับกระบวนการและการแทนที่ในกรณีฉุกเฉิน

### การดาวน์เกรดหลังเปลี่ยนมาใช้ SQLite

คืนค่าอาร์ติแฟกต์บันทึกบทสนทนาแบบเดิมที่เก็บถาวรก่อนเรียกใช้ OpenClaw
รุ่นเก่าที่ใช้ไฟล์เป็นที่เก็บ:

```bash
openclaw doctor --session-sqlite restore --session-sqlite-all-agents
```

การย้ายข้อมูลจะคงไฟล์ `sessions.json` แบบเดิมไว้เพื่อการสนับสนุนและ
การย้อนกลับ แต่ไฟล์ JSONL บันทึกบทสนทนาที่ใช้งานอยู่ซึ่งนำเข้า SQLite แล้วจะถูก
เปลี่ยนชื่อไปไว้ใน `session-sqlite-import-archive/` รันไทม์รุ่นเก่าที่ใช้ไฟล์เป็นที่เก็บจะติดตาม
พาธ `sessionFile` ใน `sessions.json` จึงต้องคืนค่าอาร์ติแฟกต์เหล่านั้น
ก่อนเริ่มต้น การคืนค่าใช้ไฟล์รายการการย้ายข้อมูล ย้ายเฉพาะอาร์ติแฟกต์ที่เก็บถาวร
ซึ่งมีการบันทึกไว้และพาธเดิมหายไป และคงฐานข้อมูล SQLite ไว้
สำหรับการกู้คืนไปข้างหน้า

เซสชันที่สร้างหลังเปลี่ยนมาใช้ SQLite จะอยู่ใน SQLite เท่านั้นและจะไม่ปรากฏต่อ
รันไทม์รุ่นเก่าที่ใช้ไฟล์เป็นที่เก็บ หากอัปเกรดอีกครั้งหลังดาวน์เกรด ให้เรียกใช้ลำดับ
การตรวจสอบและการยืนยันของ Doctor อีกครั้ง เพื่อให้ OpenClaw สามารถตรวจสอบ
อาร์ติแฟกต์แบบเดิมที่คืนค่าแล้วก่อนนำเข้า

## เซสชัน Cron และบันทึกการรัน

การรัน cron แบบแยกจะสร้างรายการเซสชัน/บันทึกบทสนทนาของตนเองพร้อมระยะเวลาการเก็บรักษาเฉพาะ:

- `cron.sessionRetention` (ค่าเริ่มต้น `"24h"`) จะตัดแต่งเซสชันการรัน cron แบบแยกที่เก่าออกจากที่เก็บ; `false` ปิดใช้งาน
- ประวัติการรันจะเก็บแถวสถานะสิ้นสุดล่าสุด 2000 แถวต่องาน cron แถวที่สูญหายยังคงมีช่วงเวลาล้างข้อมูล 24 ชั่วโมง

เมื่อ cron บังคับสร้างเซสชันการรันแบบแยกใหม่ ระบบจะล้างข้อมูลรายการเซสชัน `cron:<jobId>` ก่อนหน้าก่อนเขียนแถวใหม่ โดยจะนำค่ากำหนดที่ปลอดภัยติดไปด้วย (การตั้งค่าการคิด/เร็ว/ละเอียด/การให้เหตุผล ป้ายกำกับ ชื่อที่แสดง) และการแทนที่โมเดล/การยืนยันตัวตนที่ผู้ใช้เลือกอย่างชัดเจน แต่จะตัดบริบทบทสนทนาแวดล้อมออก (การกำหนดเส้นทางช่องทาง/กลุ่ม นโยบายการส่ง/คิว การยกระดับ สิ่งที่มา การผูกกับรันไทม์ ACP) เพื่อให้การรันแบบแยกครั้งใหม่ไม่สามารถสืบทอดสิทธิ์การส่งหรือรันไทม์ที่ล้าสมัยจากการรันครั้งเก่า

## คีย์เซสชัน (`sessionKey`)

`sessionKey` ระบุว่าคุณอยู่ในบักเก็ตบทสนทนาใด (การกำหนดเส้นทาง + การแยก) กฎมาตรฐาน: [/concepts/session](/th/concepts/session)

| รูปแบบ                      | ตัวอย่าง                                                     |
| ---------------------------- | ----------------------------------------------------------- |
| แชตหลัก/โดยตรง (ต่อเอเจนต์) | `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>` (เว้นแต่ถูกแทนที่)                           |

## ID เซสชัน (`sessionId`)

`sessionKey` แต่ละรายการชี้ไปยัง `sessionId` ปัจจุบัน (ข้อมูลประจำตัวบันทึกบทสนทนา SQLite ที่ใช้ดำเนินบทสนทนาต่อ) ตรรกะการตัดสินใจอยู่ใน `initSessionState()` ภายใน `src/auto-reply/reply/session.ts`

- **รีเซ็ต** (`/new`, `/reset`) สร้าง `sessionId` ใหม่สำหรับ `sessionKey` นั้น
- **ไม่มีการรีเซ็ตอัตโนมัติ** เป็นค่าเริ่มต้น โดย `sessionId` ปัจจุบันจะดำเนินต่อไป ขณะที่ Compaction ควบคุมบริบทของโมเดลที่ใช้งานอยู่ให้อยู่ภายในขอบเขต
- **รีเซ็ตรายวัน** (`session.reset.mode: "daily"`) สร้าง `sessionId` ใหม่เมื่อมีข้อความถัดไปหลังพ้นขอบเขตชั่วโมงท้องถิ่นที่กำหนดค่าไว้ (`session.reset.atHour`, ค่าเริ่มต้น `4`)
- **การหมดอายุเมื่อไม่มีการใช้งาน** (`session.reset.mode: "idle"` ร่วมกับ `session.reset.idleMinutes` หรือ `session.idleMinutes` แบบเดิม) สร้าง `sessionId` ใหม่เมื่อมีข้อความเข้ามาหลังพ้นช่วงเวลาที่ไม่มีการใช้งาน หากกำหนดค่าทั้งรายวันและเมื่อไม่มีการใช้งาน เงื่อนไขใดหมดอายุก่อนจะมีผล
- **การกลับมาทำงานต่อเมื่อ Control UI เชื่อมต่อใหม่** จะคงเซสชันที่มองเห็นอยู่ในขณะนั้นไว้สำหรับการส่งหนึ่งครั้งหลังเชื่อมต่อใหม่ เมื่อ Gateway ได้รับ `sessionId` ที่ตรงกันจากไคลเอนต์ UI ของผู้ปฏิบัติงาน นี่เป็นสัญญาณแบบใช้ครั้งเดียว การส่งข้อมูลเก่าตามปกติยังคงสร้าง `sessionId` ใหม่
- **เหตุการณ์ระบบ** (Heartbeat, การปลุกโดย Cron, การแจ้งเตือน exec, งานบันทึกสถานะของ Gateway) อาจเปลี่ยนแปลงแถวเซสชัน แต่จะไม่ยืดอายุความใหม่ของการรีเซ็ตรายวัน/เมื่อไม่มีการใช้งาน เมื่อเปลี่ยนผ่านการรีเซ็ต ระบบจะทิ้งประกาศเหตุการณ์ระบบที่อยู่ในคิวของเซสชันก่อนหน้า ก่อนสร้างพรอมต์ใหม่
- **นโยบายการ fork จากพาเรนต์** ใช้สาขาที่ใช้งานอยู่ของ OpenClaw เมื่อสร้างเธรดหรือ fork ของเอเจนต์ย่อย หากสาขานั้นมีขนาดใหญ่เกินไป (เกินขีดจำกัดภายในคงที่ ซึ่งปัจจุบันคือ 100K โทเค็น) OpenClaw จะเริ่มลูกด้วยบริบทแยกต่างหาก แทนที่จะล้มเหลวหรือสืบทอดประวัติที่ใช้งานไม่ได้ การกำหนดขนาดเป็นไปโดยอัตโนมัติและไม่สามารถกำหนดค่าได้ โดย `session.parentForkMaxTokens` แบบเดิมจะถูกลบออกโดย `openclaw doctor --fix`
- **การ fork โดยผู้ปฏิบัติงาน**: `sessions.create { parentSessionKey, fork: true }` สร้างเซสชันใหม่ที่ทรานสคริปต์แตกแขนงจากสถานะปัจจุบันของพาเรนต์ (ใช้กลไก fork เดียวกับการสร้างเอเจนต์ย่อย รวมถึงขีดจำกัดขนาดข้างต้น) ระบบจะปฏิเสธการ fork ขณะที่พาเรนต์มีการรันที่ใช้งานอยู่ สืบทอดการเลือกโมเดลของพาเรนต์ เว้นแต่จะส่งค่าเข้ามาอย่างชัดเจน และทำเครื่องหมาย `forkedFromParent` ของลูกพร้อมตัวนับโทเค็นใหม่

## สคีมาของที่เก็บเซสชัน

ที่เก็บรันไทม์เก็บค่า `SessionEntry` ไว้ใน SQLite แยกตามเอเจนต์ ชนิดของค่าคือ `SessionEntry` ใน `src/config/sessions.ts` ฟิลด์สำคัญ (ไม่ใช่รายการทั้งหมด):

- `sessionId`: ID ทรานสคริปต์ปัจจุบันที่ใช้ระบุแถวทรานสคริปต์ใน SQLite
- `sessionStartedAt`: เวลาประทับเริ่มต้นของ `sessionId` ปัจจุบัน ซึ่งใช้ตรวจสอบความใหม่ของการรีเซ็ตรายวัน แถวแบบเดิมอาจอนุมานค่านี้จากส่วนหัวเซสชัน JSONL
- `lastInteractionAt`: เวลาประทับของการโต้ตอบจริงล่าสุดจากผู้ใช้/ช่องทาง ซึ่งใช้ตรวจสอบความใหม่ของการรีเซ็ตเมื่อไม่มีการใช้งาน เพื่อไม่ให้เหตุการณ์ Heartbeat, Cron และ exec คงเซสชันไว้ แถวแบบเดิมที่ไม่มีฟิลด์นี้จะใช้เวลาเริ่มต้นเซสชันที่กู้คืนมาแทน
- `updatedAt`: เวลาประทับของการเปลี่ยนแปลงแถวในที่เก็บครั้งล่าสุด ใช้สำหรับการแสดงรายการ/ตัดทิ้ง/บันทึกสถานะ ไม่ใช่แหล่งอ้างอิงความใหม่ของการรีเซ็ตรายวัน/เมื่อไม่มีการใช้งาน
- `archivedAt`: เวลาประทับการเก็บถาวรที่ไม่บังคับ เซสชันที่เก็บถาวรจะยังอยู่ในที่เก็บพร้อมทรานสคริปต์ครบถ้วน และไม่รวมอยู่ในการแสดงรายการที่ใช้งานอยู่ตามปกติ
- `pinnedAt`: เวลาประทับการปักหมุดที่ไม่บังคับ เซสชันที่ใช้งานอยู่และถูกปักหมุดจะเรียงอยู่ก่อนเซสชันที่ไม่ถูกปักหมุด การเก็บเซสชันถาวรจะล้างการปักหมุด
- การทำงานร่วมกันกับเธรด Codex: ทั้งสองฟิลด์ใช้รูปแบบการจัดการเธรดของ Codex โดยค่าบูลีน `archived`/`pinned` บนสายสื่อสารจะถูกอนุมานจากเวลาประทับและประทับค่าโดยเซิร์ฟเวอร์เสมอ ซึ่งตรงกับความหมายของ `threads.archived_at` ใน Codex และการซีเรียลไลซ์แบบ camelCase เวลาประทับของ OpenClaw ใช้มิลลิวินาทีตั้งแต่ epoch ส่วน Codex ใช้วินาทีตั้งแต่ epoch ดังนั้นบริดจ์จึงแปลงค่าที่รอยต่อ Plugin `codex` ขณะนี้ Codex ยังไม่มี API สำหรับการปักหมุด (มีเพียง `thread/archive`/`thread/unarchive`) สถานะที่ปักหมุดจึงยังคงอยู่ฝั่ง OpenClaw จนกว่าจะมี API ดังกล่าว ซึ่งเมื่อมีแล้ว รูปแบบที่สอดคล้องกันจะช่วยให้เซสชันที่เชื่อมโยงสามารถส่งสถานะการปักหมุดไปกลับได้โดยอัตโนมัติ
- การควบคุมดูแลของ Codex จะแสดงเฉพาะเธรดเนทีฟที่ไม่ได้เก็บถาวรเท่านั้น เธรด `idle` หรือ `notLoaded` ภายใน Gateway ซึ่งไม่ทราบสถานะกิจกรรม จะเก็บถาวรผ่าน `thread/archive` แบบเนทีฟได้ก็ต่อเมื่อผู้ปฏิบัติงานยืนยันอย่างชัดเจนว่าไม่มีกระบวนการ Codex อื่นเป็นเจ้าของ Plugin จะอ่านสถานะภายในกระบวนการใหม่ก่อน จากนั้นเธรดจะหายไปจากแค็ตตาล็อก การอ่านดังกล่าวไม่สามารถพิสูจน์ได้ว่ากระบวนการ App Server อื่นไม่ได้ใช้งานเธรดอยู่ OpenClaw ปฏิเสธการเก็บแถวที่ใช้งานอยู่และแถวข้อผิดพลาดเป็นถาวร และยังไม่รองรับการเก็บถาวรผ่าน Node ที่จับคู่จนกว่าบริดจ์ของ Node จะควบคุมวงจรชีวิตเธรดแบบสตรีมทั้งหมดได้ การยกเลิกการเก็บถาวรในไคลเอนต์ Codex แบบเนทีฟทำให้เธรดมีสิทธิ์ปรากฏขึ้นอีกครั้ง
- `lastReadAt` / `markedUnreadAt`: เวลาประทับสถานะการอ่านที่ประทับโดยเซิร์ฟเวอร์ผ่าน `sessions.patch { unread }` โดย `unread: false` บันทึกการอ่าน (ตั้งค่า `lastReadAt` และล้าง `markedUnreadAt`) ส่วน `unread: true` ทำเครื่องหมายเซสชันว่าไม่ได้อ่านจนกว่าจะมีการอ่านครั้งถัดไป แถวเซสชันแสดงค่าบูลีน `unread` ที่อนุมานได้ ได้แก่ ถูกทำเครื่องหมายว่าไม่ได้อ่านอย่างชัดเจน หรือถูกอ่านก่อนกิจกรรมล่าสุด เซสชันที่ไม่เคยถูกทำเครื่องหมายว่าอ่านแล้วจะยังคงเป็น `unread: false` เพื่อไม่ให้การติดตั้งเดิมแสดงสถานะใหม่ขึ้นมาเมื่ออัปเกรด
- `lastActivityAt`: เวลาประทับของการรันเอเจนต์ที่เสร็จสมบูรณ์ล่าสุดซึ่งนับเป็นกิจกรรมที่ควรทำให้เกิดสถานะยังไม่ได้อ่าน (การรันจากผู้ใช้ ช่องทาง และ Cron) เทิร์นของ Heartbeat และเหตุการณ์ภายใน รวมถึงแพตช์เมทาดาทา จะไม่อัปเดตค่านี้ และ `updatedAt` ไม่ใช่สัญญาณกิจกรรม
- `sessionFile`: ตัวทำเครื่องหมายแบบเดิมที่คงไว้เพื่อความเข้ากันได้ของการย้ายข้อมูล/การเก็บถาวร รันไทม์ที่ใช้งานอยู่ใช้ข้อมูลระบุตัวตนของ SQLite
- `chatType`: `direct | group | room`
- `provider`, `subject`, `room`, `space`, `displayName`: เมทาดาทาป้ายกำกับกลุ่ม/ช่องทาง
- ตัวสลับ: `thinkingLevel`, `verboseLevel`, `reasoningLevel`, `elevatedLevel`, `sendPolicy` (การแทนที่ค่าระดับเซสชัน)
- การเลือกโมเดล: `providerOverride`, `modelOverride`, `authProfileOverride`
- ตัวนับโทเค็น (ตามความพยายาม/ขึ้นอยู่กับผู้ให้บริการ): `inputTokens`, `outputTokens`, `totalTokens`, `contextTokens`
- `compactionCount`: จำนวนครั้งที่การ Compaction อัตโนมัติเสร็จสมบูรณ์สำหรับคีย์เซสชันนี้
- `memoryFlushAt` / `memoryFlushCompactionCount`: เวลาประทับและจำนวนครั้งของ Compaction ในการฟลัชหน่วยความจำก่อน Compaction ครั้งล่าสุด

Gateway เป็นแหล่งอ้างอิงหลัก โดยอาจเขียนรายการใหม่หรือเติมข้อมูลรายการกลับคืนขณะที่เซสชัน
ทำงานอยู่ สำหรับการติดตั้งแบบเดิมที่ใช้ไฟล์เป็นที่เก็บ ให้ย้ายข้อมูลด้วย
`openclaw doctor --session-sqlite import --session-sqlite-all-agents` แทนการ
แก้ไข `sessions.json` แล้วคาดหวังให้รันไทม์อ่านไฟล์นั้นต่อไป

## โครงสร้างเหตุการณ์ของทรานสคริปต์

ทรานสคริปต์ได้รับการจัดการโดยตัวเข้าถึงเซสชันของ OpenClaw และเปิดให้โค้ดรันไทม์ใช้งานผ่านตัวช่วยที่อิงข้อมูลระบุตัวตน สตรีมเหตุการณ์เป็นแบบเพิ่มต่อท้ายเท่านั้น:

- รายการแรก: ส่วนหัวเซสชัน - `type: "session"`, `id`, `cwd`, `timestamp`, และ `parentSession` ซึ่งไม่บังคับ
- จากนั้น: รายการที่มี `id` + `parentId` (โครงสร้างต้นไม้)

ชนิดรายการที่สำคัญ:

- `message`: ข้อความจากผู้ใช้/ผู้ช่วย/toolResult
- `custom_message`: ข้อความที่ส่วนขยายแทรกเข้ามาซึ่ง _เข้าสู่_ บริบทของโมเดล (แสดงผลใน TUI เมื่อเป็น `display: true` และซ่อนทั้งหมดเมื่อเป็น `display: false`)
- `custom`: สถานะส่วนขยายที่ _ไม่เข้าสู่_ บริบทของโมเดล (สำหรับคงสถานะส่วนขยายไว้ระหว่างการโหลดใหม่)
- `compaction`: สรุป Compaction ที่บันทึกถาวรพร้อม `firstKeptEntryId` และ `tokensBefore`
- `branch_summary`: สรุปที่บันทึกถาวรเมื่อไปยังสาขาหนึ่งของต้นไม้

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

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

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

1. **หน้าต่างบริบทของโมเดล**: ขีดจำกัดตายตัวต่อโมเดล (โทเค็นที่โมเดลมองเห็นได้) มาจากแค็ตตาล็อกโมเดลและสามารถแทนที่ผ่านการกำหนดค่าได้
2. **ตัวนับในที่เก็บเซสชัน**: สถิติสะสมที่เขียนลงในแถวเซสชัน (ใช้สำหรับ `/status` และแดชบอร์ด) `contextTokens` เป็นค่าประมาณ/ค่ารายงานของรันไทม์ อย่าถือว่าเป็นการรับประกันอย่างเคร่งครัด

ข้อมูลเพิ่มเติมเกี่ยวกับขีดจำกัด: [/reference/token-use](/th/reference/token-use)

## Compaction คืออะไร

Compaction สรุปบทสนทนาเก่าเป็นรายการ `compaction` ที่บันทึกถาวรในทรานสคริปต์ และคงข้อความล่าสุดไว้ครบถ้วน หลัง Compaction เทิร์นในอนาคตจะเห็นสรุป Compaction พร้อมข้อความหลัง `firstKeptEntryId` Compaction เป็นแบบ **ถาวร** ต่างจากการตัดเซสชัน โปรดดู [/concepts/session-pruning](/th/concepts/session-pruning)

Compaction แบบฝังใน OpenClaw จะสืบทอดระดับการคิดของเซสชันตามค่าเริ่มต้น ตั้งค่า `agents.defaults.compaction.thinkingLevel` เพื่อใช้ระดับแยกต่างหากสำหรับการเรียกสรุป โดยรันไทม์จะจำกัดค่าให้เหมาะกับโมเดล Compaction หรือโมเดลสำรองแต่ละรายการ เซิร์ฟเวอร์แอป Codex แบบเนทีฟเป็นผู้ควบคุมคำขอ compact และไม่สามารถรับการแทนที่ระดับการคิดเฉพาะ Compaction ได้ ดังนั้น OpenClaw จะแสดงคำเตือนและปล่อยให้ Codex จัดการการตั้งค่านั้น

การแทรกส่วน AGENTS.md กลับเข้าไปหลัง Compaction ต้องเลือกเปิดใช้ผ่าน `agents.defaults.compaction.postCompactionSections` เมื่อไม่ได้ตั้งค่าหรือเป็น `[]` OpenClaw จะไม่ต่อท้ายข้อความตัดตอนจาก AGENTS.md เพิ่มจากสรุป Compaction

### ขอบเขตส่วนย่อยและการจับคู่เครื่องมือ

เมื่อแบ่งทรานสคริปต์ยาวออกเป็นส่วนย่อยสำหรับ Compaction OpenClaw จะรักษาการจับคู่การเรียกเครื่องมือของผู้ช่วยกับรายการ `toolResult` ที่ตรงกัน:

- หากการแบ่งตามสัดส่วนโทเค็นจะตกอยู่ระหว่างการเรียกเครื่องมือกับผลลัพธ์ OpenClaw จะเลื่อนขอบเขตไปยังข้อความเรียกเครื่องมือของผู้ช่วยแทนการแยกคู่ออกจากกัน
- หากบล็อกผลลัพธ์เครื่องมือท้ายสุดจะทำให้ส่วนย่อยเกินเป้าหมาย OpenClaw จะคงบล็อกเครื่องมือที่รอดำเนินการนั้นไว้ และรักษาส่วนท้ายที่ยังไม่ได้สรุปให้ครบถ้วน
- บล็อกการเรียกเครื่องมือที่ถูกยกเลิก/เกิดข้อผิดพลาดจะไม่ทำให้การแบ่งที่รอดำเนินการค้างอยู่

## การเกิด Compaction อัตโนมัติ

มีทริกเกอร์สองรายการในเอเจนต์ OpenClaw แบบฝัง:

1. **การกู้คืนจากการเกินขีดจำกัด**: โมเดลส่งคืนข้อผิดพลาดบริบทเกินขีดจำกัด (`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` และรูปแบบอื่นที่ขึ้นอยู่กับผู้ให้บริการ) ให้ทำ Compaction แล้วลองใหม่ เมื่อผู้ให้บริการรายงานจำนวนโทเค็นที่พยายามใช้ OpenClaw จะส่งต่อจำนวนที่ตรวจพบดังกล่าวไปยัง Compaction สำหรับการกู้คืนจากการเกินขีดจำกัด หากผู้ให้บริการยืนยันว่าเกินขีดจำกัดแต่ไม่เปิดเผยจำนวนที่แยกวิเคราะห์ได้ OpenClaw จะส่งจำนวนสังเคราะห์ที่เกินงบประมาณเพียงเล็กน้อยไปยังกลไก Compaction และการวินิจฉัย หากการกู้คืนจากการเกินขีดจำกัดยังคงล้มเหลว OpenClaw จะแสดงคำแนะนำอย่างชัดเจนและคงการแมปเซสชันปัจจุบันไว้ แทนการเปลี่ยนไปใช้ ID เซสชันใหม่โดยไม่แจ้ง ให้ลองส่งข้อความอีกครั้ง เรียกใช้ `/compact` หรือเรียกใช้ `/new`
2. **การบำรุงรักษาตามเกณฑ์**: หลังเทิร์นสำเร็จ เมื่อบริบทปัจจุบันเกินขนาดหน้าต่างของโมเดลลบด้วยพื้นที่สำรองในตัวของ OpenClaw สำหรับพรอมต์และเอาต์พุตถัดไปของโมเดล

มีกลไกป้องกันเพิ่มเติมอีกสองรายการที่ทำงานนอกเหนือจากทริกเกอร์สองรายการนี้:

- **Compaction ภายในเครื่องก่อนเริ่ม**: ตั้งค่า `agents.defaults.compaction.maxActiveTranscriptBytes` (เป็นไบต์หรือสตริง เช่น `"20mb"`) เพื่อเรียกใช้ Compaction ภายในเครื่องก่อนเปิดการทำงานรอบถัดไป เมื่อทรานสคริปต์ที่ใช้งานอยู่มีขนาดถึงค่าดังกล่าว นี่เป็นกลไกควบคุมขนาดเพื่อลดต้นทุนการเปิดซ้ำภายในเครื่อง ไม่ใช่การเก็บถาวรแบบดิบ โดย Compaction เชิงความหมายตามปกติยังคงทำงาน และต้องใช้ `truncateAfterCompaction` เพื่อให้ข้อมูลสรุปที่ผ่าน Compaction กลายเป็นทรานสคริปต์ตัวสืบทอดใหม่
- **การตรวจสอบล่วงหน้าระหว่างเทิร์น**: ตั้งค่า `agents.defaults.compaction.midTurnPrecheck.enabled: true` (ค่าเริ่มต้น `false`) เพื่อเพิ่มกลไกป้องกันลูปเครื่องมือ หลังผนวกผลลัพธ์ของเครื่องมือและก่อนเรียกโมเดลครั้งถัดไป OpenClaw จะประเมินแรงกดดันต่อพรอมต์โดยใช้ตรรกะงบประมาณก่อนเริ่มแบบเดียวกับที่ใช้เมื่อเริ่มเทิร์น หากบริบทไม่พอดีอีกต่อไป กลไกป้องกันจะไม่ทำ Compaction ภายในขั้นตอนนั้น แต่จะส่งสัญญาณการตรวจสอบล่วงหน้าระหว่างเทิร์นแบบมีโครงสร้าง หยุดการส่งพรอมต์ปัจจุบัน และให้ลูปการทำงานชั้นนอกใช้เส้นทางการกู้คืนที่มีอยู่ (ตัดผลลัพธ์เครื่องมือที่มีขนาดใหญ่เกินไปเมื่อเพียงพอ หรือเรียกใช้โหมด Compaction ที่กำหนดค่าไว้แล้วลองใหม่) ใช้ได้กับโหมด Compaction ทั้ง `default` และ `safeguard` รวมถึง Compaction เพื่อป้องกันที่อาศัยผู้ให้บริการ โดยทำงานเป็นอิสระจาก `maxActiveTranscriptBytes`: กลไกป้องกันขนาดไบต์ทำงานก่อนเปิดเทิร์น ส่วนการตรวจสอบล่วงหน้าระหว่างเทิร์นทำงานภายหลัง หลังผนวกผลลัพธ์เครื่องมือใหม่แล้ว

## การตั้งค่า Compaction

```json5
{
  agents: {
    defaults: {
      compaction: {
        enabled: true,
        keepRecentTokens: 20000,
      },
    },
  },
}
```

OpenClaw บังคับใช้พื้นที่สำรองในตัวสำหรับการทำงานแบบฝังตัว และจำกัดพื้นที่ดังกล่าวตามหน้าต่างบริบทของโมเดลที่ใช้งานอยู่ เพื่อไม่ให้ใช้พื้นที่งบประมาณพรอมต์ทั้งหมด วิธีนี้ช่วยป้องกันไม่ให้โมเดลภายในเครื่องที่มีบริบทขนาดเล็กเข้าสู่ Compaction ตั้งแต่โทเค็นแรก พร้อมคงพื้นที่เผื่อเพียงพอสำหรับงานดูแลหลายเทิร์น เช่น การเขียนหน่วยความจำลงดิสก์

การเรียก `/compact` ด้วยตนเองจะใช้ค่า `agents.defaults.compaction.keepRecentTokens` ที่ระบุไว้อย่างชัดเจน และคงจุดตัดส่วนท้ายล่าสุดของรันไทม์ไว้ หากไม่ได้ระบุงบประมาณการเก็บรักษาอย่างชัดเจน Compaction ด้วยตนเองจะเป็นจุดตรวจสอบแบบตายตัว และบริบทที่สร้างใหม่จะเริ่มจากข้อมูลสรุปใหม่

เมื่อเปิดใช้งาน `truncateAfterCompaction` OpenClaw จะหมุนเวียนทรานสคริปต์ที่ใช้งานอยู่ไปยังตัวสืบทอดที่ผ่าน Compaction หลังทำ Compaction การดำเนินการจุดตรวจสอบสำหรับการแตกแขนง/กู้คืนจะใช้ตัวสืบทอดที่ผ่าน Compaction ดังกล่าว ส่วนไฟล์จุดตรวจสอบเดิมก่อนทำ Compaction จะยังคงอ่านได้ขณะที่มีการอ้างอิงอยู่

## ผู้ให้บริการ Compaction ที่เปลี่ยนได้

Plugin ลงทะเบียนผู้ให้บริการ Compaction ผ่าน `registerCompactionProvider()` บน API ของ Plugin เมื่อกำหนด `agents.defaults.compaction.provider` เป็นรหัสผู้ให้บริการที่ลงทะเบียนไว้ ส่วนขยายเพื่อป้องกันจะมอบหมายการสรุปให้ผู้ให้บริการนั้นแทนไปป์ไลน์ `summarizeInStages` ในตัว

- `provider`: รหัสของ Plugin ผู้ให้บริการ Compaction ที่ลงทะเบียนไว้ ไม่ต้องตั้งค่าเพื่อใช้การสรุปด้วย LLM เริ่มต้น การตั้งค่า `provider` จะบังคับใช้ `mode: "safeguard"`
- ผู้ให้บริการจะได้รับคำสั่ง Compaction และนโยบายการรักษาตัวระบุเช่นเดียวกับเส้นทางในตัว และกลไกป้องกันจะยังคงรักษาบริบทส่วนท้ายของเทิร์นล่าสุดและเทิร์นที่ถูกแบ่งไว้หลังได้รับผลลัพธ์จากผู้ให้บริการ
- การสรุปเพื่อป้องกันในตัวจะกลั่นข้อมูลสรุปก่อนหน้าใหม่ร่วมกับข้อความใหม่ แทนการเก็บข้อมูลสรุปก่อนหน้าทั้งหมดไว้แบบคำต่อคำ
- โหมดป้องกันจะเปิดใช้การตรวจสอบคุณภาพข้อมูลสรุปโดยค่าเริ่มต้น ตั้งค่า `qualityGuard.enabled: false` เพื่อข้ามพฤติกรรมการลองใหม่เมื่อผลลัพธ์มีรูปแบบไม่ถูกต้อง
- หากผู้ให้บริการล้มเหลวหรือส่งคืนผลลัพธ์ว่าง OpenClaw จะย้อนกลับไปใช้การสรุปด้วย LLM ในตัวโดยอัตโนมัติ สัญญาณยกเลิก/หมดเวลาที่ผู้เรียกสั่งอย่างชัดเจนจะถูกส่งต่อ ไม่ถูกกลืนทิ้ง เพื่อให้การยกเลิกได้รับการเคารพเสมอ

แหล่งที่มา: `src/plugins/compaction-provider.ts`, `src/agents/agent-hooks/compaction-safeguard.ts`

## ส่วนที่ผู้ใช้มองเห็น

- `/status` ในเซสชันแชตใดก็ได้
- `openclaw status` (CLI)
- `openclaw sessions` / `openclaw sessions --json`
- บันทึกของ Gateway (`pnpm gateway:watch` หรือ `openclaw logs --follow`): `embedded run auto-compaction start` + `complete`
- โหมดรายละเอียด: `🧹 Auto-compaction complete` พร้อมจำนวนครั้งของ Compaction

## งานดูแลแบบเงียบ (`NO_REPLY`)

OpenClaw รองรับเทิร์นแบบ "เงียบ" สำหรับงานเบื้องหลังที่ไม่ควรให้ผู้ใช้เห็นผลลัพธ์ระหว่างดำเนินการ

- ผู้ช่วยจะเริ่มผลลัพธ์ด้วยโทเค็นเงียบที่ตรงกันทุกประการ `NO_REPLY` / `no_reply` เพื่อหมายความว่า "ไม่ต้องส่งการตอบกลับให้ผู้ใช้" OpenClaw จะตัด/ระงับข้อความนี้ในชั้นการส่งมอบ
- การระงับโทเค็นเงียบที่ตรงกันทุกประการไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่: ทั้ง `NO_REPLY` และ `no_reply` จะถือว่าเข้าเงื่อนไขเมื่อเพย์โหลดทั้งหมดมีเพียงโทเค็นเงียบ
- ตั้งแต่ `2026.1.10` เป็นต้นมา OpenClaw ยังระงับการสตรีมฉบับร่าง/สถานะกำลังพิมพ์เมื่อส่วนข้อมูลบางส่วนเริ่มด้วย `NO_REPLY` เพื่อไม่ให้การดำเนินการแบบเงียบเปิดเผยผลลัพธ์บางส่วนระหว่างเทิร์น
- กลไกนี้มีไว้สำหรับเทิร์นเบื้องหลัง/ไม่มีการส่งมอบอย่างแท้จริงเท่านั้น ไม่ใช่ทางลัดสำหรับคำขอทั่วไปของผู้ใช้ที่ต้องดำเนินการ

## การเขียนหน่วยความจำลงดิสก์ก่อน Compaction

ก่อนเกิด Compaction อัตโนมัติ OpenClaw สามารถเรียกใช้เทิร์นแบบเอเจนต์ที่เงียบเพื่อเขียนสถานะถาวรลงดิสก์ (เช่น `memory/YYYY-MM-DD.md` ในพื้นที่ทำงานของเอเจนต์) เพื่อไม่ให้ Compaction ลบบริบทสำคัญ โดยจะตรวจสอบการใช้บริบทของเซสชัน และเมื่อเกินเกณฑ์อ่อนที่ต่ำกว่าเกณฑ์ Compaction จะส่งคำสั่ง "เขียนหน่วยความจำตอนนี้" แบบเงียบโดยใช้โทเค็นเงียบที่ตรงกันทุกประการ `NO_REPLY` / `no_reply` เพื่อไม่ให้ผู้ใช้เห็นสิ่งใด

การกำหนดค่า (`agents.defaults.compaction.memoryFlush`) โปรดดูข้อมูลอ้างอิงฉบับเต็มที่ [/gateway/config-agents](/th/gateway/config-agents#agentsdefaultscompaction):

| คีย์                         | ค่าเริ่มต้น          | หมายเหตุ                                                                                                                                  |
| --------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`                   | `true`           |                                                                                                                                        |
| `model`                     | ไม่ได้ตั้งค่า            | การแทนที่ผู้ให้บริการ/โมเดลที่ตรงกันทุกประการสำหรับเทิร์นการเขียนลงดิสก์เท่านั้น เช่น `ollama/qwen3:8b`                                                   |
| `softThresholdTokens`       | `4000`           | ระยะห่างต่ำกว่าเกณฑ์ Compaction ที่เรียกใช้การเขียนลงดิสก์                                                                               |
| `forceFlushTranscriptBytes` | ไม่ได้ตั้งค่า (ปิดใช้งาน) | บังคับเขียนลงดิสก์เมื่อไฟล์ทรานสคริปต์มีขนาดถึงจำนวนไบต์นี้ (หรือสตริง เช่น `"2mb"`) แม้ว่าตัวนับโทเค็นจะไม่เป็นปัจจุบัน โดย `0` จะปิดใช้งาน |
| `prompt`                    | ในตัว         | ข้อความผู้ใช้สำหรับเทิร์นการเขียนลงดิสก์                                                                                                        |
| `systemPrompt`              | ในตัว         | พรอมต์ระบบเพิ่มเติมที่ผนวกสำหรับเทิร์นการเขียนลงดิสก์                                                                                        |

หมายเหตุ:

- พรอมต์/พรอมต์ระบบเริ่มต้นมีคำแนะนำ `NO_REPLY` เพื่อระงับการส่งมอบ
- เมื่อตั้งค่า `model` เทิร์นการเขียนลงดิสก์จะใช้โมเดลดังกล่าวโดยไม่สืบทอดสายการย้อนกลับของเซสชันที่ใช้งานอยู่ เพื่อให้งานดูแลเฉพาะภายในเครื่องไม่ย้อนกลับไปใช้โมเดลสนทนาแบบชำระเงินโดยไม่แจ้งเมื่อเกิดความล้มเหลว
- การเขียนลงดิสก์จะทำงานหนึ่งครั้งต่อรอบ Compaction (ติดตามในแถวเซสชัน)
- การเขียนลงดิสก์จะทำงานเฉพาะเซสชัน OpenClaw แบบฝังตัว ส่วนแบ็กเอนด์ CLI และเทิร์น Heartbeat จะข้ามขั้นตอนนี้
- ระบบจะข้ามการเขียนลงดิสก์เมื่อพื้นที่ทำงานของเซสชันเป็นแบบอ่านอย่างเดียว (`workspaceAccess: "ro"` หรือ `"none"`)
- ดูรูปแบบไฟล์ในพื้นที่ทำงานและรูปแบบการเขียนได้ที่ [หน่วยความจำ](/th/concepts/memory)

OpenClaw เปิดเผยฮุก `session_before_compact` ใน API ของส่วนขยาย แต่ตรรกะการเขียนลงดิสก์ข้างต้นอยู่ฝั่ง Gateway (`src/auto-reply/reply/memory-flush.ts`, `src/auto-reply/reply/agent-runner-memory.ts`) ไม่ได้อยู่ในฮุกดังกล่าว

## รายการตรวจสอบการแก้ไขปัญหา

- **คีย์เซสชันไม่ถูกต้องหรือไม่?** เริ่มจาก [/concepts/session](/th/concepts/session) และยืนยัน `sessionKey` ใน `/status`
- **ข้อมูลในที่เก็บไม่ตรงกับทรานสคริปต์หรือไม่?** ยืนยันโฮสต์ Gateway และพาธของที่เก็บจาก `openclaw status`
- **Compaction เกิดถี่เกินไปหรือไม่?** ตรวจสอบหน้าต่างบริบทของโมเดล (หากเล็กเกินไปจะบังคับให้ทำ Compaction บ่อยครั้ง) และผลลัพธ์เครื่องมือที่มีขนาดใหญ่เกินไป (ปรับแต่งการตัดแต่งเซสชัน)
- **ทุกพรอมต์ดูเหมือนจะล้นในโมเดลภายในเครื่องขนาดเล็กหรือไม่?** ยืนยันว่าผู้ให้บริการรายงานหน้าต่างบริบทของโมเดลที่ถูกต้อง OpenClaw จะจำกัดพื้นที่สำรองที่มีผลได้ก็ต่อเมื่อทราบขนาดหน้าต่างดังกล่าว
- **เทิร์นแบบเงียบมีข้อมูลรั่วไหลหรือไม่?** ยืนยันว่าคำตอบเริ่มต้นด้วยโทเค็นเงียบที่ตรงกันทุกประการ `NO_REPLY` (ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่) และกำลังใช้บิลด์ที่มีการแก้ไขการระงับการสตรีม (`2026.1.10`+)

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

- [การจัดการเซสชัน](/th/concepts/session)
- [การตัดแต่งเซสชัน](/th/concepts/session-pruning)
- [กลไกบริบท](/th/concepts/context-engine)
- [ข้อมูลอ้างอิงการกำหนดค่าเอเจนต์](/th/gateway/config-agents)
