Session Management & Compaction (Tìm hiểu sâu)
Tài liệu này giải thích cách OpenClaw quản lý session từ đầu đến cuối:
- Session routing (cách message đến được map vào
sessionKey) - Session store (
sessions.json) và những gì nó theo dõi - Transcript persistence (
*.jsonl) và cấu trúc của nó - Transcript hygiene (fixup theo provider trước khi chạy)
- Context limit (context window vs tracked token)
- Compaction (manual + auto-compaction) và nơi hook pre-compaction work
- Silent housekeeping (ví dụ: memory write không hiển thị output cho user)
Nếu các bạn muốn xem tổng quan cấp cao trước, hãy bắt đầu với:
Source of truth: Gateway
OpenClaw được thiết kế xoay quanh một Gateway process duy nhất sở hữu session state.
- Các UI (macOS app, web Control UI, TUI) nên query Gateway để lấy danh sách session và số lượng token.
- Ở remote mode, các file session nằm trên remote host; việc “check file trên Mac local” sẽ không phản ánh những gì Gateway đang dùng.
Hai lớp persistence
OpenClaw lưu trữ session ở hai lớp:
-
Session store (
sessions.json)- Map key/value:
sessionKey -> SessionEntry - Nhỏ gọn, có thể thay đổi, an toàn khi edit (hoặc xóa entry)
- Theo dõi metadata của session (session id hiện tại, hoạt động cuối, toggle, bộ đếm token, v.v.)
- Map key/value:
-
Transcript (
<sessionId>.jsonl)- Transcript append-only với cấu trúc cây (các entry có
id+parentId) - Lưu trữ cuộc hội thoại thực tế + tool call + compaction summary
- Dùng để rebuild model context cho các turn sau
- Transcript append-only với cấu trúc cây (các entry có
Vị trí trên đĩa
Với mỗi agent, trên Gateway host:
- Store:
~/.openclaw/agents/<agentId>/sessions/sessions.json - Transcript:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- Telegram topic session:
.../<sessionId>-topic-<threadId>.jsonl
- Telegram topic session:
OpenClaw resolve các đường dẫn này qua src/config/sessions.ts.
Session key (sessionKey)
sessionKey xác định conversation bucket nào các bạn đang ở (routing + isolation).
Các pattern phổ biến:
- Main/direct chat (mỗi agent):
agent:<agentId>:<mainKey>(mặc địnhmain) - Group:
agent:<agentId>:<channel>:group:<id> - Room/channel (Discord/Slack):
agent:<agentId>:<channel>:channel:<id>hoặc...:room:<id> - Cron:
cron:<job.id> - Webhook:
hook:<uuid>(trừ khi bị override)
Các quy tắc chính thức được ghi tại /concepts/session.
Session id (sessionId)
Mỗi sessionKey trỏ đến một sessionId hiện tại (file transcript tiếp tục cuộc hội thoại).
Quy tắc chung:
- Reset (
/new,/reset) tạosessionIdmới chosessionKeyđó. - Daily reset (mặc định 4:00 SA theo giờ local trên gateway host) tạo
sessionIdmới ở message tiếp theo sau reset boundary. - Idle expiry (
session.reset.idleMinuteshoặc legacysession.idleMinutes) tạosessionIdmới khi message đến sau idle window. Khi cả daily + idle được config, cái nào hết hạn trước thì thắng.
Chi tiết implementation: quyết định xảy ra trong initSessionState() ở src/auto-reply/reply/session.ts.
Schema của Session store (sessions.json)
Value type của store là SessionEntry trong src/config/sessions.ts.
Các trường chính (không đầy đủ):
sessionId: transcript id hiện tại (filename được derive từ cái này trừ khisessionFileđược set)updatedAt: timestamp hoạt động cuốisessionFile: override đường dẫn transcript tùy chọnchatType:direct | group | room(giúp UI và send policy)provider,subject,room,space,displayName: metadata cho group/channel labeling- Toggle:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(override per-session)
- Model selection:
providerOverride,modelOverride,authProfileOverride
- Bộ đếm token (best-effort / phụ thuộc provider):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: số lần auto-compaction hoàn thành cho session key nàymemoryFlushAt: timestamp cho lần memory flush pre-compaction cuốimemoryFlushCompactionCount: compaction count khi flush cuối chạy
Store an toàn để edit, nhưng Gateway là authority: nó có thể rewrite hoặc rehydrate entry khi session chạy.
Cấu trúc Transcript (*.jsonl)
Transcript được quản lý bởi SessionManager của @mariozechner/pi-coding-agent.
File là JSONL:
- Dòng đầu: session header (
type: "session", bao gồmid,cwd,timestamp,parentSessiontùy chọn) - Sau đó: các session entry với
id+parentId(cây)
Các loại entry đáng chú ý:
message: message user/assistant/toolResultcustom_message: message do extension inject có vào model context (có thể ẩn khỏi UI)custom: state của extension không vào model contextcompaction: compaction summary được persist vớifirstKeptEntryIdvàtokensBeforebranch_summary: summary được persist khi navigate tree branch
OpenClaw cố ý không “fix up” transcript; Gateway dùng SessionManager để đọc/ghi chúng.
Context window vs tracked token
Hai khái niệm khác nhau quan trọng:
- Model context window: giới hạn cứng mỗi model (token mà model nhìn thấy)
- Session store counter: thống kê rolling được ghi vào
sessions.json(dùng cho /status và dashboard)
Nếu các bạn đang tune limit:
- Context window đến từ model catalog (và có thể override qua config).
contextTokenstrong store là giá trị ước tính/báo cáo runtime; đừng coi nó như đảm bảo chặt chẽ.
Xem thêm tại /token-use.
Compaction: nó là gì
Compaction tóm tắt cuộc hội thoại cũ thành một entry compaction được persist trong transcript và giữ nguyên các message gần đây.
Sau compaction, các turn sau sẽ thấy:
- Compaction summary
- Message sau
firstKeptEntryId
Compaction là persistent (không giống session pruning). Xem /concepts/session-pruning.
Khi nào auto-compaction xảy ra (Pi runtime)
Trong embedded Pi agent, auto-compaction trigger trong hai trường hợp:
- Overflow recovery: model trả về context overflow error → compact → retry.
- Threshold maintenance: sau một turn thành công, khi:
contextTokens > contextWindow - reserveTokens
Trong đó:
contextWindowlà context window của modelreserveTokenslà headroom dành cho prompt + model output tiếp theo
Đây là ngữ nghĩa Pi runtime (OpenClaw consume event, nhưng Pi quyết định khi nào compact).
Cài đặt Compaction (reserveTokens, keepRecentTokens)
Cài đặt compaction của Pi nằm trong Pi settings:
{
compaction: {
enabled: true,
reserveTokens: 16384,
keepRecentTokens: 20000,
},
}
OpenClaw cũng enforce safety floor cho embedded run:
- Nếu
compaction.reserveTokens < reserveTokensFloor, OpenClaw tăng nó lên. - Floor mặc định là
20000token. - Set
agents.defaults.compaction.reserveTokensFloor: 0để tắt floor. - Nếu nó đã cao hơn, OpenClaw để nguyên.
Tại sao: để lại đủ headroom cho “housekeeping” nhiều turn (như memory write) trước khi compaction trở nên không thể tránh khỏi.
Implementation: ensurePiCompactionReserveTokens() trong src/agents/pi-settings.ts
(được gọi từ src/agents/pi-embedded-runner.ts).
Giao diện user có thể thấy
Các bạn có thể quan sát compaction và session state qua:
/status(trong bất kỳ chat session nào)openclaw status(CLI)openclaw sessions/sessions --json- Verbose mode:
🧹 Auto-compaction complete+ compaction count
Silent housekeeping (NO_REPLY)
OpenClaw hỗ trợ turn “silent” cho background task mà user không nên thấy output trung gian.
Quy ước:
- Assistant bắt đầu output với
NO_REPLYđể chỉ ra “đừng gửi reply cho user”. - OpenClaw strip/suppress cái này ở delivery layer.
Kể từ 2026.1.10, OpenClaw cũng suppress draft/typing streaming khi partial chunk bắt đầu bằng NO_REPLY, nên silent operation không leak partial output giữa turn.
Pre-compaction “memory flush” (đã implement)
Mục tiêu: trước khi auto-compaction xảy ra, chạy một silent agentic turn ghi durable
state vào đĩa (ví dụ: memory/YYYY-MM-DD.md trong agent workspace) để compaction không thể
xóa context quan trọng.
OpenClaw dùng approach pre-threshold flush:
- Monitor session context usage.
- Khi nó vượt qua “soft threshold” (dưới compaction threshold của Pi), chạy silent directive “write memory now” cho agent.
- Dùng
NO_REPLYđể user không thấy gì.
Config (agents.defaults.compaction.memoryFlush):
enabled(mặc định:true)softThresholdTokens(mặc định:4000)prompt(user message cho flush turn)systemPrompt(system prompt thêm vào cho flush turn)
Lưu ý:
- Prompt/system prompt mặc định bao gồm hint
NO_REPLYđể suppress delivery. - Flush chạy một lần mỗi compaction cycle (được track trong
sessions.json). - Flush chỉ chạy cho embedded Pi session (CLI backend bỏ qua).
- Flush bị skip khi session workspace là read-only (
workspaceAccess: "ro"hoặc"none"). - Xem Memory cho workspace file layout và write pattern.
Pi cũng expose hook session_before_compact trong extension API, nhưng logic
flush của OpenClaw nằm ở Gateway side hiện tại.
Checklist troubleshooting
- Session key sai? Bắt đầu với /concepts/session và xác nhận
sessionKeytrong/status. - Store vs transcript không khớp? Xác nhận Gateway host và đường dẫn store từ
openclaw status. - Compaction spam? Kiểm tra:
- model context window (quá nhỏ)
- cài đặt compaction (
reserveTokensquá cao cho model window có thể gây compaction sớm hơn) - tool-result bloat: enable/tune session pruning
- Silent turn bị leak? Xác nhận reply bắt đầu bằng
NO_REPLY(token chính xác) và các bạn đang dùng build có streaming suppression fix.