# Compaction Strategy OpenClaw employs a multi-layered conversation compaction system to manage long-running sessions within finite model context windows. Unlike basic truncation, this system uses LLM-driven summarization, token-budget gating, and quality safeguards to preserve critical state, identifiers, and recent context. *** ## Trigger & Token Gating Compaction is primarily triggered by "preflight" checks before processing a new turn, ensuring the model has sufficient headroom for its next response. This process is managed in `auto-reply/reply/agent-runner-memory.ts` and `memory-flush.ts`. ### Gating Logic The decision to compact is based on a projected token count compared against a computed threshold: - **Threshold Formula**: `contextWindowTokens - reserveTokensFloor - softThresholdTokens` - **Reserve Floor**: Defaults to 20,000 tokens (`reserveTokensFloor`), providing a safety buffer for tool outputs and reasoning. - **Soft Threshold**: An additional 4,000 token buffer (`softThresholdTokens`) to prevent compaction oscillations at the exact limit. - **Token Estimation**: Performed by `estimateMessagesTokens()`, which strips `toolResult.details` for security and applies a `SAFETY_MARGIN` of 1.2 to account for estimation inaccuracies. ### Execution Hooks - **shouldRunPreflightCompaction**: Runs before a turn to ensure the input fits the budget. - **shouldRunMemoryFlush**: Evaluates if the session should be "flushed" to long-term memory based on token pressure. - **Deduplication**: `hasAlreadyFlushedForCurrentCompaction` prevents redundant flushes within a single compaction cycle. - **Manual Trigger**: The `/compact` command allows users to manually force a compaction cycle. *** ## Summarization Core The core summarization engine in `agents/compaction.ts` orchestrates the transformation of raw history into structured summaries. ### Resource Allocation - **SUMMARIZATION_OVERHEAD_TOKENS**: 4,096 tokens are reserved for the summarization prompt, system instructions, and previous summaries. - **Adaptive Chunking**: `computeAdaptiveChunkRatio` shrinks chunk sizes as the average message size increases. If a single message exceeds 50% of the context window, it is flagged as `isOversizedForSummary` and handled via fallback mechanisms. ### Orchestration Pipeline 1. **summarizeChunks**: Splits the history into chunks based on `maxChunkTokens`. 2. **summarizeWithFallback**: Attempts a full summary. On failure, it separates "small" messages from "oversized" ones, summarizing the small messages and annotating the oversized ones (e.g., `[Large message (~15K tokens) omitted from summary]`). 3. **summarizeInStages**: For very large histories, it generates partial summaries and then merges them using `MERGE_SUMMARIES_INSTRUCTIONS`. ### Preservation Priorities The system uses `MERGE_SUMMARIES_INSTRUCTIONS` to ensure the model retains: - Active tasks and current status (in-progress, blocked, pending). - Commitments, decisions, and their rationale. - Unresolved user asks and key factual identifiers. - Recent context over older history. *** ## Safeguard Extension The `compaction-safeguard.ts` hook acts as a safety layer, registering on `session_before_compact` to manage context sharing and content preservation. ### Context Preservation - **Recent Turns**: Preserves `DEFAULT_RECENT_TURNS_PRESERVE = 3` turns verbatim to maintain immediate conversational flow. - **History Pruning**: `pruneHistoryForContextShare` drops older chunks if the new content consumes too much of the history budget. Dropped messages are summarized and prepended as a `previousSummary`. - **Suffix Protection**: Critical metadata is appended to a protected suffix that survives truncation: - Tool failures (capped at 8 failures). - File operations (read/modified lists). - Workspace rules (extracted from `AGENTS.md`). ### Length Constraints - **MAX_COMPACTION_SUMMARY_CHARS**: 16,000 characters cap for the total summary. - **MAX_FILE_OPS_SECTION_CHARS**: 2,000 characters for file operation logs. - **MAX_FILE_OPS_LIST_CHARS**: 900 characters for the list of files. *** ## Quality Guard The Quality Guard (`compaction-safeguard-quality.ts`) ensures the LLM-generated summary meets strict structural and content requirements. ### Required Sections Every summary must contain these exact Markdown headings: - `## Decisions` - `## Open TODOs` - `## Constraints/Rules` - `## Pending user asks` - `## Exact identifiers` ### Identifier Preservation The system extracts opaque identifiers (URLs, file paths, hex IDs, ports) using regex and enforces their preservation. - **Strict Policy**: If `identifierPolicy` is set to `strict`, the guard validates that all extracted identifiers appear in the final summary. - **Audit Loop**: `auditSummaryQuality` checks for section presence and identifier integrity. If checks fail, the system triggers a regeneration with `qualityFeedbackInstruction`. *** ## Default Instructions Default behavior is governed by `compaction-instructions.ts`, which merges user-defined, runtime, and system-level instructions. ```typescript export const DEFAULT_COMPACTION_INSTRUCTIONS = "Write the summary body in the primary language used in the conversation.\n" + "Focus on factual content: what was discussed, decisions made, and current state.\n" + "Keep the required summary structure and section headers unchanged.\n" + "Do not translate or alter code, file paths, identifiers, or error messages."; ``` Instructions are capped at `MAX_INSTRUCTION_LENGTH = 800` characters to prevent prompt bloat. *** ## Runtime Execution & Truncation The `compact.ts` runner provides the entry point for both automated and manual compaction. ### Execution Flow 1. **Preparation**: Opens the session, sanitizes history, and runs `before_compaction` hooks. 2. **Safety Timeout**: Wraps the LLM call in `compactWithSafetyTimeout` to prevent hanging processes. 3. **Post-Processing**: Runs `after_compaction` hooks and estimates the resulting token count. ### Session Truncation If enabled via `config.agents.defaults.compaction.truncateAfterCompaction`, the system physically rewrites the session JSONL file using `session-truncation.ts`. - **Removal**: Deletes message entries that were summarized. - **Re-parenting**: Re-parents orphaned entries to the nearest kept ancestor to maintain the integrity of the session tree. - **Archiving**: Optionally creates an archive of the original session file before truncation. *** ## Configuration Knobs Compaction behavior can be tuned via `OpenClawConfig`: - `config.agents.defaults.compaction.model`: Override the model used for summarization. - `config.agents.defaults.compaction.reserveTokensFloor`: Minimum buffer (default ~20,000). - `config.agents.defaults.compaction.timeoutSeconds`: Max time allowed for a summarization call. - `config.agents.defaults.compaction.truncateAfterCompaction`: Boolean to enable physical file cleanup. - `memoryFlush`: Configuration for soft thresholds and forced flush triggers. *** ## Relevance to Luna Luna currently uses a basic `LibrarianAgent` for compaction with no token-budget gating, no quality guards, and no structured instruction sets. To achieve OpenClaw-level reliability, Luna should adopt: - **Token-Budget Gating**: Triggering compaction based on projected context usage rather than arbitrary turn counts. - **Structured Sections**: Enforcing a specific Markdown schema in summaries to ensure critical state is never lost. - **Identifier Preservation**: Using regex extraction and quality audits to protect file paths and IDs. - **Quality Audit Loop**: Implementing a verification step that can re-trigger summarization if requirements are missed. - **Session Truncation**: Physically cleaning up on-disk history files to prevent unbounded growth. Patterns like the `compaction-safeguard` provide a more resilient approach for long-term project management in Luna by ensuring the project state, goals, and critical constraints are always prioritized in the model's working memory. See also: [[Core]], [[Configuration]], [[Session Management]]