How to Customize the Headroom Transform Pipeline: 4 Proven Methods
To customize the Headroom transform pipeline, pass a custom list of transforms to the TransformPipeline constructor, toggle individual transforms via HeadroomConfig flags, or subclass the Transform base class to inject custom logic while inheriting built-in circuit-breaker safety.
The Headroom library (chopratejas/headroom) provides a modular TransformPipeline that orchestrates LLM message compression through a series of configurable transforms. Whether you need to reorder the default compression steps, disable specific transforms like CacheAligner, or implement entirely custom compression strategies, you can customize the Headroom transform pipeline using the public API exposed in headroom/transforms/pipeline.py. This guide demonstrates four proven methods to modify pipeline behavior, from configuration tweaks to custom class implementations.
Understanding the TransformPipeline Architecture
The TransformPipeline class in headroom/transforms/pipeline.py serves as the main orchestrator, iterating over a list of Transform objects while measuring token counts and recording metrics. According to the source code, customizing the pipeline follows this four-step flow:
- Instantiate
HeadroomConfig(or a subclass) and toggle individual transforms via its boolean fields likecache_aligner.enabled. - Pass a custom list of
Transformobjects to theTransformPipelineconstructor to bypass the default builder. - Optionally provide a
Provider(e.g.,OpenAIProvider) to supply model-specific tokenizers. - Run
applyorsimulateon your messages to execute or preview transformations.
The default pipeline constructs transforms via _build_default_transforms (lines 99-133 of pipeline.py), which typically returns CacheAligner → ContentRouter → optional ML compressor → RollingWindow. Each transform inherits from the abstract Transform base class defined in headroom/transforms/base.py, implementing should_apply and apply methods.
Method 1: Replace the Default Transform List
To completely customize the Headroom transform pipeline ordering or composition, pass a custom list to the TransformPipeline constructor. When you provide the transforms argument, the initialization logic in headroom/transforms/pipeline.py (lines 84-88) skips the default _build_default_transforms method and uses your exact ordering.
from headroom.transforms import SmartCrusher, CacheAligner, RollingWindow
from headroom.transforms.pipeline import TransformPipeline
# Build a pipeline that runs SmartCrusher before CacheAligner
custom_transforms = [
SmartCrusher(), # Compress JSON tool results first
CacheAligner(), # Then detect volatile system content
RollingWindow(), # Finally drop old messages
]
pipeline = TransformPipeline(transforms=custom_transforms)
result = pipeline.apply(messages, model="gpt-4")
Method 2: Toggle Individual Transforms via Configuration
For finer control without replacing the entire pipeline, use HeadroomConfig to enable or disable specific transforms. Each transform checks its configuration flag in should_apply before executing, as implemented in headroom/transforms/cache_aligner.py (lines 54-59).
from headroom import TransformPipeline, HeadroomConfig
cfg = HeadroomConfig()
cfg.cache_aligner.enabled = False # Disable CacheAligner detection
cfg.content_router.enabled = True # Keep ContentRouter active
pipeline = TransformPipeline(config=cfg)
You can also use the convenience factory create_pipeline in headroom/pipeline.py (lines 498-516) to build a pipeline with a custom CacheAlignerConfig.
Method 3: Create Custom Transform Classes
To extend functionality, subclass Transform from headroom/transforms/base.py and implement the required interface. Custom transforms automatically participate in logging, timing, and the circuit-breaker safety net controlled by HEADROOM_PIPELINE_BREAKER_THRESHOLD and HEADROOM_PIPELINE_BREAKER_COOLDOWN_S environment variables.
from headroom.transforms.base import Transform
from headroom.transforms.pipeline import TransformResult
class UppercaseTransform(Transform):
name = "uppercase"
def should_apply(self, messages, tokenizer, **kwargs):
return kwargs.get("uppercase", False)
def apply(self, messages, tokenizer, **kwargs):
new_msgs = [
{**msg, "content": msg["content"].upper() if isinstance(msg.get("content"), str) else msg["content"]}
for msg in messages
]
return TransformResult(
messages=new_msgs,
tokens_before=tokenizer.count_messages(messages),
tokens_after=tokenizer.count_messages(new_msgs),
transforms_applied=[self.name],
)
# Inject the custom transform
pipeline = TransformPipeline(transforms=[UppercaseTransform(), SmartCrusher()])
result = pipeline.apply(messages, model="gpt-4", uppercase=True)
Method 4: Simulate Changes Without Side Effects
The simulate method allows you to preview token savings without mutating the original message list. According to the source in headroom/transforms/pipeline.py (lines 77-96), simulate calls apply with record_metrics=False on a deep-copied message list.
pipeline = TransformPipeline()
sim_result = pipeline.simulate(messages, model="gpt-4")
print(f"Would have saved {sim_result.tokens_before - sim_result.tokens_after} tokens")
Summary
- Pass custom transforms: Supply a list to
TransformPipeline(transforms=[...])to replace the default ordering built by_build_default_transformsinheadroom/transforms/pipeline.py. - Toggle via config: Use
HeadroomConfigflags likecache_aligner.enabledto disable specific transforms without subclassing or replacing the pipeline. - Extend the base class: Subclass
Transformfromheadroom/transforms/base.pyto implement custom compression logic that integrates with metrics and circuit breakers. - Simulate safely: Use
pipeline.simulate()to preview token savings viaTransformResultwithout modifying original messages. - Source locations: Core orchestration resides in
headroom/transforms/pipeline.py, base contracts inheadroom/transforms/base.py, and configuration inheadroom/config.py.
Frequently Asked Questions
How do I change the order of transforms in the Headroom pipeline?
Pass a custom list to the TransformPipeline constructor using the transforms parameter. When you provide this argument, the initialization logic in headroom/transforms/pipeline.py (lines 84-88) automatically skips the default _build_default_transforms method and uses your exact ordering instead.
Can I disable only the CacheAligner transform while keeping others active?
Yes. Instantiate HeadroomConfig and set cfg.cache_aligner.enabled = False before passing it to TransformPipeline(config=cfg). The CacheAligner.should_apply method checks this boolean flag at lines 54-59 of headroom/transforms/cache_aligner.py, causing it to skip execution while other transforms remain active.
What methods must a custom transform implement?
Your class must inherit from Transform in headroom/transforms/base.py and implement two methods: should_apply(self, messages, tokenizer, **kwargs) returning a boolean, and apply(self, messages, tokenizer, **kwargs) returning a TransformResult object containing the modified messages, token counts, and a list of applied transform names.
How do I test token savings without modifying my original messages?
Call pipeline.simulate(messages, model="...") instead of apply(). This method creates a deep copy of your messages and runs the pipeline without side effects, returning token counts and transformation metrics via TransformResult while leaving your original data unchanged.
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 →