15. Conversation Summaries
Long conversations with AI systems generate context that exceeds model context windows. OpenCLaw implements automatic conversation summarization to compress historical context while preserving essential information for continuity.
Summary Triggers
Summarization occurs at three trigger conditions: token count thresholds (configurable, default 4K tokens), conversation segment boundaries (user indicates topic change), and time gaps (pause exceeding threshold).
# conversation_summarizer.py
from typing import List, Tuple, Optional
from dataclasses import dataclass
from datetime import datetime, timedelta
@dataclass
class ConversationSegment:
messages: List[Message]
start_time: datetime
end_time: datetime
topic: Optional[str] = None
summary: Optional[str] = None
class ConversationSummarizer:
def __init__(
self,
token_threshold: int = 4000,
time_gap_threshold: timedelta = timedelta(minutes=30),
llm_client: LLMClient = None
):
self.token_threshold = token_threshold
self.time_gap_threshold = time_gap_threshold
self.llm = llm_client
def should_summarize(self, conversation: Conversation) -> bool:
if self.count_tokens(conversation) > self.token_threshold:
return True
if self.has_topic_boundary(conversation):
return True
if self.has_time_gap(conversation):
return True
return False
def summarize_segment(
self,
segment: ConversationSegment
) -> str:
prompt = f"""Summarize the following conversation segment.
Preserve: key decisions, user preferences expressed,
tasks mentioned, important context.
Conversation:
{self.format_segment(segment)}
Summary:"""
response = self.llm.generate(prompt, max_tokens=200)
return response.content
def compress_conversation(
self,
conversation: Conversation
) -> Tuple[List[Message], List[ConversationSegment]]:
segments = self.segment_conversation(conversation)
summaries = []
for segment in segments:
if self.should_summarize_segment(segment):
summary_text = self.summarize_segment(segment)
summary_msg = Message(
role="system",
content=f"[Earlier conversation summary: {summary_text}]"
)
summaries.append(summary_msg)
else:
summaries.extend(segment.messages)
return summaries, segments
Hierarchical Summaries
For very long conversations, OpenCLaw implements hierarchical summarization. Individual exchanges summarize to segment summaries, segments summarize to conversation arc summaries, and arcs summarize to full context narratives.
class HierarchicalSummarizer:
def __init__(self, levels: int = 3):
self.levels = levels
self.summarizers = [
FineGrainedSummarizer(),
MidLevelSummarizer(),
ArcSummarizer()
][:levels]
def compress(self, messages: List[Message]) -> Message:
current_level = messages
for level, summarizer in enumerate(self.summarizers):
compressed = summarizer.compress(current_level)
current_level = [Message(role="system", content=compressed)]
return current_level[0]
Entity and Fact Tracking
Summarization preserves not just narrative flow but specific entities and facts. The system maintains an entity registry that gets updated across summaries, ensuring that referenced people, dates, and decisions remain accessible even when their originating messages are compressed away.
Implement a summary coherence checker that validates whether a compressed conversation preserves logical consistency. Design metrics for measuring summary quality beyond simple token reduction.