Session 관리
OpenClaw는 agent당 하나의 direct-chat session을 primary로 취급합니다. Direct chat은 agent:<agentId>:<mainKey>(기본값 main)로 축약되고, group/channel chat은 자체 키를 갖습니다. session.mainKey는 존중됩니다.
session.dmScope를 사용하여 direct 메시지가 그룹화되는 방식을 제어하세요:
- main (기본값): 모든 DM이 연속성을 위해 main session을 공유합니다.
- per-peer: channel 간 발신자 id별로 격리합니다.
- per-channel-peer: channel + 발신자별로 격리합니다(다중 사용자 inbox에 권장).
- per-account-channel-peer: account + channel + 발신자별로 격리합니다(다중 계정 inbox에 권장). session.identityLinks를 사용하여 provider 접두사가 붙은 peer id를 canonical identity에 매핑하여 per-peer, per-channel-peer 또는 per-account-channel-peer 사용 시 동일한 사람이 channel 간에 DM session을 공유하도록 합니다.
Gateway가 진실의 원천
모든 session 상태는 gateway가 소유합니다("master" OpenClaw). UI 클라이언트(macOS 앱, WebChat 등)는 로컬 파일을 읽는 대신 session 목록 및 토큰 수를 gateway에 쿼리해야 합니다.
- 원격 모드에서 신경 쓰는 session 스토어는 Mac이 아닌 원격 gateway 호스트에 있습니다.
- UI에 표시되는 토큰 수는 gateway의 store 필드(inputTokens, outputTokens, totalTokens, contextTokens)에서 가져옵니다. 클라이언트는 JSONL transcript를 파싱하여 총계를 "수정"하지 않습니다.
상태가 저장되는 위치
- Gateway 호스트에서:
- Store 파일: ~/.openclaw/agents/<agentId>/sessions/sessions.json (agent별).
- Transcript: ~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl (Telegram topic session은 .../<SessionId>-topic-<threadId>.jsonl 사용).
- Store는 sessionKey -> { sessionId, updatedAt, ... } 맵입니다. 항목 삭제는 안전합니다. 필요 시 재생성됩니다.
- Group 항목에는 UI에서 session을 레이블링하기 위해 displayName, channel, subject, room 및 space가 포함될 수 있습니다.
- Session 항목에는 origin 메타데이터(레이블 + 라우팅 힌트)가 포함되어 UI가 session이 어디에서 왔는지 설명할 수 있습니다.
- OpenClaw는 레거시 Pi/Tau session 폴더를 읽지 않습니다.
Session pruning
OpenClaw는 기본적으로 LLM 호출 직전에 인메모리 컨텍스트에서 오래된 tool 결과를 트리밍합니다. 이것은 JSONL 기록을 다시 작성하지 않습니다. /concepts/session-pruning을 참조하세요.
Pre-compaction 메모리 플러시
Session이 자동 compaction에 가까워지면 OpenClaw는 model에 지속 가능한 노트를 디스크에 작성하도록 상기시키는 침묵 메모리 플러시 턴을 실행할 수 있습니다. 이것은 workspace가 쓰기 가능한 경우에만 실행됩니다. Memory 및 Compaction을 참조하세요.
Transport → session 키 매핑
- Direct chat은 session.dmScope를 따릅니다(기본값 main).
- main: agent:<agentId>:<mainKey> (장치/channel 간 연속성).
- 여러 전화번호 및 channel이 동일한 agent main 키에 매핑될 수 있습니다. 이들은 하나의 대화로 전송되는 transport 역할을 합니다.
- per-peer: agent:<agentId>:dm:<peerId>.
- per-channel-peer: agent:<agentId>:<channel>:dm:<peerId>.
- per-account-channel-peer: agent:<agentId>:<channel>:<accountId>:dm:<peerId> (accountId 기본값은 default).
- session.identityLinks가 provider 접두사가 붙은 peer id(예: telegram:123)와 일치하면 canonical 키가 <peerId>를 대체하여 동일한 사람이 channel 간에 session을 공유합니다.
- main: agent:<agentId>:<mainKey> (장치/channel 간 연속성).
- Group chat은 상태를 격리합니다: agent:<agentId>:<channel>:group:<id> (room/channel은 agent:<agentId>:<channel>:channel:<id> 사용).
- Telegram 포럼 topic은 격리를 위해 group id에 :topic:<threadId>를 추가합니다.
- 레거시 group:<id> 키는 마이그레이션을 위해 여전히 인식됩니다.
- 인바운드 컨텍스트는 여전히 group:<id>를 사용할 수 있습니다. Channel은 Provider에서 추론되고 canonical agent:<agentId>:<channel>:group:<id> 형태로 정규화됩니다.
- 기타 소스:
- Cron 작업: cron:<job.id>
- Webhook: hook:<uuid> (hook에서 명시적으로 설정하지 않은 경우)
- Node 실행: node-<nodeId>
수명 주기
- 재설정 정책: session은 만료될 때까지 재사용되며, 만료는 다음 인바운드 메시지에서 평가됩니다.
- Daily 재설정: 기본값은 gateway 호스트 로컬 시간 오전 4:00입니다. Session은 마지막 업데이트가 가장 최근 daily 재설정 시간보다 이전이면 오래된 것입니다.
- Idle 재설정 (선택사항): idleMinutes는 슬라이딩 idle 윈도우를 추가합니다. Daily 및 idle 재설정이 모두 구성된 경우 먼저 만료되는 것이 새 session을 강제합니다.
- 레거시 idle 전용: session.reset/resetByType config 없이 session.idleMinutes를 설정하면 OpenClaw는 역호환성을 위해 idle 전용 모드로 유지됩니다.
- 유형별 재정의 (선택사항): resetByType을 사용하면 dm, group 및 thread session에 대한 정책을 재정의할 수 있습니다(thread = Slack/Discord 스레드, Telegram topic, connector에서 제공하는 Matrix 스레드).
- Channel별 재정의 (선택사항): resetByChannel은 channel에 대한 재설정 정책을 재정의합니다(해당 channel의 모든 session 유형에 적용되며 reset/resetByType보다 우선).
- 재설정 트리거: 정확한 /new 또는 /reset (plus resetTriggers의 extras)는 새로운 session id를 시작하고 메시지의 나머지를 전달합니다. /new <model>은 model 별칭, provider/model 또는 provider 이름(퍼지 매치)을 허용하여 새 session model을 설정합니다. /new 또는 /reset만 전송되면 OpenClaw는 재설정을 확인하기 위해 짧은 "hello" 인사 턴을 실행합니다.
- 수동 재설정: store에서 특정 키를 삭제하거나 JSONL transcript를 제거합니다. 다음 메시지가 이들을 재생성합니다.
- 격리된 cron 작업은 항상 실행당 새로운 sessionId를 생성합니다(idle 재사용 없음).
Send policy (선택사항)
개별 id를 나열하지 않고 특정 session 유형에 대한 전달을 차단합니다.
{
session: {
sendPolicy: {
rules: [
{ action: "deny", match: { channel: "discord", chatType: "group" } },
{ action: "deny", match: { keyPrefix: "cron:" } }
],
default: "allow"
}
}
}
런타임 재정의 (소유자 전용):
- /send on → 이 session에 대해 허용
- /send off → 이 session에 대해 거부
- /send inherit → 재정의를 지우고 config 규칙 사용 등록되도록 독립 실행형 메시지로 전송하세요.
구성 (선택적 이름 바꾸기 예시)
// ~/.openclaw/openclaw.json
{
session: {
scope: "per-sender", // 그룹 키를 별도로 유지
dmScope: "main", // DM 연속성 (공유 inbox의 경우 per-channel-peer/per-account-channel-peer 설정)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"]
},
reset: {
// 기본값: mode=daily, atHour=4 (gateway 호스트 로컬 시간).
// idleMinutes도 설정하면 먼저 만료되는 것이 우선합니다.
mode: "daily",
atHour: 4,
idleMinutes: 120
},
resetByType: {
thread: { mode: "daily", atHour: 4 },
dm: { mode: "idle", idleMinutes: 240 },
group: { mode: "idle", idleMinutes: 120 }
},
resetByChannel: {
discord: { mode: "idle", idleMinutes: 10080 }
},
resetTriggers: ["/new", "/reset"],
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
mainKey: "main",
}
}
검사
- openclaw status — store 경로 및 최근 session을 표시합니다.
- openclaw sessions --json — 모든 항목을 덤프합니다(--active <minutes>로 필터링).
- openclaw gateway call sessions.list --params '{}' — 실행 중인 gateway에서 session을 가져옵니다(원격 gateway 액세스를 위해 --url/--token 사용).
- 채팅에서 독립 실행형 메시지로 /status를 전송하여 agent가 도달 가능한지, session 컨텍스트가 얼마나 사용되는지, 현재 thinking/verbose 토글 및 WhatsApp web 인증 정보가 마지막으로 새로 고쳐진 시점(재링크 필요성을 발견하는 데 도움)을 확인하세요.
- /context list 또는 /context detail을 전송하여 시스템 프롬프트 및 주입된 workspace 파일에 무엇이 있는지 확인하세요(및 가장 큰 컨텍스트 기여자).
- 독립 실행형 메시지로 /stop을 전송하여 현재 실행을 중단하고, 해당 session에 대한 대기 중인 followup을 지우고, 거기서 생성된 sub-agent 실행을 중지하세요(답장에는 중지 수가 포함됨).
- 독립 실행형 메시지로 /compact (선택적 지침)를 전송하여 오래된 컨텍스트를 요약하고 윈도우 공간을 확보하세요. /concepts/compaction을 참조하세요.
- JSONL transcript를 직접 열어 전체 턴을 검토할 수 있습니다.
팁
- Primary 키를 1:1 트래픽 전용으로 유지하세요. 그룹이 자체 키를 유지하도록 하세요.
- 자동화된 정리 시 다른 곳의 컨텍스트를 유지하기 위해 전체 store가 아닌 개별 키를 삭제하세요.
Session origin 메타데이터
각 session 항목은 origin에 출처(best-effort)를 기록합니다:
- label: 사람이 읽을 수 있는 레이블(대화 레이블 + 그룹 제목/channel에서 해석됨)
- provider: 정규화된 channel id(extension 포함)
- from/to: 인바운드 envelope의 원시 라우팅 id
- accountId: provider 계정 id(다중 계정인 경우)
- threadId: channel이 지원하는 경우 thread/topic id Origin 필드는 direct 메시지, channel 및 그룹에 대해 채워집니다. Connector가 전달 라우팅만 업데이트하는 경우(예: DM main session을 신선하게 유지하기 위해) session이 설명 메타데이터를 유지하도록 인바운드 컨텍스트를 제공해야 합니다. Extension은 인바운드 컨텍스트에서 ConversationLabel, GroupSubject, GroupChannel, GroupSpace 및 SenderName을 전송하고 recordSessionMetaFromInbound를 호출하여(또는 동일한 컨텍스트를 updateLastRoute에 전달하여) 이를 수행할 수 있습니다.