Technical reference
세션 관리 심층 분석
OpenClaw는 다음 영역 전반에서 세션을 종단 간 관리합니다.
- 세션 라우팅(수신 메시지가
sessionKey에 매핑되는 방식) - 세션 저장소(
sessions.json)와 저장소가 추적하는 항목 - 트랜스크립트 지속성(
*.jsonl)과 그 구조 - 트랜스크립트 위생(실행 전 공급자별 수정)
- 컨텍스트 제한(컨텍스트 윈도우와 추적 토큰)
- Compaction(수동 및 자동 Compaction)과 Compaction 전 작업을 연결할 위치
- 무음 하우스키핑(사용자에게 보이는 출력을 생성하지 않아야 하는 메모리 쓰기)
먼저 더 높은 수준의 개요를 보려면 다음부터 시작하세요.
진실의 원천: Gateway
OpenClaw는 세션 상태를 소유하는 단일 Gateway 프로세스를 중심으로 설계되었습니다.
- UI(macOS 앱, 웹 Control UI, TUI)는 세션 목록과 토큰 수를 Gateway에 조회해야 합니다.
- 원격 모드에서는 세션 파일이 원격 호스트에 있습니다. 따라서 "로컬 Mac 파일 확인"은 Gateway가 사용하는 내용을 반영하지 않습니다.
두 가지 지속성 계층
OpenClaw는 세션을 두 계층에 지속합니다.
-
세션 저장소(
sessions.json)- 키/값 맵:
sessionKey -> SessionEntry - 작고, 변경 가능하며, 편집해도 안전함(또는 항목 삭제 가능)
- 세션 메타데이터(현재 세션 ID, 마지막 활동, 토글, 토큰 카운터 등)를 추적함
- 키/값 맵:
-
트랜스크립트(
<sessionId>.jsonl)- 트리 구조를 가진 추가 전용 트랜스크립트(항목에는
id+parentId가 있음) - 실제 대화 + 도구 호출 + Compaction 요약을 저장함
- 이후 턴의 모델 컨텍스트를 다시 빌드하는 데 사용됨
- 활성 트랜스크립트가 체크포인트 크기 상한을 초과하면 큰 Compaction 전 디버그 체크포인트는 건너뛰어, 두 번째 거대한
.checkpoint.*.jsonl복사본을 만들지 않습니다.
- 트리 구조를 가진 추가 전용 트랜스크립트(항목에는
Gateway 히스토리 리더는 표면이 임의의 과거 접근을 명시적으로 필요로 하지 않는 한 전체 트랜스크립트를 메모리에 올리지 않아야 합니다. 첫 페이지 히스토리, 임베드된 채팅 히스토리, 재시작 복구, 토큰/사용량 확인은 제한된 꼬리 읽기를 사용합니다. 전체 트랜스크립트 스캔은 비동기 트랜스크립트 인덱스를 거치며, 이 인덱스는 파일 경로와 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를 통해 해석합니다.
저장소 유지관리 및 디스크 제어
세션 지속성에는 sessions.json, 트랜스크립트 아티팩트, trajectory 사이드카를 위한 자동 유지관리 제어(session.maintenance)가 있습니다.
mode:warn(기본값) 또는enforcepruneAfter: 오래된 항목 나이 기준(기본값30d)maxEntries:sessions.json의 항목 상한(기본값500)resetArchiveRetention:*.reset.<timestamp>트랜스크립트 아카이브 보존 기간(기본값:pruneAfter와 동일,false는 정리 비활성화)maxDiskBytes: 선택적 세션 디렉터리 예산highWaterBytes: 정리 후 선택적 목표값(기본값은maxDiskBytes의80%)
일반 Gateway 쓰기는 프로세스 내 변경을 직렬화하는 저장소별 세션 writer를 거치며, 런타임 파일 락을 잡지 않습니다. 핫 경로 패치 헬퍼는 writer 슬롯을 보유하는 동안 검증된 변경 가능 캐시를 빌리므로, 큰 sessions.json 파일을 모든 메타데이터 업데이트마다 복제하거나 다시 읽지 않습니다. 런타임 코드는 updateSessionStore(...) 또는 updateSessionStoreEntry(...)를 선호해야 합니다. 직접 전체 저장소 저장은 호환성 및 오프라인 유지관리 도구입니다. Gateway에 연결할 수 있을 때, 비 dry-run openclaw sessions cleanup 및 openclaw agents delete는 저장소 변경을 Gateway에 위임하여 정리가 동일한 writer 큐에 합류하도록 합니다. --store <path>는 직접 파일 유지관리를 위한 명시적 오프라인 복구 경로입니다. maxEntries 정리는 운영 규모 상한에서도 여전히 일괄 처리되므로, 다음 high-water 정리가 다시 줄여 쓸 때까지 저장소가 구성된 상한을 잠시 초과할 수 있습니다. 세션 저장소 읽기는 Gateway 시작 중에 항목을 정리하거나 상한을 적용하지 않습니다. 정리에는 쓰기 또는 openclaw sessions cleanup --enforce를 사용하세요. openclaw sessions cleanup --enforce는 디스크 예산이 구성되지 않았더라도 구성된 상한을 즉시 적용하고 오래된 참조되지 않은 트랜스크립트, 체크포인트, trajectory 아티팩트를 정리합니다.
유지관리는 그룹 세션 및 스레드 범위 채팅 세션 같은 내구성 있는 외부 대화 포인터를 유지하지만, cron, 훅, Heartbeat, ACP, 하위 에이전트용 합성 런타임 항목은 구성된 나이, 개수 또는 디스크 예산을 초과하면 제거될 수 있습니다.
OpenClaw는 더 이상 Gateway 쓰기 중 자동 sessions.json.bak.* 회전 백업을 만들지 않습니다. 레거시 session.maintenance.rotateBytes 키는 무시되며 openclaw doctor --fix가 이전 구성에서 이를 제거합니다.
트랜스크립트 변경은 트랜스크립트 파일의 세션 쓰기 락을 사용합니다. 락 획득은 바쁜 세션 오류를 표시하기 전에 최대 session.writeLock.acquireTimeoutMs까지 기다립니다. 기본값은 60000 ms입니다. 느린 머신에서 합법적인 준비, 정리, Compaction 또는 트랜스크립트 미러 작업이 더 오래 경합할 때만 이 값을 높이세요. 오래된 락 감지와 최대 보유 경고는 별도 정책으로 유지됩니다.
디스크 예산 정리(mode: "enforce")의 적용 순서:
- 가장 오래된 아카이브, 고아 트랜스크립트 또는 고아 trajectory 아티팩트를 먼저 제거합니다.
- 그래도 목표를 초과하면 가장 오래된 세션 항목과 해당 트랜스크립트/trajectory 파일을 제거합니다.
- 사용량이
highWaterBytes이하가 될 때까지 계속합니다.
mode: "warn"에서 OpenClaw는 잠재적 제거를 보고하지만 저장소/파일을 변경하지 않습니다.
필요할 때 유지관리를 실행하세요.
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce
Cron 세션 및 실행 로그
격리된 cron 실행도 세션 항목/트랜스크립트를 만들며, 전용 보존 제어가 있습니다.
cron.sessionRetention(기본값24h)은 세션 저장소에서 오래된 격리 cron 실행 세션을 정리합니다(false는 비활성화).cron.runLog.maxBytes+cron.runLog.keepLines는~/.openclaw/cron/runs/<jobId>.jsonl파일을 정리합니다(기본값:2_000_000바이트 및2000줄).
cron이 새 격리 실행 세션을 강제로 만들 때, 새 행을 쓰기 전에 이전 cron:<jobId> 세션 항목을 정리합니다. thinking/fast/verbose 설정, 라벨, 명시적으로 사용자가 선택한 모델/인증 재정의 같은 안전한 기본 설정은 유지합니다. 채널/그룹 라우팅, 전송 또는 큐 정책, 권한 상승, 출처, ACP 런타임 바인딩 같은 주변 대화 컨텍스트는 제거하여 새로운 격리 실행이 오래된 실행의 낡은 전달 또는 런타임 권한을 상속하지 못하게 합니다.
세션 키(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에 문서화되어 있습니다.
세션 ID(sessionId)
각 sessionKey는 현재 sessionId(대화를 이어가는 트랜스크립트 파일)를 가리킵니다.
경험칙:
- 재설정(
/new,/reset)은 해당sessionKey에 새sessionId를 만듭니다. - 일일 재설정(기본값: Gateway 호스트의 로컬 시간 오전 4:00)은 재설정 경계를 지난 뒤 다음 메시지에서 새
sessionId를 만듭니다. - 유휴 만료(
session.reset.idleMinutes또는 레거시session.idleMinutes)는 유휴 윈도우 이후 메시지가 도착하면 새sessionId를 만듭니다. 일일 재설정과 유휴 만료가 모두 구성된 경우 먼저 만료되는 쪽이 적용됩니다. - 시스템 이벤트(Heartbeat, cron 깨우기, exec 알림, gateway 장부 처리)는 세션 행을 변경할 수 있지만 일일/유휴 재설정 freshness를 연장하지 않습니다. 재설정 롤오버는 새 프롬프트를 빌드하기 전에 이전 세션에 대해 대기 중이던 시스템 이벤트 알림을 버립니다.
- 부모 포크 정책은 스레드 또는 하위 에이전트 포크를 만들 때 Pi의 활성 브랜치를 사용합니다. 해당 브랜치가 너무 크면 OpenClaw는 실패하거나 사용할 수 없는 히스토리를 상속하는 대신 격리된 컨텍스트로 자식을 시작합니다. 크기 정책은 자동입니다. 레거시
session.parentForkMaxTokens구성은openclaw doctor --fix로 제거됩니다.
구현 세부 정보: 결정은 src/auto-reply/reply/session.ts의 initSessionState()에서 이루어집니다.
세션 저장소 스키마(sessions.json)
저장소의 값 타입은 src/config/sessions.ts의 SessionEntry입니다.
주요 필드(전체 목록 아님):
sessionId: 현재 트랜스크립트 ID(sessionFile이 설정되지 않은 한 파일명은 여기에서 파생됨)sessionStartedAt: 현재sessionId의 시작 타임스탬프. 일일 재설정 freshness는 이를 사용합니다. 레거시 행은 JSONL 세션 헤더에서 이를 파생할 수 있습니다.lastInteractionAt: 마지막 실제 사용자/채널 상호작용 타임스탬프. 유휴 재설정 freshness는 이를 사용하므로 Heartbeat, cron, exec 이벤트가 세션을 계속 살아 있게 하지 않습니다. 이 필드가 없는 레거시 행은 복구된 세션 시작 시간으로 폴백하여 유휴 freshness에 사용합니다.updatedAt: 마지막 저장소 행 변경 타임스탬프이며, 목록 표시, 정리, 장부 처리에 사용됩니다. 일일/유휴 재설정 freshness의 기준은 아닙니다.sessionFile: 선택적 명시적 트랜스크립트 경로 재정의chatType:direct | group | room(UI 및 전송 정책에 도움)provider,subject,room,space,displayName: 그룹/채널 라벨링용 메타데이터- 토글:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(세션별 재정의)
- 모델 선택:
providerOverride,modelOverride,authProfileOverride
- 토큰 카운터(최선 노력 / 공급자 의존):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: 이 세션 키에 대해 자동 Compaction이 완료된 횟수memoryFlushAt: 마지막 Compaction 전 메모리 플러시의 타임스탬프memoryFlushCompactionCount: 마지막 플러시가 실행되었을 때의 Compaction 횟수
저장소는 편집해도 안전하지만 Gateway가 기준입니다. 세션이 실행되면서 항목을 다시 쓰거나 재수화할 수 있습니다.
트랜스크립트 구조(*.jsonl)
트랜스크립트는 @mariozechner/pi-coding-agent의 SessionManager가 관리합니다.
파일은 JSONL입니다.
- 첫 줄: 세션 헤더(
type: "session",id,cwd,timestamp, 선택적parentSession포함) - 이후:
id+parentId가 있는 세션 항목(트리)
주요 항목 타입:
message: 사용자/어시스턴트/toolResult 메시지custom_message: 모델 컨텍스트에 들어가는 extension 주입 메시지(UI에서는 숨길 수 있음)custom: 모델 컨텍스트에 들어가지 않는 extension 상태compaction:firstKeptEntryId및tokensBefore가 있는 지속된 Compaction 요약branch_summary: 트리 브랜치를 탐색할 때 지속된 요약
OpenClaw는 의도적으로 트랜스크립트를 "수정"하지 않습니다. Gateway는 SessionManager를 사용해 이를 읽고 씁니다.
컨텍스트 윈도우와 추적 토큰
중요한 개념은 두 가지입니다.
- 모델 컨텍스트 윈도우: 모델별 하드 상한(모델이 볼 수 있는 토큰)
- 세션 저장소 카운터:
sessions.json에 기록되는 롤링 통계(/status 및 대시보드에 사용)
제한을 조정하는 경우:
- 컨텍스트 윈도우는 모델 카탈로그에서 가져옵니다(구성을 통해 재정의 가능).
- 저장소의
contextTokens는 런타임 추정/보고 값입니다. 이를 엄격한 보장으로 취급하지 마세요.
자세한 내용은 /token-use를 참조하세요.
Compaction: 정의
Compaction은 이전 대화를 트랜스크립트의 지속된 compaction 항목으로 요약하고 최근 메시지는 그대로 유지합니다.
Compaction 이후 이후 턴은 다음을 봅니다.
- Compaction 요약
firstKeptEntryId이후의 메시지
Compaction은 영구적입니다(세션 가지치기와 다름). /concepts/session-pruning을 참고하세요.
Compaction 청크 경계와 도구 페어링
OpenClaw가 긴 transcript를 Compaction 청크로 나눌 때, assistant 도구 호출을
일치하는 toolResult 항목과 쌍으로 유지합니다.
- 토큰 비율 분할 지점이 도구 호출과 그 결과 사이에 걸리면, OpenClaw는 쌍을 분리하지 않고 경계를 assistant 도구 호출 메시지로 옮깁니다.
- 뒤따르는 도구 결과 블록 때문에 청크가 목표치를 초과하게 될 경우, OpenClaw는 해당 대기 중인 도구 블록을 보존하고 요약되지 않은 꼬리 부분을 그대로 유지합니다.
- 중단된/오류 도구 호출 블록은 대기 중인 분할을 열린 상태로 유지하지 않습니다.
자동 Compaction이 발생하는 시점(Pi 런타임)
임베디드 Pi 에이전트에서 자동 Compaction은 두 경우에 트리거됩니다.
- 오버플로 복구: 모델이 context 오버플로 오류를 반환하는 경우
(
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및 유사한 provider 형식의 변형) → compact → 재시도. - 임계값 유지 관리: 성공적인 turn 이후, 다음 조건일 때:
contextTokens > contextWindow - reserveTokens
여기서:
contextWindow는 모델의 context window입니다.reserveTokens는 프롬프트 + 다음 모델 출력을 위해 예약된 여유 공간입니다.
이는 Pi 런타임 시맨틱입니다(OpenClaw는 이벤트를 소비하지만, 언제 compact할지는 Pi가 결정합니다).
OpenClaw는 agents.defaults.compaction.maxActiveTranscriptBytes가 설정되어 있고
active transcript 파일이 해당 크기에 도달하면 다음 run을 열기 전에 preflight 로컬 Compaction도
트리거할 수 있습니다. 이는 원시 보관용이 아니라 로컬 재열기 비용을 위한 파일 크기 가드입니다.
OpenClaw는 여전히 일반 semantic Compaction을 실행하며,
compacted 요약이 새 successor transcript가 될 수 있도록 truncateAfterCompaction이 필요합니다.
임베디드 Pi 실행에서 agents.defaults.compaction.midTurnPrecheck.enabled: true는
옵트인 도구 루프 가드를 추가합니다. 도구 결과가 추가된 뒤, 다음 모델 호출 전에
OpenClaw는 turn 시작 시 사용하는 것과 동일한 preflight budget 로직으로 프롬프트 압력을 추정합니다.
context가 더 이상 맞지 않으면, 이 가드는 Pi의 transformContext hook 내부에서 compact하지 않습니다.
대신 구조화된 mid-turn precheck 신호를 발생시키고, 현재 프롬프트 제출을 중단하며,
외부 run loop가 기존 복구 경로를 사용하게 합니다. 충분한 경우 과도하게 큰 도구 결과를 자르거나,
설정된 Compaction 모드를 트리거한 뒤 재시도합니다. 이 옵션은 기본적으로 비활성화되어 있으며
provider-backed safeguard Compaction을 포함해 default와 safeguard Compaction 모드 모두에서 동작합니다.
이는 maxActiveTranscriptBytes와 독립적입니다. byte 크기 가드는 turn이 열리기 전에 실행되고,
mid-turn precheck는 새 도구 결과가 추가된 뒤 임베디드 Pi 도구 루프에서 나중에 실행됩니다.
Compaction 설정(reserveTokens, keepRecentTokens)
Pi의 Compaction 설정은 Pi 설정에 있습니다.
{
compaction: {
enabled: true,
reserveTokens: 16384,
keepRecentTokens: 20000,
},
}
OpenClaw는 임베디드 실행에 대해 안전 하한도 강제합니다.
compaction.reserveTokens < reserveTokensFloor이면 OpenClaw가 올립니다.- 기본 하한은
20000토큰입니다. - 하한을 비활성화하려면
agents.defaults.compaction.reserveTokensFloor: 0을 설정하세요. - 이미 더 높으면 OpenClaw는 그대로 둡니다.
- 수동
/compact는 명시적인agents.defaults.compaction.keepRecentTokens를 존중하고 Pi의 recent-tail 절단 지점을 유지합니다. 명시적인 유지 budget이 없으면 수동 Compaction은 계속 hard checkpoint로 남으며, 재구성된 context는 새 요약에서 시작합니다. - 새 도구 결과 이후와 다음 모델 호출 전에 선택적 도구 루프 precheck를 실행하려면
agents.defaults.compaction.midTurnPrecheck.enabled: true를 설정하세요. 이는 trigger일 뿐이며, 요약 생성은 여전히 설정된 Compaction 경로를 사용합니다. 이는 turn 시작 시 active transcript byte 크기 가드인maxActiveTranscriptBytes와 독립적입니다. - active transcript가 커졌을 때 turn 전에 로컬 Compaction을 실행하려면
agents.defaults.compaction.maxActiveTranscriptBytes를 byte 값 또는"20mb"같은 문자열로 설정하세요. 이 가드는truncateAfterCompaction도 활성화된 경우에만 활성화됩니다. 비활성화하려면 설정하지 않거나0으로 설정하세요. agents.defaults.compaction.truncateAfterCompaction이 활성화되면, OpenClaw는 Compaction 이후 active transcript를 compacted successor JSONL로 교체합니다. 이전 전체 transcript는 제자리에서 다시 쓰이지 않고, 보관된 상태로 남아 Compaction checkpoint에서 링크됩니다.
이유: Compaction이 불가피해지기 전에 여러 turn에 걸친 "housekeeping"(예: 메모리 쓰기)을 위한 충분한 여유 공간을 남기기 위해서입니다.
구현: src/agents/pi-settings.ts의 ensurePiCompactionReserveTokens()
(src/agents/pi-embedded-runner.ts에서 호출됨).
플러그형 Compaction provider
Plugin은 Plugin API의 registerCompactionProvider()를 통해 Compaction provider를 등록할 수 있습니다. agents.defaults.compaction.provider가 등록된 provider id로 설정되면, safeguard Plugin은 내장 summarizeInStages pipeline 대신 해당 provider에 요약을 위임합니다.
provider: 등록된 Compaction provider Plugin의 id입니다. 기본 LLM 요약을 사용하려면 설정하지 마세요.provider를 설정하면mode: "safeguard"가 강제됩니다.- Provider는 내장 경로와 동일한 Compaction 지침과 식별자 보존 정책을 받습니다.
- Safeguard는 provider 출력 이후에도 recent-turn 및 split-turn suffix context를 보존합니다.
- 내장 safeguard 요약은 전체 이전 요약을 그대로 보존하지 않고, 이전 요약을 새 메시지와 함께 다시 정제합니다.
- Safeguard 모드는 기본적으로 요약 품질 감사를 활성화합니다. malformed output 시 재시도 동작을 건너뛰려면
qualityGuard.enabled: false를 설정하세요. - Provider가 실패하거나 빈 결과를 반환하면 OpenClaw는 자동으로 내장 LLM 요약으로 fallback합니다.
- 중단/timeout 신호는 호출자 취소를 존중하기 위해 다시 throw됩니다(삼켜지지 않음).
소스: src/plugins/compaction-provider.ts, src/agents/pi-hooks/compaction-safeguard.ts.
사용자에게 보이는 표면
다음을 통해 Compaction 및 세션 상태를 관찰할 수 있습니다.
/status(모든 chat 세션)openclaw status(CLI)openclaw sessions/sessions --json- Verbose 모드:
🧹 Auto-compaction complete+ Compaction 횟수
조용한 housekeeping(NO_REPLY)
OpenClaw는 사용자가 중간 출력을 보지 않아야 하는 백그라운드 작업을 위해 "silent" turn을 지원합니다.
규칙:
- assistant가 출력 시작 부분에 정확한 silent token
NO_REPLY/no_reply를 사용하여 "사용자에게 답장을 전달하지 말라"는 의미를 표시합니다. - OpenClaw는 delivery layer에서 이를 제거/억제합니다.
- 정확한 silent-token 억제는 대소문자를 구분하지 않으므로, 전체 payload가 silent token만인 경우
NO_REPLY와no_reply가 모두 해당됩니다. - 이는 진짜 백그라운드/비전달 turn 전용입니다. 일반적인 실행 가능한 사용자 요청을 위한 shortcut이 아닙니다.
2026.1.10부터 OpenClaw는 partial chunk가 NO_REPLY로 시작할 때 draft/typing streaming도
억제하므로, silent 작업이 turn 중간에 partial output을 누출하지 않습니다.
Pre-Compaction "memory flush"(구현됨)
목표: 자동 Compaction이 발생하기 전에, durable state를 disk에 쓰는 조용한 agentic turn을 실행합니다
(예: agent workspace의 memory/YYYY-MM-DD.md). 그러면 Compaction이 중요한 context를 지울 수 없습니다.
OpenClaw는 pre-threshold flush 접근 방식을 사용합니다.
- 세션 context 사용량을 모니터링합니다.
- Pi의 Compaction 임계값보다 낮은 "soft threshold"를 넘으면, agent에 조용한 "write memory now" 지시를 실행합니다.
- 사용자가 아무것도 보지 않도록 정확한 silent token
NO_REPLY/no_reply를 사용합니다.
Config(agents.defaults.compaction.memoryFlush):
enabled(기본값:true)model(flush turn에 대한 선택적 exact provider/model override, 예:ollama/qwen3:8b)softThresholdTokens(기본값:4000)prompt(flush turn용 사용자 메시지)systemPrompt(flush turn에 추가되는 extra system prompt)
참고:
- 기본 prompt/system prompt에는 delivery를 억제하기 위한
NO_REPLY힌트가 포함됩니다. model이 설정되면 flush turn은 active session fallback chain을 상속하지 않고 해당 모델을 사용하므로, 로컬 전용 housekeeping이 유료 대화 모델로 조용히 fallback하지 않습니다.- Flush는 Compaction cycle마다 한 번 실행됩니다(
sessions.json에서 추적). - Flush는 임베디드 Pi 세션에서만 실행됩니다(CLI backend는 건너뜀).
- 세션 workspace가 read-only(
workspaceAccess: "ro"또는"none")이면 flush를 건너뜁니다. - workspace 파일 layout과 쓰기 패턴은 Memory를 참고하세요.
Pi도 extension API에 session_before_compact hook을 노출하지만, OpenClaw의
flush 로직은 현재 Gateway 쪽에 있습니다.
문제 해결 checklist
- 세션 key가 잘못되었나요? /concepts/session에서 시작해
/status의sessionKey를 확인하세요. - Store와 transcript가 일치하지 않나요?
openclaw status에서 Gateway host와 store path를 확인하세요. - Compaction spam인가요? 다음을 확인하세요.
- 모델 context window(너무 작음)
- Compaction 설정(모델 window에 비해
reserveTokens가 너무 높으면 Compaction이 더 일찍 발생할 수 있음) - 도구 결과 bloat: 세션 가지치기를 활성화/조정하세요.
- Silent turn이 누출되나요? reply가
NO_REPLY로 시작하는지(대소문자 무관 정확한 token), 그리고 streaming suppression fix가 포함된 build인지 확인하세요.