서문
OpenClaw에서 여러 채팅 플랫폼을 설정한 후, 핵심적인 문제가 뒤따릅니다: 서로 다른 플랫폼, 사용자, 대화 간의 메시지를 어떻게 라우팅하고 격리해야 할까요? 모든 메시지가 뒤섞이면 AI의 응답은 필연적으로 혼란스러워질 것입니다.
OpenClaw은 다중 Agent 라우팅과 세션 격리 메커니즘을 통해 이 문제를 우아하게 해결합니다. 각 Agent는 독립적인 세션 공간을 가지며, 세션은 JSONL 형식으로 영구 저장되고, 트리 구조의 분기와 압축을 지원합니다. 이 글에서는 이 메커니즘의 작동 원리와 설정 방법을 심층적으로 분석합니다.
다중 Agent 라우팅 아키텍처
OpenClaw의 핵심 설계 이념은 "대화별 라우팅"입니다. 여러 플랫폼(Telegram, Discord, Slack 등)을 설정한 후, 시스템은 모든 메시지를 동일한 처리 파이프라인에 넣는 것이 아니라, 각 독립적인 대화에 대해 격리된 세션 컨텍스트를 유지합니다.
사용자A (Telegram DM) ──→ Agent-1 ──→ Session A-001
사용자A (Discord #general) ──→ Agent-2 ──→ Session A-002
사용자B (Telegram DM) ──→ Agent-1 ──→ Session B-001
사용자B (Slack 그룹) ──→ Agent-3 ──→ Session B-002
보시다시피, 동일한 사용자라도 다른 플랫폼에서의 대화는 서로 다른 Agent로 라우팅되며, 완전히 격리된 세션을 가집니다. 이러한 설계는 컨텍스트가 서로 오염되지 않도록 보장합니다.
세션 저장: JSONL과 트리 구조
OpenClaw의 세션 데이터는 JSONL(JSON Lines) 형식으로 저장되며, 각 세션 파일에는 일련의 메시지 기록이 포함됩니다. 저장 경로는 통일된 디렉터리 구조를 따릅니다:
~/.openclaw/agents/<agentId>/sessions/
├── session-a001.jsonl
├── session-a002.jsonl
├── session-b001.jsonl
└── session-b002.jsonl
각 메시지 기록에는 id와 parentId 필드가 포함되어 트리 구조를 형성합니다:
{"id":"msg_001","parentId":null,"role":"user","content":"안녕하세요","timestamp":1710000000}
{"id":"msg_002","parentId":"msg_001","role":"assistant","content":"안녕하세요! 무엇을 도와드릴까요?","timestamp":1710000001}
{"id":"msg_003","parentId":"msg_002","role":"user","content":"Python 코드를 작성해 주세요","timestamp":1710000010}
{"id":"msg_004","parentId":"msg_002","role":"user","content":"오늘 날씨가 어때요","timestamp":1710000015}
위에서 msg_003과 msg_004는 동일한 parentId를 가지고 있으며, 이는 대화가 msg_002 이후 분기되었음을 의미합니다. 트리 구조를 통해 OpenClaw은 단순한 선형 채팅 기록이 아닌, 대화의 모든 분기 경로를 완전히 기록할 수 있습니다. 이는 사용자가 이전 메시지를 다시 편집하거나 시스템이 자동 압축을 수행할 때 특히 중요합니다.
채널 유형별 기록 제한
서로 다른 유형의 채팅 채널은 다른 사용 시나리오를 가지며, OpenClaw은 이에 따라 기록 길이를 차별화하여 처리합니다.
개인 채팅(DM) 채널
개인 채팅 시나리오는 일반적으로 1:1의 심층 대화로, 사용자는 AI가 더 긴 컨텍스트를 기억하기를 기대합니다. 따라서 DM 채널은 기본적으로 더 많은 기록 메시지를 보존합니다:
{
agents: {
"personal-assistant": {
history: {
dm: {
maxMessages: 100, // 최근 100개 메시지 보존
maxTokens: 32000, // 최대 Token 수
},
},
},
},
}
그룹(Group) 채널
그룹 시나리오에서는 메시지 양이 많고 주제 전환이 잦아, 너무 많은 기록을 보존하면 오히려 노이즈가 됩니다. OpenClaw은 그룹 채널에 기본적으로 더 엄격한 제한을 적용합니다:
{
agents: {
"group-bot": {
history: {
group: {
maxMessages: 30, // 최근 30개 메시지만 보존
maxTokens: 8000, // 더 작은 Token 윈도우
},
},
},
},
}
이러한 채널 유형별 구분 설계는 Token 비용을 절약하면서도 각 시나리오에서 최적의 경험을 보장합니다.
컨텍스트 오버플로 시 자동 압축
대화 기록이 모델의 컨텍스트 윈도우 제한을 초과하면, OpenClaw은 단순히 오래된 메시지를 잘라내지 않고 자동 압축(Auto-compaction) 메커니즘을 트리거합니다.
자동 압축의 작동 흐름은 다음과 같습니다:
- 현재 세션의 Token 수가 모델의 컨텍스트 제한에 근접함을 감지
- 이전 대화 내용을 모델에 전송하여 압축 요약을 생성
- 요약으로 원래의 기록 메시지를 대체하여 Token 사용량을 대폭 감소
- JSONL 파일에 새로운 압축 노드를 생성하고, 원본 메시지는 트리의 이전 분기에 보존
{"id":"compact_001","parentId":null,"role":"system","type":"compaction","content":"[세션 요약] 사용자가 Python 크롤러 개발에 대해 논의했으며, requests 라이브러리 사용, 안티크롤링 전략, 데이터 파싱 방법 등을 포함...","timestamp":1710001000}
{"id":"msg_050","parentId":"compact_001","role":"user","content":"Scrapy 프레임워크에 대해 계속 설명해 주세요","timestamp":1710001001}
압축이 발생할 때 사용자는 전혀 인지하지 못합니다. AI는 여전히 요약을 기반으로 이전 대화 배경을 이해할 수 있으면서, 매 요청의 Token 소비를 대폭 줄일 수 있습니다.
설정을 통해 압축 동작을 조정할 수 있습니다:
{
agents: {
"my-agent": {
compaction: {
enabled: true,
// Token 사용률이 얼마에 도달하면 압축을 트리거할지 (0-1)
threshold: 0.85,
// 압축 요약의 최대 Token 수
summaryMaxTokens: 1024,
// 최근 몇 개의 메시지를 압축하지 않고 보존할지
preserveRecent: 10,
},
},
},
}
세션 영구화와 분기 관리
JSONL 형식과 트리 구조의 조합으로, OpenClaw은 강력한 세션 영구화 능력을 갖추고 있습니다. 서비스가 재시작되더라도 모든 세션 상태를 완전히 복구할 수 있습니다.
분기 시나리오
트리 구조는 다음 시나리오에서 역할을 발휘합니다:
- 사용자 메시지 편집: 사용자가 이전 메시지를 수정하고 재전송하면, OpenClaw은 기존 대화 경로를 덮어쓰지 않고 편집된 노드에서 새로운 분기를 생성합니다
- 자동 압축 분기: 압축 작업이 새로운 요약 노드를 생성하고, 원본 대화는 이전 분기로 보존되어 데이터 손실이 없도록 보장합니다
- 대화 역추적: 관리자가 Dashboard를 통해 임의 분기의 전체 대화 기록을 조회할 수 있습니다
세션 데이터 조회
원시 세션 파일을 직접 조회할 수 있습니다:
# 특정 Agent의 모든 세션 나열
ls ~/.openclaw/agents/my-agent/sessions/
# 특정 세션의 내용 조회
cat ~/.openclaw/agents/my-agent/sessions/session-xxx.jsonl | jq .
Provider 무관의 모델 전환
OpenClaw의 다중 Agent 아키텍처는 또 하나의 중요한 장점을 제공합니다: 각 Agent가 독립적으로 모델 제공자와 모델명을 지정할 수 있으며, 서로 영향을 주지 않습니다.
{
agents: {
// Agent 1: Claude 사용, Telegram 개인 채팅 처리
"telegram-dm": {
model: {
provider: "claude",
name: "claude-sonnet-4-20250514",
},
channels: ["telegram"],
scope: "dm",
},
// Agent 2: Ollama 로컬 모델 사용, Discord 그룹 채팅 처리
"discord-group": {
model: {
provider: "ollama",
name: "llama3.1:70b",
},
channels: ["discord"],
scope: "group",
},
// Agent 3: GPT-4o 사용, Slack 업무 채널 처리
"slack-work": {
model: {
provider: "openai",
name: "gpt-4o",
},
channels: ["slack"],
scope: "all",
},
},
}
이러한 Provider 무관 설계는 다른 Agent의 운영에 영향을 주지 않고 특정 Agent의 모델을 언제든지 전환할 수 있음을 의미합니다. 예를 들어, 비용에 민감한 그룹 채팅 Agent를 Claude에서 Ollama 로컬 모델로 전환하면서, 개인 채팅 Agent는 고품질의 상용 모델을 계속 사용할 수 있습니다.
라우팅 규칙 요약
OpenClaw의 다중 Agent 라우팅은 다음 우선순위 체인을 따릅니다:
- 플랫폼 매칭: 메시지가 어느 채팅 플랫폼에서 왔는지 (Telegram / Discord / Slack 등)
- 채널 유형 매칭: 메시지가 개인 채팅에서 왔는지 그룹에서 왔는지
- Agent 할당: 매칭 결과에 따라 메시지를 해당 Agent로 라우팅
- 세션 조회 또는 생성: Agent의 세션 디렉터리에서 기존 세션을 찾거나 새 세션 생성
- 기록 로드: 채널 유형의 기록 제한에 따라 적절한 길이의 컨텍스트 로드
- 모델 호출: 해당 Agent에 설정된 모델로 메시지 처리
전체 흐름은 완전 자동으로 완료되며, 사용자 개입이 필요 없습니다.
정리
OpenClaw의 다중 Agent 라우팅과 세션 격리 메커니즘은 아키텍처의 가장 핵심적인 설계 중 하나입니다. 대화별 라우팅으로 완전한 컨텍스트 격리를 구현하고, JSONL 트리 구조로 영구화와 분기 관리를 실현하며, 채널 유형별 차별화된 기록 제한으로 비용과 경험의 균형을 맞추고, 자동 압축으로 컨텍스트 오버플로에 대응합니다. 이 메커니즘을 통해 여러 플랫폼에 여러 Agent를 안심하고 배포할 수 있으며, 각 Agent는 자체 세션 공간에서 안정적이고 효율적으로 운영됩니다.