OpenDeepWiki Auto Context Compression: How It Preserves Function Calls
OpenDeepWiki uses a structured marking system with <preserve> tags to shield function call records from LLM-based summarization, ensuring critical tool invocations remain intact during auto context compression.
The AIDotNet/OpenDeepWiki repository implements an intelligent auto context compression mechanism to handle long-running AI conversations without hitting token limits. This system specifically addresses the challenge of preserving function calls—structured tool invocations like search_repo or read_file—while compressing conversational history into concise summaries.
The Challenge of Token Limits in AI Conversations
As conversations grow, the accumulated context can exceed model token constraints. Simple truncation risks losing critical information, particularly function call metadata that maintains the conversation's logical flow. OpenDeepWiki solves this by distinguishing between compressible narrative text and incompressible structured data.
How OpenDeepWiki Auto Context Compression Works
The compression pipeline operates through five distinct phases, implemented across the chat service architecture.
Step 1: Structured Function Call Recording
When the system executes a tool, it captures the invocation as a FunctionCallRecord rather than plain text. In src/OpenDeepWiki/Services/Chat/ChatService.cs, the system records:
- Function name (e.g.,
search_repo) - Arguments (the parameter object)
- Return results (the tool output)
This structured approach separates function calls from conversational text, making them identifiable during compression.
Step 2: Marking Critical Sections with Preserve Tags
Before compression begins, the MarkPreserveScope method (located in ChatService.cs around lines 210-225) scans the conversation history. It identifies all FunctionCallRecord entries and wraps their token blocks with <preserve> markers.
These markers act as instructions to the compression engine: skip these sections entirely. This ensures that function call syntax, parameter values, and return data remain unaltered.
Step 3: Selective Compression via LLM
The ContextCompressor.cs file (src/OpenDeepWiki/Services/Chat/ContextCompressor.cs) implements the CompressAsync method. This uses an LLM (typically GPT-3.5-turbo-16k or a configured alternative) to summarize conversational content.
Crucially, the compressor parses the <preserve> tags and excludes marked blocks from the summarization process. Only unmarked narrative text gets compressed into concise summaries.
Step 4: Merging Preserved and Compressed Content
After compression, the MergeCompressedAsync method (lines 87-104 in ContextCompressor.cs) reconstructs the conversation history:
- Inserts preserved function call blocks in their original chronological positions
- Appends compressed summaries of the conversational narrative
- Maintains logical flow between tool invocations and user queries
Step 5: Persistent State Management
The compressed state persists in ChatSession.cs (src/OpenDeepWiki/Entities/Chat/ChatSession.cs). Key fields include:
CompressedTokens: Tracks the cumulative token count saved through compressionPreservedCalls: Maintains a list of all function calls retained in the session
This persistence ensures that compression benefits accumulate across conversation turns without losing critical tool interaction history.
Implementation Details and Code Examples
The following pattern demonstrates how function calls are recorded and protected:
// In ChatService.cs - Recording a tool execution
var result = await _gitTool.SearchRepositoryAsync(query);
await _chatService.RecordFunctionCallAsync(
name: "search_repo",
arguments: new { query = "OpenDeepWiki compression" },
result: result);
When compression triggers, the system processes messages like this:
// Conceptual flow in ContextCompressor.cs
public async Task<List<Message>> CompressAsync(List<Message> messages)
{
var preservedBlocks = ExtractPreserveBlocks(messages);
var compressibleText = RemovePreserveBlocks(messages);
var summary = await _llm.SummarizeAsync(compressibleText);
return MergeWithPreserved(summary, preservedBlocks);
}
The resulting compressed context maintains function call integrity:
<preserve>
[FunctionCall] search_repo({"query":"OpenDeepWiki compression"})
=> {"results":[{"id":123,"name":"OpenDeepWiki"}]}
</preserve>
[Summary] User inquired about compression mechanisms in OpenDeepWiki...
Summary
- OpenDeepWiki auto context compression uses a hybrid approach: LLM summarization for narrative text and structural preservation for function calls.
<preserve>tags mark function call blocks as incompressible, ensuring tool invocations remain syntactically valid and contextually accessible.FunctionCallRecordstructures capture name, arguments, and results separately from conversational text, enabling precise identification during compression.- Five-phase pipeline: Recording → Marking → Selective Compression → Merging → Persistence ensures zero loss of critical tool interaction data.
- Implementation spans
ChatService.cs,ContextCompressor.cs, andChatSession.csin the AIDotNet/OpenDeepWiki repository.
Frequently Asked Questions
How does OpenDeepWiki distinguish between compressible text and function calls?
The system relies on structured data types rather than pattern matching. When a tool executes, ChatService.cs creates a FunctionCallRecord object containing the function name, arguments, and result. This structured record is wrapped in <preserve> tags before compression begins, explicitly signaling to the ContextCompressor that these tokens must be excluded from summarization.
What happens if a compressed conversation exceeds token limits again?
OpenDeepWiki implements iterative compression tracked through the CompressedTokens field in ChatSession.cs. If a session approaches limits after initial compression, the system re-evaluates the entire history. Previously compressed summaries may be further condensed, while function calls in the PreservedCalls list remain protected by their <preserve> markers, ensuring cumulative compression never degrades tool interaction integrity.
Does context compression affect the chronological order of function calls?
No, the temporal sequence is strictly maintained. During the merge phase in ContextCompressor.cs, the MergeCompressedAsync method reconstructs the message list by inserting preserved function blocks at their original chronological positions relative to compressed narrative summaries. This ensures that dependencies between consecutive tool calls (where one function's output becomes another's input) remain logically coherent.
Which LLM models does OpenDeepWiki use for the compression task?
According to the source code in ContextCompressor.cs, the default compression engine is GPT-3.5-turbo-16k, chosen for its balance of context window size and cost efficiency. However, the implementation supports configurable LLM providers through dependency injection, allowing deployment-specific alternatives (such as GPT-4 or local models) to handle the CompressAsync operations while maintaining the same <preserve> tag protocol.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →