Tools
Context Distiller
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.
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.
[](https://opensource.org/licenses/MIT)
[](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