← Back to Plugins
Tools

Context Distiller

baixiaodev By baixiaodev 👁 392 views ▲ 0 votes

I don't know code at all, and this is my first time to upload my "code" to public. I hope this plugin is useful to you all. Intelligent context distillation plugin for OpenClaw — reduces context noise by compressing verbose tool outputs, patches, and file content. Saves 65-85% tokens on average.

GitHub

Install

npm install
```

Configuration Example

{
  "plugins": {
    // 1. Allow the plugin
    "allow": [
      // ... existing plugins ...
      "context-distiller"
    ],

    // 2. Configure it
    "entries": {
      "context-distiller": {
        "enabled": true,
        "config": {
          "toolOutputMaxTokens": 1200,
          "patchMaxTokens": 600,
          "fileContentMaxTokens": 1000,
          "aggressiveness": "moderate",
          "distillModel": "ollama/qwen3:8b"  // optional, for LLM-powered summarization
        }
      }
    },

    // 3. Register install path
    "installs": {
      "context-distiller": {
        "source": "path",
        "installPath": "/path/to/.openclaw/extensions/context-distiller",
        "version": "0.1.0"
      }
    }
  }
}

README

# context-distiller

> Intelligent context distillation plugin for [OpenClaw](https://github.com/nicepkg/openclaw) — reduces context noise by compressing verbose tool outputs, patches, and file content before they enter the context window.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![OpenClaw Plugin](https://img.shields.io/badge/OpenClaw-Plugin-blue)](https://github.com/nicepkg/openclaw)

---

## Why context-distiller?

When AI agents work on complex tasks, they generate massive amounts of context: tool outputs, file reads, search results, diffs, and logs. This verbose content fills up the context window fast, causing:

- **Context overflow** — the LLM silently drops important earlier messages
- **Degraded reasoning** — too much noise drowns out the signal
- **Higher costs** — more tokens = more money

**context-distiller** hooks into OpenClaw's message pipeline and compresses verbose content *before* it enters the context engine. Think of it as a smart filter that keeps the important bits and throws away the noise.

### Results from real-world testing (20 research scenarios):

| Metric | Value |
|--------|-------|
| Total distillations | 98 |
| Tokens saved | **636,186** |
| Avg. compression | 65-85% on verbose outputs |
| Rules triggered | 9 different compression strategies |
| False positives | 0 (small content passes through untouched) |

---

## Architecture

```
User Query → Agent → Tool Call → Tool Result
                                      ↓
                        ┌─────────────────────────┐
                        │   tool_result_persist    │  ← sync hook (primary)
                        │                         │
                        │  1. Content Analysis     │  detect value: search/API/log/help/error
                        │  2. Budget Adjustment    │  high-value → 4x budget, low-value → 0.6x
                        │  3. Rule Pipeline        │  6 rules sorted by priority
                        │  4. distillSync()        │  pure synchronous, no Promises
                        │                         │
                        └────────────┬────────────┘
                                     ↓
                        ┌─────────────────────────┐
                        │  before_message_write    │  ← sync hook (safety net)
                        │  catches remaining       │
                        │  verbose tool messages   │
                        └────────────┬────────────┘
                                     ↓
                           Context Engine (LCM)
                         e.g. lossless-claw
```

### Design Principles

1. **Enhance, don't replace** — Works alongside any context engine (lossless-claw, built-in, etc.)
2. **Content-aware intelligence** — Different content types get different treatment. Search results are preserved; install logs are aggressively compressed.
3. **Pure synchronous execution** — Gateway's `tool_result_persist` hook is strictly sync. All distillation runs without async/await/Promise.
4. **Graceful degradation** — If a rule fails, the content passes through unchanged. If stats I/O fails, distillation continues.
5. **Observable** — Persistent statistics survive Gateway restarts. Agent tools let you inspect and tune at runtime.

### Content Intelligence Layer

Before applying any compression rules, the plugin analyzes content to determine its value:

| Content Type | Value | Budget Multiplier | Strategy |
|-------------|-------|-------------------|----------|
| Search results (Tavily/Google/Bing JSON) | Critical | 4.0× | Structured JSON summary preserving URLs/titles/snippets |
| API responses (web_fetch, structured JSON) | High | 4.0× | JSON summary with leading paragraphs preserved |
| URL-rich content | High | 2.5× | Smart truncation |
| Error output | Medium | 1.2× | Error line extraction + head/tail |
| Generic tool output | Medium | 1.0× | Standard rule pipeline |
| Install/build logs | Low | 0.8× | Aggressive head+tail |
| Usage/help text | Low | 0.6× | Aggressive head+tail |

### Rule Pipeline (by priority)

| Priority | Rule | Applies To | Strategy |
|----------|------|-----------|----------|
| P4 | `domain-aware` | file_content, tool_output | BibTeX bibliography → compact listing; CSV/TSV → stats + samples; Markdown → heading skeleton |
| P5 | `repetition-elimination` | tool_output, file_content, text | 4-tier dedup: records → lines → blocks → templates. JSON excluded (routed to dedicated JSON summary) |
| P8 | `error-extraction` | tool_output | Preserves error/warning/summary lines from verbose logs. Prevents the "buried error" problem |
| P10 | `tool-output-truncation` | tool_output | JSON summary → file listing summary → LLM summary → head+tail truncation |
| P10 | `patch-distill` | patch | Keeps changed lines (+/-) with configurable context. Falls back to stats-only for huge diffs |
| P10 | `file-content-distill` | file_content | Config JSON → code structural summary (imports + definitions) → LLM summary → truncation |

### Persistent Statistics

Gateway reloads plugins on every request (stateless architecture). To maintain cumulative stats across restarts, context-distiller uses a `.stats.json` sidecar file with:
- Throttled writes (≤ 1 per 5 seconds)
- Atomic POSIX rename for crash safety
- Graceful degradation if disk I/O fails

---

## Installation

### From source (local path)

```bash
# Clone the repo
git clone https://github.com/baixiaodev/context-distiller.git ~/.openclaw/extensions/context-distiller

