DOCS/journey/research/260317_OpenClaw_컨텍스트_메모리_리서치.md
happybell80 60a892e5ab fix: DOCS 내 0_VALUE 참조를 GitHub URL → 로컬 상대경로로 전환, 02_Governance → 20_Governance 수정 #33 #34
SSOT는 로컬 0_VALUE/. GitHub URL은 복사본 참조로 SSOT 원칙 위반.
02_Governance는 존재하지 않는 구 경로로 전부 깨진 링크.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 14:00:21 +09:00

117 lines
6.2 KiB
Markdown

# OpenClaw 컨텍스트·메모리 리서치
**작성일**: 2026-03-17
**목적**: OpenClaw의 직전 대화·컨텍스트 처리 방식을 조사하고, 로빙 적용 가능성을 검토한다.
**관련 문서**:
- [아이디어: OpenClaw 스타일 컨텍스트·compaction](../ideas/260317_OpenClaw_스타일_컨텍스트_compaction_아이디어.md)
- [writing-principles](../../../../0_VALUE/20_Governance/writing-principles.md)
---
## 1. 사실 (Facts)
### 1.1 OpenClaw 1차 자료
| 항목 | 출처 | 내용 |
|------|------|------|
| Context 정의 | [open-claw.bot/docs/concepts/context](https://open-claw.bot/docs/concepts/context) | "실행 시 모델로 전송되는 모든 데이터". 디스크 Memory와 구분됨. |
| Context 구성요소 | 동일 | Attachments, Tool Calls & Results, **Conversation History**, System Prompt |
| Conversation History | 동일 | "이번 세션에서 주고받은 메시지 기록" |
| Compaction | [open-claw.bot/docs/concepts/compaction](https://open-claw.bot/docs/concepts/compaction) | 토큰 한도 근접 시 **이전 대화를 요약**해 한 블록으로 압축. auto-compaction 기본 활성화. |
| Manual Compaction | 동일 | `/compact Focus on decisions and open questions` — 우선순위 지시 가능 |
| Persistence | 동일 | 요약은 session JSONL에 저장. 재시작 후에도 유지. |
| 3-Layer Memory | [learnopenclaw.com/core-concepts/memory](https://learnopenclaw.com/core-concepts/memory) | Short-term(세션), Medium-term(daily log), Long-term(MEMORY.md) |
| Short-term | 동일 | LLM context window 내. 세션 종료 시 초기화. 자동 유지. |
| Medium-term | 동일 | `session-memory` 훅이 대화 종료 시 **요약** 생성 → 날짜별 daily log 마크다운에 append |
| Long-term | 동일 | MEMORY.md. 사용자 직접 관리. `boot-md` 훅으로 매 대화 시작 시 로드 |
| Hybrid Search | 동일 | 70% vector, 30% BM25. MEMORY 검색 시 사용 |
| Session isolation | [session-management-compaction](https://open-claw.bot/docs/cli/reference/session-management-compaction) | `session.dmScope`: per-channel(공유) vs per-channel-peer(격리) |
| Compaction 설정 | 동일 | `reserveTokens`, `keepRecentTokens` 등 |
### 1.2 로빙 현재 구현
| 항목 | 파일 | 내용 |
|------|------|------|
| 조회 | `app/state/database.py` 115-147행 | `get_recent_conversations(user_id, limit=300, window_hours=24)` |
| DB | `conversation_log` | `message`, `response`, `intent`, `timestamp` |
| 조건 | 동일 | `user_id`(UUID), `timestamp >= cutoff`(24h), `ORDER BY timestamp DESC` |
| 제한 | 동일 | Slack ID(`U`로 시작)면 `[]` 반환 |
| 전달 | `app/router/message_router.py` 320-351행 | `get_user_context()``recent_conversations` |
| 사용처 | `decision_engine.analyze_intent()` | approval, CONTEXT_FOLLOWUP, LLM 폴백 시 `previous_message + message` 결합 |
| 필터 | 동일 331-339행 | 정책 placeholder 응답 제거 |
---
## 2. 해석 (Interpretation)
### 2.1 OpenClaw vs 로빙 차이
| 구분 | OpenClaw | 로빙 |
|------|----------|------|
| 대화 로드 | 세션 단위, 토큰 예산 내 | 24h 내 300개 raw |
| 초과 시 | compaction(요약) | 제한 없음(호출부에서 잘라쓸 가능성) |
| 중장기 | daily log + MEMORY.md | 없음 |
| 세션 | 단일 에이전트, 채널/peer 격리 | 멀티유저, user_id·channel |
| 저장 | JSONL + 마크다운 파일 | PostgreSQL `conversation_log` |
### 2.2 로빙에 compaction이 필요한 이유
- 300개 raw는 수만~수십만 토큰. 대부분 LLM 호출 시 전부 주입 불가.
- 실제로는 handler에서 `recent_conversations[:N]` 등으로 잘라쓸 가능성 있으나, **어디서 몇 개를 쓰는지** 명시적이지 않음.
- "그래", "무슨 말이야?" 오분류: 직전 raw 대화와 결합해 시맨틱/LLM이 잘못된 의도로 분류. **요약된 맥락**이면 노이즈 감소 기대.
### 2.3 적용 시 고려사항
1. **compaction 단위**: user_id·channel별 세션. 로빙은 요청 단위 무상태이므로 "세션" 정의 필요(예: 30분 내 연속 대화).
2. **요약 생성 시점**: 대화 종료 정의 어려움. OpenClaw는 단일 스레드 대화. 로빙은 비동기·멀티채널. → **주기적 배치** 또는 **N회 대화마다** 요약 후 append 가능.
3. **저장소**: daily log는 파일 vs DB. 로빙 인프라가 DB 중심이면 `conversation_summary` 테이블 추가 검토.
4. **MEMORY.md 대응**: user별 `user_memory` 또는 `robeing_memory` 테이블. boot 시 로드.
---
## 3. 미확정 항목 (Unresolved)
- compaction 요약에 사용할 LLM 모델·토큰 예산.
- `session-memory` 훅 트리거: "대화 종료"를 타임아웃(예: 30분 무응답) vs 명시적 `/end` vs 배치.
- 기존 `conversation_log`와 요약 저장소 관계: 대체 vs 병행(원본 유지 + 요약 추가).
- Slack ID → UUID 매핑 없을 때 `recent_conversations``[]`인 문제. OpenClaw는 세션 파일로 해결. 로빙은 Gateway `X-User-Id` 전달 전제.
---
## 4. 코드 경로 (로빙)
```
get_recent_conversations(user_id, limit=300, window_hours=24)
← message_router.get_user_context()
← message_service.route_message()
→ context["recent_conversations"]
→ create_execution_plan(message, context)
→ analyze_intent(message, context)
├ approval: context["recent_conversations"][0].intent
├ CONTEXT_FOLLOWUP: previous_message + message → semantic
└ _llm_intent_fallback: combined → semantic 재시도
```
---
## 5. 1차 자료 링크
- [OpenClaw Context](https://open-claw.bot/docs/concepts/context)
- [OpenClaw Compaction](https://open-claw.bot/docs/concepts/compaction)
- [OpenClaw Session & Compaction](https://open-claw.bot/docs/cli/reference/session-management-compaction)
- [OpenClaw Memory System](https://learnopenclaw.com/core-concepts/memory)
---
## 6. 다음 단계
1. 아이디어 문서 기준으로 플랜 작성(Phase별 작업 단위).
2. compaction 프로토타입: `get_recent_conversations` 대체 또는 래퍼로 "최근 N개 raw + 그 이전은 요약 1블록" 반환.
3. session-memory 훅: `save_conversation` 호출 후 조건 만족 시 요약 생성·저장.
---
**tags**: [research, context, memory, compaction, OpenClaw, robeing]
**상위 원칙**: [writing-principles](../../../../0_VALUE/20_Governance/writing-principles.md)