Summarization Engine
Relevant source files
The following files were used as context for generating this wiki page:
- server/services/conversation/summarization/summarizer.py
- server/services/conversation/summarization/scheduler.py
- server/services/conversation/summarization/prompt_builder.py
- server/services/conversation/summarization/working_memory_log.py
- server/services/conversation/log.py
- server/agents/interaction_agent/runtime.py
The Summarization Engine is a core background service responsible for maintaining a concise "working memory" of the conversation history. Its primary purpose is to compress long chat logs into a structured briefing that provides the interaction agent with high-density context without exceeding token limits or processing redundant information. It acts as a "chief-of-staff memory curator," rebuilding a strategic overview of the user's commitments, routines, and preferences.
Sources: server/services/conversation/summarization/prompt_builder.py:20-22, server/services/conversation/summarization/summarizer.py:86-120
Architecture and Data Flow
The engine operates as an asynchronous background task triggered by conversation events. It follows a cyclic pattern: collecting new log entries, merging them with existing state using an LLM, and persisting the updated summary back to the working memory storage.
Data Flow Diagram
The following diagram illustrates the flow from a log event to the updated working memory state.
Components and Logic
1. Scheduler and Worker
The scheduler.py module prevents race conditions and redundant processing by managing a singleton worker loop. It uses asyncio.get_running_loop() to spawn a background task whenever the conversation log is updated.
| Variable | Description |
|---|---|
_pending | Boolean flag indicating a summarization pass is requested. |
_running | Boolean flag indicating the worker task is currently active. |
Sources: server/services/conversation/summarization/scheduler.py:9-10
2. The Summarization Process
The summarize_conversation function in summarizer.py executes the core business logic. It evaluates whether the number of unsummarized entries exceeds a configured threshold before proceeding.
- Threshold Check: It calculates
unsummarized_entriesby comparing current logs against thelast_indexstored in theSummaryState. - Batching: It processes a batch defined by
conversation_summary_thresholdwhile maintaining a "tail" of recent messages for immediate context. - State Management: After a successful LLM call, it updates the
SummaryStatewith the new text and thecutoff_index.
Sources: server/services/conversation/summarization/summarizer.py:86-110
3. Prompt Construction
The prompt_builder.py defines the structure of the memory briefing. The LLM is instructed to output information into five distinct categories:
- Timeline & Commitments: Chronological events, meetings, and status.
- Pending & Follow-ups: Open tasks, owners, and blockers.
- Routines & Recurring: Habitual cadences and standing orders.
- Preferences & Profile: Stable user constraints (e.g., dietary needs, brands).
- Context & Notes: Strategic insights and risks.
Sources: server/services/conversation/summarization/prompt_builder.py:25-50
Persistence Layer
The engine uses two primary log files to maintain state:
- Conversation Log: An append-only record of every message (
user_message,agent_message,poke_reply). - Working Memory Log: A structured file (
poke_working_memory.log) containing the summarized text and a small buffer of the most recent unsummarized entries.
Class Diagram: Memory State
The relationship between state management and persistence is shown below.
Configuration and Integration
The summarization engine is integrated into the ConversationLog via a notification system. Every time a message is recorded, the log calls schedule_summarization().
Configuration Options
Derived from settings usage in summarizer.py:
| Setting | Type | Description |
|---|---|---|
summarization_enabled | bool | Master toggle for the service. |
conversation_summary_threshold | int | Minimum new messages required to trigger a summary pass. |
conversation_summary_tail_size | int | Number of recent messages to keep unsummarized for immediate context. |
summarizer_model | str | The OpenRouter model used for summarization. |
Sources: server/services/conversation/summarization/summarizer.py:87-100, server/services/conversation/log.py:129-145
Sequence of a Summarization Pass
This sequence shows how the interaction agent triggers the background summarization.
Conclusion
The Summarization Engine ensures the assistant's context remains relevant and manageable. By distilling raw logs into a structured "working memory," it allows the interaction agent to maintain long-term awareness of user preferences and commitments while optimizing for LLM token efficiency.
Sources: server/services/conversation/summarization/prompt_builder.py:20-22, server/agents/interaction_agent/runtime.py:151-155