세션 관리 & 컴팩션 (심층 분석)
이 문서는 OpenClaw가 세션을 엔드투엔드로 관리하는 방법을 설명합니다:
- 세션 라우팅 (인바운드 메시지가 sessionKey에 매핑되는 방식)
- 세션 저장소 (sessions.json) 및 추적 내용
- 트랜스크립트 영속성 (*.jsonl) 및 구조
- 트랜스크립트 정리 (프로바이더별 수정)
- 컨텍스트 제한 (컨텍스트 윈도우 vs 추적 토큰)
- 컴팩션 (수동 + 자동 컴팩션) 및 사전 컴팩션 작업 후크
- 사일런트 하우스키핑 (예: 사용자에게 보이지 않는 메모리 쓰기)
상위 수준의 개요를 먼저 보려면:
진실의 원천: Gateway
OpenClaw는 세션 상태를 소유하는 단일 Gateway 프로세스를 중심으로 설계되었습니다.
- UI(macOS 앱, 웹 Control UI, TUI)는 세션 목록 및 토큰 수를 Gateway에서 조회해야 합니다
- 원격 모드에서 세션 파일은 원격 호스트에 있습니다
두 가지 영속성 레이어
세션 저장소 (sessions.json)
- 키/값 맵: sessionKey -> SessionEntry
- 작고 변경 가능하며 편집(또는 항목 삭제) 안전
- 세션 메타데이터 추적 (현재 세션 ID, 마지막 활동, 토글, 토큰 카운터 등)
트랜스크립트 (.jsonl)
- 트리 구조의 추가 전용 트랜스크립트 (항목에 id + parentId 있음)
- 실제 대화 + 도구 호출 + 컴팩션 요약 저장
- 향후 턴의 모델 컨텍스트 재구성에 사용
디스크 위치
에이전트별, Gateway 호스트:
- 저장소: ~/.openclaw/agents/<agent>/sessions/sessions.json
- 트랜스크립트: ~/.openclaw/agents/<agent>/sessions/<sessionId>.jsonl
세션 키 (sessionKey)
sessionKey는 어떤 대화 버킷에 있는지 식별합니다 (라우팅 + 격리).
일반적인 패턴:
- 메인/다이렉트 채팅: agent:<agent>:<provider>
- 그룹: agent:<agent>:<provider>:group:<groupId>
- 채널 (Discord/Slack): agent:<agent>:<provider>:channel:<channelId>
- Cron: cron:<jobId>
컴팩션: 개요
컴팩션은 오래된 대화를 트랜스크립트의 영속 컴팩션 항목으로 요약하고 최근 메시지를 유지합니다.
컴팩션 후 향후 턴은 다음을 봅니다:
- 컴팩션 요약
- firstKeptEntryId 이후의 메시지
컴팩션은 영속적입니다 (세션 프루닝과 달리). /concepts/session-pruning 참조.
자동 컴팩션 트리거
- 오버플로 복구: 모델이 컨텍스트 오버플로 오류 반환 → 컴팩트 → 재시도
- 임계값 유지: 성공적인 턴 후, contextTokens > contextWindow - reserveTokens일 때
컴팩션 설정
\{
"compaction": \{
"enabled": true,
"reserveTokens": 16384,
"keepRecentTokens": 20000
\}
\}
OpenClaw는 안전 하한선도 적용합니다: compaction.reserveTokens < 16384이면 16384로 올립니다.
사전 컴팩션 "메모리 플러시"
목표: 자동 컴팩션 전에 사일런트 에이전트 턴을 실행하여 영구 상태를 디스크에 씁니다 (예: memory/YYYY-MM-DD.md).
설정 (agents.defaults.compaction.memoryFlush):
- enabled (기본값: true)
- softThresholdTokens (기본값: 4000)
- prompt (플러시 턴의 사용자 메시지)
- systemPrompt (플러시 턴에 추가되는 시스템 프롬프트)
문제 해결
- 세션 키 오류? /concepts/session에서 시작하여 /status의 sessionKey 확인
- 컴팩션 스팸? 모델 컨텍스트 윈도우(너무 작음), 컴팩션 설정, 도구 결과 비대화 확인
- 사일런트 턴 누출? 응답이 NO_REPLY로 시작하는지 확인