How to Configure Compression Pipeline Hooks in Headroom: A Complete Guide
To configure compression pipeline hooks in Headroom, subclass CompressionHooks from headroom.hooks, implement the lifecycle methods (pre_compress, compute_biases, post_compress), and pass an instance to ProxyConfig.hooks when initializing the proxy.
Headroom is an open-source LLM proxy that compresses request contexts to reduce token costs. Configuring compression pipeline hooks in Headroom allows you to intercept, modify, and monitor the compression process at well-defined stages of the request lifecycle without modifying core pipeline code.
Understanding the Compression Hooks Architecture
Headroom’s hook system centers on a single abstract base class that defines extension points for the compression pipeline. The architecture separates concerns between the proxy configuration layer, the hook implementations, and the transform pipeline itself.
The CompressionHooks Base Class
The CompressionHooks class in headroom/hooks.py (lines 21–51) defines four extension methods with default no-op implementations:
pre_compress(messages, ctx)– Called before any transforms runcompute_biases(messages, ctx)– Called after pre-processing but before compressionpost_compress(event)– Called after the pipeline completeson_pipeline_event(event)– Optional handler for pipeline lifecycle events
All methods have default implementations, so you only override the stages you need.
CompressContext and CompressEvent Data Classes
Hooks receive context through two specialized dataclasses defined in the same file:
CompressContextcarries conversation metadata including model name, user query, turn number, tool calls, and provider information.CompressEventcontains post-compression metrics includingtokens_before,tokens_after,tokens_saved, compression ratios, and applied transform names.
ProxyConfig Integration
The ProxyConfig dataclass in headroom/proxy/models.py (lines 79–81) accepts a hooks parameter that holds your custom implementation. When the proxy server processes requests, it extracts this hook object and invokes the appropriate methods at each pipeline stage.
Hook Execution Lifecycle
The proxy orchestrates hook calls around the TransformPipeline.apply method in headroom/transforms/pipeline.py. Execution follows this strict sequence:
-
pre_compressreceives the full message list andCompressContext. Use this to rewrite, filter, or inject messages before compression begins. -
compute_biasesreturns a dictionary mapping message indices to bias factors. Values greater than 1.0 indicate "keep more tokens"; values less than 1.0 indicate "compress harder." -
post_compressreceives aCompressEventcontaining token counts and compression statistics. Use this for logging, analytics, or feedback loops. -
on_pipeline_eventreceives anyPipelineEventemitted during execution. Return a modified event to augment or replace the default event handling.
Implementing Custom Hooks
Creating a Position-Aware Bias Hook
The following implementation biases the compression algorithm to preserve the middle of a conversation, where context is often most relevant:
# my_hooks.py
from headroom.hooks import CompressionHooks, CompressContext
class PositionBiasHooks(CompressionHooks):
def compute_biases(self, messages, ctx: CompressContext):
"""Apply higher bias to center messages to preserve them."""
biases = {}
n = len(messages)
for i in range(n):
pos = i / max(n - 1, 1) # Normalize to 0.0–1.0
# Peak bias at center (pos ≈ 0.5)
biases[i] = 1.0 + 0.5 * (1.0 - abs(2 * pos - 1))
return biases
This override matches the signature documented at lines 21–27 of headroom/hooks.py.
Building a Logging and Analytics Hook
Capture detailed compression metrics for monitoring or cost analysis:
# logging_hooks.py
import logging
from headroom.hooks import CompressionHooks, CompressEvent
log = logging.getLogger("headroom.hooks")
class MetricsHooks(CompressionHooks):
def post_compress(self, event: CompressEvent) -> None:
"""Log compression savings and ratios."""
if event.tokens_before > 0:
savings_pct = (event.tokens_saved / event.tokens_before) * 100
else:
savings_pct = 0
log.info(
"Compression: %d → %d tokens (saved %d, %.1f%%)",
event.tokens_before,
event.tokens_after,
event.tokens_saved,
savings_pct
)
The post_compress method signature and CompressEvent attributes are defined at lines 31–44 of headroom/hooks.py.
Handling Pipeline Events with on_pipeline_event
For advanced lifecycle management, intercept pipeline events to inject custom attributes:
# lifecycle_hooks.py
from headroom.hooks import CompressionHooks, PipelineEvent
class LifecycleHooks(CompressionHooks):
def on_pipeline_event(self, event: PipelineEvent) -> PipelineEvent | None:
"""Augment events with custom metadata."""
event.attributes["custom_tracking_id"] = "my-app-v1"
return event
This optional hook is documented at lines 45–51 of headroom/hooks.py.
Integrating Hooks into ProxyConfig
After implementing your subclass, wire it into the proxy configuration:
# server_startup.py
from headroom.proxy.server import HeadroomProxy, ProxyConfig
from my_hooks import PositionBiasHooks
config = ProxyConfig(hooks=PositionBiasHooks())
proxy = HeadroomProxy(config)
The proxy server reads config.hooks during request handling and invokes pre_compress, compute_biases, and post_compress at the appropriate stages. If on_pipeline_event is implemented, the pipeline dispatches events to your handler before final processing.
Summary
- Subclass
CompressionHooksfromheadroom/hooks.pyto customize compression behavior. - Implement lifecycle methods:
pre_compressfor pre-processing,compute_biasesfor token allocation control, andpost_compressfor analytics. - Pass hook instances to
ProxyConfig(hooks=...)as defined inheadroom/proxy/models.py. - Access rich context through
CompressContext(input metadata) andCompressEvent(output metrics). - Maintain backward compatibility by only overriding the methods you need; default no-op implementations preserve existing behavior.
Frequently Asked Questions
What is the difference between pre_compress and compute_biases?
pre_compress runs before any transforms and allows you to modify the message list itself—filtering, reordering, or injecting content. compute_biases runs after pre-processing but before the actual compression transforms, and it only returns a mapping of indices to bias factors that influence how aggressively each message is compressed. Use pre_compress for structural changes; use compute_biases for soft weighting without modifying content.
Can I use multiple hooks simultaneously?
Headroom’s ProxyConfig accepts a single hooks instance. To combine multiple behaviors, create a composite hook class that inherits from CompressionHooks and delegates to your individual implementations, or chain logic within a single class by calling multiple internal methods from each lifecycle hook.
How do I access turn number and model metadata in hooks?
The CompressContext object passed to pre_compress and compute_biases contains attributes for turn_number, model_name, provider, and tool_calls. According to the source in headroom/hooks.py, this dataclass carries all conversation metadata from the proxy layer into your hook implementation.
Are hooks required for Headroom to function?
No. All methods in CompressionHooks have default no-op implementations in headroom/hooks.py. If you do not provide a custom hooks instance to ProxyConfig, the proxy operates with the default behavior, applying the standard compression pipeline without custom pre-processing, biasing, or post-processing logic.
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 →