# OpenDeepWiki Auto Context Compression: How It Preserves Function Calls

> Discover how OpenDeepWiki's auto context compression preserves function calls using structured `<preserve>` tags, safeguarding critical tool invocations during LLM summarization.

- Repository: [AIDotNet/OpenDeepWiki](https://github.com/aidotnet/opendeepwiki)
- Tags: deep-dive
- Published: 2026-02-19

---

**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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ContextCompressor.cs) file ([`src/OpenDeepWiki/Services/Chat/ContextCompressor.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ContextCompressor.cs)) reconstructs the conversation history:

1. **Inserts preserved function call blocks** in their original chronological positions
2. **Appends compressed summaries** of the conversational narrative
3. **Maintains logical flow** between tool invocations and user queries

### Step 5: Persistent State Management

The compressed state persists in [`ChatSession.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ChatSession.cs) ([`src/OpenDeepWiki/Entities/Chat/ChatSession.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/src/OpenDeepWiki/Entities/Chat/ChatSession.cs)). Key fields include:

- **`CompressedTokens`**: Tracks the cumulative token count saved through compression
- **`PreservedCalls`**: 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:

```csharp
// 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:

```csharp
// 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.
- **`FunctionCallRecord`** structures 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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ChatService.cs), [`ContextCompressor.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ContextCompressor.cs), and [`ChatSession.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ChatSession.cs) in 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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/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`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/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.