# How to Configure Custom Compression Policies for Different Content Types in Headroom

> Learn to configure custom compression policies for different content types in Headroom using ContentRouterConfig. Customize algorithms, token thresholds, and per-tool profiles easily.

- Repository: [Tejas Chopra/headroom](https://github.com/chopratejas/headroom)
- Tags: how-to-guide
- Published: 2026-06-09

---

**Headroom routes incoming data through specialized compressors based on content type detection, controlled entirely by the `ContentRouterConfig` dataclass in [`headroom/transforms/content_router.py`](https://github.com/chopratejas/headroom/blob/main/headroom/transforms/content_router.py) where you can enable specific algorithms, set token thresholds, and define per-tool profiles.**

Headroom is an intelligent compression framework that optimizes token usage for LLM workflows by selecting context-aware compression strategies. To configure custom compression policies for different content types, you manipulate the `ContentRouterConfig` object passed to the `ContentRouter` at initialization, allowing fine-grained control over which compressors activate for code, logs, search results, or plain text.

## Understanding the ContentRouter Architecture

The routing logic lives in [`headroom/transforms/content_router.py`](https://github.com/chopratejas/headroom/blob/main/headroom/transforms/content_router.py) and follows a detection-then-compression pipeline. When processing content, the router executes this flow:

1. Detect mixed content and route each section individually
2. Call `_detect_content` to obtain a `ContentType` classification
3. Map `ContentType` to `CompressionStrategy` via `_strategy_from_detection` (lines 45-55)
4. Apply the chosen compressor through `_apply_strategy_to_content`
5. Record decisions in a `RouterCompressionResult` containing tokens saved and strategy used

The `ContentRouterConfig` dataclass (defined at lines 19-60) serves as the single source of truth for customizing this behavior. All configuration fields are plain Python attributes, making experimentation straightforward and reproducible.

## ContentRouterConfig Reference

The configuration controls three orthogonal concerns: feature toggles, routing preferences, and per-tool compression profiles.

### Feature Toggles and Routing Preferences

Control which compressors are active and how the router prioritizes them:

- **`enable_<compressor>`** (bool): Turn individual compressors on or off (e.g., `enable_log_compressor=False` disables log compression entirely)
- **`prefer_code_aware_for_code`** (bool): When `True`, prefers the AST-aware `CodeAwareCompressor` over generic ML compression for source code
- **`min_section_tokens`** (int): Minimum token count threshold before attempting compression (e.g., `min_section_tokens=50` skips small snippets)
- **`fallback_strategy`** (enum): Defines the `CompressionStrategy` used when no specific compressor matches (e.g., `CompressionStrategy.TEXT` or `CompressionStrategy.KOMPRESS`)
- **`skip_user_messages`** (bool): Protects user messages from compression (defaults to `True`)

### Per-Tool Compression Profiles

Fine-tune individual compressor behavior through the **`tool_profiles`** dictionary, which maps tool names to configuration objects defined in [`headroom/config.py`](https://github.com/chopratejas/headroom/blob/main/headroom/config.py):

- **`search`**: Accepts `SearchCompressorConfig` with parameters like `max_results`, `relevance_threshold`, and `preserve_file_diversity`
- **`log`**: Accepts `LogCompressorConfig` with `preserve_errors`, `max_lines`, and error-pattern matching
- **`code`**: Accepts profiles for AST-aware compression with token-count limits and semantic relevance filters

## Practical Configuration Examples

Create a custom configuration by instantiating `ContentRouterConfig` with your desired parameters, then pass it to the `ContentRouter` constructor.

### Disabling Specific Compressors

Disable the log compressor and set a high token threshold to avoid compressing small payloads:

```python
from headroom.transforms import ContentRouter, ContentRouterConfig, CompressionStrategy

custom_cfg = ContentRouterConfig(
    enable_log_compressor=False,                 # Never compress build logs

    enable_search_compressor=True,
    enable_kompress=True,
    prefer_code_aware_for_code=False,            # Use Kompress for code instead of AST

    min_section_tokens=50,                       # Only compress sections ≥50 tokens

    fallback_strategy=CompressionStrategy.TEXT,  # Fall back to plain-text compressor

)
router = ContentRouter(config=custom_cfg)

```

### Configuring Search and Log Profiles

Define granular behaviors for specific content types using tool-specific config classes:

```python
from headroom.transforms.search_compressor import SearchCompressorConfig
from headroom.transforms.log_compressor import LogCompressorConfig

custom_cfg = ContentRouterConfig(
    tool_profiles={
        "search": SearchCompressorConfig(
            max_results=30,
            preserve_file_diversity=True,
            relevance_threshold=0.2,
        ),
        "log": LogCompressorConfig(
            preserve_errors=True,
            max_lines=200,
        ),
    },
)
router = ContentRouter(config=custom_cfg)

# Search results now use the custom profile above

search_content = """\
src/utils.py:42:def process_data(items):
src/main.py:88:class Application:
"""
result = router.compress(search_content, context="process data")
print(f"Strategy used: {result.strategy_used}")
print(f"Compression ratio: {result.compression_ratio}")

```

The returned `RouterCompressionResult` exposes `routing_log`, `strategy_used`, and `compression_ratio` for auditing and debugging.

## Advanced: Per-Request Compression Policies

The router also honors **per-request policies** passed through the `apply()` method (used by Headroom's proxy layer). These runtime policies contain flags like `toin_read_only` that disable TOIN learning for subscription-mode sessions. This mechanism is wired into the router via the private attribute `_runtime_compression_policy` (lines 71-80 in [`content_router.py`](https://github.com/chopratejas/headroom/blob/main/content_router.py)).

Unless you are implementing a custom proxy or middleware layer, you typically interact with these polices indirectly through the standard `ContentRouterConfig` initialization shown above.

## Summary

- **Primary configuration**: Use `ContentRouterConfig` in [`headroom/transforms/content_router.py`](https://github.com/chopratejas/headroom/blob/main/headroom/transforms/content_router.py) to define how content maps to compression strategies
- **Content detection**: The router automatically classifies input via `_detect_content` and routes through `_strategy_from_detection` based on your config
- **Feature toggles**: Enable or disable specific compressors like `LogCompressor`, `SearchCompressor`, or `CodeAwareCompressor` using boolean flags
- **Tool profiles**: Pass specialized config objects (e.g., `SearchCompressorConfig` from [`headroom/transforms/search_compressor.py`](https://github.com/chopratejas/headroom/blob/main/headroom/transforms/search_compressor.py)) to `tool_profiles` for fine-grained control
- **Fallback handling**: Set `fallback_strategy` to ensure content always compresses even when type detection is ambiguous
- **Runtime overrides**: Advanced users can inject per-request policies via the proxy layer's `apply()` method

## Frequently Asked Questions

### How does Headroom automatically detect content types?

Headroom uses the `ContentDetector` class defined in [`headroom/transforms/content_detector.py`](https://github.com/chopratejas/headroom/blob/main/headroom/transforms/content_detector.py) to analyze payload structure and heuristics. The detection runs in `_detect_content` within the `ContentRouter`, classifying input into categories like code, logs, search results, or mixed content before the routing logic selects an appropriate `CompressionStrategy`.

### Can I completely disable the log compressor while keeping other compressors active?

Yes. Set `enable_log_compressor=False` in your `ContentRouterConfig` initialization. According to the source code in [`headroom/transforms/content_router.py`](https://github.com/chopratejas/headroom/blob/main/headroom/transforms/content_router.py), this boolean flag gates the execution of the log compression pathway, causing the router to skip `LogCompressor` and proceed to the next applicable strategy or the configured fallback.

### What happens if no compressor matches my content type?

The router uses the `fallback_strategy` parameter to determine behavior when detection fails or when all specific compressors are disabled. As implemented in `_strategy_from_detection`, if no specific mapping exists for the detected `ContentType`, the system applies the strategy specified in your `ContentRouterConfig` (commonly `CompressionStrategy.TEXT` for the generic `TextCompressor` or `CompressionStrategy.KOMPRESS` for ML-based compression).

### How do I set different compression thresholds for search results versus logs?

Define separate entries in the `tool_profiles` dictionary when constructing `ContentRouterConfig`. For search results, instantiate `SearchCompressorConfig` (defined in [`headroom/transforms/search_compressor.py`](https://github.com/chopratejas/headroom/blob/main/headroom/transforms/search_compressor.py) lines 1-30) with parameters like `max_results` and `relevance_threshold`. For logs, use `LogCompressorConfig` (from [`headroom/transforms/log_compressor.py`](https://github.com/chopratejas/headroom/blob/main/headroom/transforms/log_compressor.py)) with `max_lines` and `preserve_errors` settings. This allows independent tuning of aggressiveness and preservation rules per content type.