# Install dependencies (shares with other OpenClaw plugins)
cd ~/.openclaw/extensions/context-distiller
npm install
```

### Register in openclaw.json

Add the following to your `openclaw.json`:

```jsonc
{
  "plugins": {
    // 1. Allow the plugin
    "allow": [
      // ... existing plugins ...
      "context-distiller"
    ],

    // 2. Configure it
    "entries": {
      "context-distiller": {
        "enabled": true,
        "config": {
          "toolOutputMaxTokens": 1200,
          "patchMaxTokens": 600,
          "fileContentMaxTokens": 1000,
          "aggressiveness": "moderate",
          "distillModel": "ollama/qwen3:8b"  // optional, for LLM-powered summarization
        }
      }
    },

    // 3. Register install path
    "installs": {
      "context-distiller": {
        "source": "path",
        "installPath": "/path/to/.openclaw/extensions/context-distiller",
        "version": "0.1.0"
      }
    }
  }
}
```

### Restart Gateway

```bash
openclaw gateway restart
# or: launchctl kickstart -k user/$(id -u)/com.openclaw.gateway
```

### Verify

Check Gateway logs for:
```
[context-distiller] Plugin loaded #1 (enabled=true, aggressiveness=moderate, toolMax=1200, patchMax=600, fileMax=1000, rules=6, lifetime: 0 distillations, 0 tokens saved)
```

Or ask your agent:
```
> Use the distill_status tool
```

---

## Configuration

### Config Parameters

| Parameter | Default | Range | Description |
|-----------|---------|-------|-------------|
| `enabled` | `true` | — | Master switch |
| `toolOutputMaxTokens` | `1200` | 100–5000 | Threshold for tool output distillation |
| `patchMaxTokens` | `600` | 100–3000 | Threshold for diff/patch distillation |
| `fileContentMaxTokens` | `1000` | 200–5000 | Threshold for file content distillation |
| `aggressiveness` | `"moderate"` | conservative / moderate / aggressive | Controls compression intensity |
| `preservePatterns` | `[]` | Array of regex strings | Content matching these patterns is never distilled |
| `distillModel` | `"ollama/qwen3:8b"` | Any model ref | Model for LLM-powered summarization (optional) |
| `distillProvider` | — | Provider ID | Override provider for distill LLM calls |

### Aggressiveness Multipliers

The aggressiveness level applies a multiplier to all token thresholds:

| Level | Multiplier | Effect |
|-------|-----------|--------|
| `conservative` | 1.5× | Thresholds 50% higher → less distillation, more detail preserved |
| `moderate` | 1.0× | Thresholds as configured |
| `aggressive` | 0.6× | Thresholds 40% lower → more distillation, maximum token savings |

### Environment Variable Overrides

Environment variables take highest precedence:

```bash
CONTEXT_DISTILLER_ENABLED=true
CONTEXT_DISTILLER_AGGRESSIVENESS=aggressive
CONTEXT_DISTILLER_TOOL_MAX_TOKENS=800
CONTEXT_DISTILLER_PATCH_MAX_TOKENS=400
CONTEXT_DISTILLER_FILE_MAX_TOKENS=600
CONTEXT_DISTILLER_MODEL=ollama/qwen3:8b
CONTEXT_DISTILLER_PROVIDER=ollama
```

### Runtime Configuration

Your agent can adjust settings on the fly:

```
> Use distill_configure to set aggressiveness to aggressive
> Use distill_configure to set toolOutputMaxTokens to 800
```

---

## Agent Tools

### `distill_status`

Shows lifetime and session statistics, rule hit counts, and current configuration.

```
> Show me the distill status

## Context Distiller Status

### 📊 Lifetime Statistics (across all sessions)
- Total distillations: **98**
- Total tokens saved: **636,186**
- Plugin loaded: 44 time(s)

### Rule Hit Counts (lifetime)
- smart/search-results: 31
- tool-output-truncation/head-tail: 28
- smart/api-response: 15
- tool-output-truncation/listing: 11
- ...
```

Supports `--reset` to zero out all stats.

### `distill_configure`

Adjust configuration at runtime without restarting:

```
> Set the distiller to aggressive mode and lower tool output threshold to 800

Configuration updated: {
  "aggressiveness": "aggressive",
  "toolOutputMaxTokens": 800
}
```

---

## Use Cases

### 1. Research & Analysis Tasks

When agents perform web searches (Tavily, Google, Bing), results are often 3,000–8,000+ tokens of JSON. context-distiller:
- **Detects** search result JSON structure (url + title + snippet pattern)
- **Preserves** URLs, titles, and snippet previews
- **Compresses** 5,000 tokens → 800–1,200 tokens (75–85% reduction)

### 2. Code Exploration & Refactoring

Reading large source files (1,000+ lines) fills the context fast. context-distiller:
- **Extracts

... (truncated)
tools

Comments

Sign in to leave a comment

Loading comments...