Configuration
All configuration options for the Headroom Python and TypeScript SDKs, proxy server, and per-request overrides.
Headroom can be configured via the SDK constructor, proxy command line, environment variables, or per-request overrides.
Runtime Rollout Channels
Headroom uses rollout channels to control which behaviors an already-installed artifact may expose. They do not select a package or released version.
| Variable | Default | Purpose |
|---|---|---|
HEADROOM_ROLLOUT_CHANNEL | stable | Selects stable, beta, canary, or dev. |
HEADROOM_FEATURES | unset | Comma-separated feature names to request explicitly. |
HEADROOM_DISABLE_FEATURES | unset | Comma-separated feature names to force off. Disable wins over every enable path. |
HEADROOM_UNSAFE_ALLOW_UNSTABLE_FEATURES | unset | Break-glass override for emergency mitigation only. |
See Runtime Rollouts for policy, provenance, and contributor rules. If Codex history disappeared after using an older wrapper, see Recover Codex State before wrapping Codex again.
SDK Modes (default_mode / headroom_mode)
These modes apply to SDK usage via HeadroomClient(default_mode=...) or per-request headroom_mode=.... They are not the same as the proxy --mode flag.
| Mode | Behavior | Use Case |
|---|---|---|
audit | Observes and logs, no modifications | Production monitoring, baseline measurement |
optimize | Applies safe, deterministic transforms | Production optimization |
simulate | Returns plan without API call | Testing, cost estimation |
Proxy
--modeis a separate axis:headroom proxy --mode token(maximize compression) or--mode cache(freeze prior turns for prefix-cache stability). The proxy does not acceptaudit,optimize, orsimulate.
SDK Configuration
import { } from 'headroom-ai';
// Reads from HEADROOM_BASE_URL and HEADROOM_API_KEY automatically
const = new ();
// Or configure explicitly
const = new ({
: 'http://localhost:8787',
: 'your-api-key',
: 30_000,
: true,
: 2,
});from headroom import HeadroomClient, OpenAIProvider
from openai import OpenAI
client = HeadroomClient(
original_client=OpenAI(),
provider=OpenAIProvider(),
# Mode: "audit" (observe only) or "optimize" (apply transforms)
default_mode="optimize",
# Enable provider-specific cache optimization
enable_cache_optimizer=True,
# Enable query-level semantic caching
enable_semantic_cache=False,
# Override default context limits per model
model_context_limits={
"gpt-4o": 128000,
"gpt-4o-mini": 128000,
},
# Database location (defaults to temp directory)
# store_url="sqlite:////absolute/path/to/headroom.db",
)Per-Request Overrides
Override configuration for individual requests:
import { } from 'headroom-ai';
const = await (messages, {
: 'gpt-4o',
: 100_000,
: 15_000,
});response = client.chat.completions.create(
model="gpt-4o",
messages=[...],
# Override mode for this request
headroom_mode="audit",
# Reserve more tokens for output
headroom_output_buffer_tokens=8000,
# Keep last N turns (don't compress)
headroom_keep_turns=5,
# Skip compression for specific tools
headroom_tool_profiles={
"important_tool": {"skip_compression": True}
},
)Proxy upstream override (x-headroom-base-url)
When using the proxy, send the x-headroom-base-url request header to route a
single request to a different upstream instead of the configured provider URL.
This lets a client that speaks a provider's wire format authenticate against a
compatible gateway (for example an OpenAI-compatible endpoint, or an
Anthropic-Messages gateway such as OpenCode Zen) without changing the proxy
configuration.
The header is honored by the OpenAI-compatible routes, the Anthropic Messages
route (POST /v1/messages), and the generic passthrough route. The proxy
forwards the request to <x-headroom-base-url> + the original request path
(e.g. /v1/messages). An empty or whitespace-only value is ignored and the
configured upstream is used.
curl http://127.0.0.1:8787/v1/messages \
-H "content-type: application/json" \
-H "anthropic-version: 2023-06-01" \
-H "x-headroom-base-url: https://opencode.ai/zen/go" \
-H "x-api-key: <gateway-api-key>" \
-d '{"model":"glm-5.2","max_tokens":16,"messages":[{"role":"user","content":"hi"}]}'When HEADROOM_STRIP_INTERNAL_HEADERS is enabled (the default), the proxy
reads this header for routing and then strips it before forwarding upstream.
Configured secret headers are not sent to arbitrary upstreams
ANTHROPIC_TARGET_API_HEADERS / OPENAI_TARGET_API_HEADERS hold operator
secrets. Because x-headroom-base-url is chosen by the client, those headers
are only attached when the destination is one the operator designated:
- a host in the configured provider targets (
ANTHROPIC_TARGET_API_URL,OPENAI_TARGET_API_URL, and the Gemini/Vertex/Cloud Code equivalents), or - a host listed in
HEADROOM_UPSTREAM_ALLOWED_HOSTS(comma-separated).
A request to any other upstream is still proxied — it just does not carry
your configured headers, and the proxy logs
upstream_extra_headers_withheld host=<host> once per host. If you route to a
gateway via this header and need your configured headers to reach it, add its
host to HEADROOM_UPSTREAM_ALLOWED_HOSTS:
export HEADROOM_UPSTREAM_ALLOWED_HOSTS="gateway.internal,api.example-gateway.ai"Matching is on the parsed hostname and is exact — no wildcards — so
api.anthropic.com.evil.example and https://api.anthropic.com@evil.example
do not match api.anthropic.com.
SmartCrusher Configuration
Fine-tune JSON compression behavior:
from headroom.transforms import SmartCrusherConfig
config = SmartCrusherConfig(
# Maximum items to keep after compression
max_items_after_crush=15,
# Minimum tokens before applying compression
min_tokens_to_crush=200,
# Fraction of items always kept from the start/end
first_fraction=0.3,
last_fraction=0.15,
# Variance threshold for statistical analysis
variance_threshold=2.0,
)CacheAligner Configuration
Control prefix stabilization for provider cache hit rates:
from headroom.transforms import CacheAlignerConfig
config = CacheAlignerConfig(
# Enable/disable cache alignment
enabled=True,
# Patterns to extract from system prompt
dynamic_patterns=[
r"Today is \w+ \d+, \d{4}",
r"Current time: .*",
],
)Context Window Management
Context management is now automatic. Use per-request overrides to control behavior:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
# Reserve tokens for model output
headroom_output_buffer_tokens=4000,
# Keep last N turns uncompressed
headroom_keep_turns=3,
)The RollingWindowConfig, IntelligentContextConfig, and ScoringWeights classes are no longer part of Headroom. Context management now happens automatically inside the pipeline (live-zone-only compression).
Claude 1M context window (headroom wrap claude --1m)
headroom wrap claude --1m opts a Claude Code session into Anthropic's 1M-token context window by selecting a [1m]-suffixed model id, which makes Claude Code send the context-1m beta header. The model that --1m targets is resolved in this order:
- an explicit
--model/ANTHROPIC_MODELvalue (used as-is, with a[1m]suffix appended when missing), - otherwise
HEADROOM_1M_MODEL, when set, - otherwise the built-in default (currently
claude-opus-5).
Set HEADROOM_1M_MODEL to point --1m at a specific model without pinning ANTHROPIC_MODEL globally, so the default can follow a new Opus generation without a code change:
# Route --1m at a specific model for this shell / session
export HEADROOM_1M_MODEL=claude-opus-5
headroom wrap claude --1mHEADROOM_1M_MODEL is a fallback only: an explicit --model or ANTHROPIC_MODEL always wins. The value may be given with or without the [1m] suffix; both claude-opus-5 and claude-opus-5[1m] are accepted, and the suffix is added when absent.
Pipeline Extensions
Use a headroom.pipeline_extension entry point when you need to normalize or annotate requests before they leave Headroom. The PRE_SEND stage is the right place for provider-specific request cleanup, such as turning content: null into content: "" for upstreams that reject OpenAI-spec tool-call messages.
from headroom.pipeline import PipelineEvent, PipelineStage
class NormalizeNullContent:
def on_pipeline_event(self, event: PipelineEvent) -> PipelineEvent:
if event.stage is not PipelineStage.PRE_SEND or not event.messages:
return event
for message in event.messages:
if (
message.get("role") == "assistant"
and message.get("content") is None
and message.get("tool_calls")
):
message["content"] = ""
return eventRegister it in pyproject.toml:
[project.entry-points."headroom.pipeline_extension"]
normalize_null_content = "my_pkg.normalize:NormalizeNullContent"If the upstream base URL itself must vary per request, use the x-headroom-base-url override header in addition to the normalization hook.
Proxy Configuration
Command Line Options
headroom proxy \
--port 8787 \ # Port to listen on
--host 0.0.0.0 \ # Host to bind to
--mode token \ # token compression mode; use cache for prefix-cache stability
--budget 10.00 \ # Daily budget limit in USD
--log-file headroom.jsonl # Log file pathFeature Flags
# Disable optimization (passthrough mode)
headroom proxy --no-optimize
# Disable semantic caching
headroom proxy --no-cache
# Preserve provider prefix-cache stability instead of maximizing token removal
headroom proxy --mode cache
# Enable memory and live learning
headroom proxy --memory
headroom proxy --learn --min-evidence 3Environment Variables
| Variable | Description | Default |
|---|---|---|
HEADROOM_HOST | Proxy bind host | 127.0.0.1 |
HEADROOM_PORT | Proxy bind port | 8787 |
HEADROOM_MODE | Proxy optimization mode: token or cache | cache |
HEADROOM_WORKERS | Uvicorn worker count | 1 |
HEADROOM_LIMIT_CONCURRENCY | Maximum concurrent connections before 503 | 1000 |
HEADROOM_MAX_CONNECTIONS | Maximum upstream HTTP connections | 500 |
HEADROOM_MAX_KEEPALIVE | Maximum upstream keep-alive connections | 100 |
HEADROOM_KEEPALIVE_EXPIRY | Seconds an idle upstream keep-alive connection is kept open | 90 |
HEADROOM_HTTP_PROXY | HTTP proxy URL for upstream provider requests only; HTTPS provider APIs use CONNECT | -- |
HEADROOM_BUDGET | Daily budget limit in USD | -- |
HEADROOM_TELEMETRY | Set to on for local-only usage stats (powers your own /stats and dashboard; nothing is sent externally) | off |
HEADROOM_STATELESS | Set to true to disable filesystem writes | false |
HEADROOM_MODEL_LIMITS | Custom model config (JSON string or file path) | -- |
HEADROOM_BASE_URL | Base URL of the Headroom proxy (TypeScript SDK) | http://localhost:8787 |
HEADROOM_API_KEY | Optional API key for authenticated Headroom endpoints (TypeScript SDK) | -- |
HEADROOM_CONFIG_DIR | Canonical config (read-mostly) root. Derives models.json and per-plugin config paths when set. | ~/.headroom/config |
HEADROOM_WORKSPACE_DIR | Canonical workspace (read-write state) root. Derives savings, memory DB, logs, TOIN, subscription state, and more when set. | ~/.headroom |
HEADROOM_SAVINGS_PATH | Override persistent savings file location. Always wins when set. | derived from ${HEADROOM_WORKSPACE_DIR} |
HEADROOM_TOIN_PATH | Override TOIN telemetry file location. Always wins when set. | derived from ${HEADROOM_WORKSPACE_DIR} |
HEADROOM_SUBSCRIPTION_STATE_PATH | Override subscription tracker state file. Always wins when set. | derived from ${HEADROOM_WORKSPACE_DIR} |
HEADROOM_PERIODIC_TOIN_STATS | Controls periodic TOIN stats logging in long-lived proxy workers. Set to 0, false, off, or no to disable the 5-minute stats loop without disabling TOIN learning or request-time feedback. | true |
HEADROOM_MEMORY_INJECTION_MODE | Memory-context routing mode: live_zone_tail (default) or disabled. The legacy system_prompt mode was retired by PR-A2; supplying it raises. | live_zone_tail |
HEADROOM_PROXY_PYTHON_FORWARDER_MODE | Python forwarder serialization mode. byte_faithful (default) forwards original request bytes verbatim when no transform mutated the body and re-serializes canonically only when needed — keeps Anthropic prompt-cache hit-rate intact. legacy_json_kwarg is an explicit operator opt-in for emergency rollback to the historical httpx ... json=body behavior. NOT a fallback — only flip on explicit operator decision. | byte_faithful |
HEADROOM_STRIP_INTERNAL_HEADERS | Python proxy: whether to strip internal x-headroom-* request headers (e.g. x-headroom-bypass, x-headroom-mode, x-headroom-user-id, x-headroom-stack, x-headroom-base-url) before every upstream forwarder call (PR-A5, fixes P5-49). enabled (default) stops fingerprinting / leakage. disabled is an explicit operator opt-in for diagnostic shadow tracing — NOT a fallback. Inbound reads of these headers (bypass gating, memory user-id resolution) are unaffected because they read request.headers directly. | enabled |
HEADROOM_PROXY_STRIP_INTERNAL_HEADERS | Rust proxy: same policy as HEADROOM_STRIP_INTERNAL_HEADERS but for the Rust transparent proxy. Stripping happens inside build_forward_request_headers so both HTTP and WebSocket upstream calls are gated by one flag. enabled default; disabled operator opt-in for diagnostic shadow tracing. Response-side X-Headroom-* injection (e.g. x-headroom-tokens-saved) is unrelated and stays. | enabled |
HEADROOM_EMBEDDER_RUNTIME | Set to pytorch_mps to run the memory embedder via the torch sentence-transformers backend on the Apple GPU (MPS). Only engages when Apple MPS is actually available; otherwise it logs a warning and uses the existing default embedder selection path. pytorch_mps is the only accepted value. Requires the [pytorch-mps] extra. See Memory. | default embedder selection |
ORT_DYLIB_PATH | Path to the ONNX Runtime shared library loaded by the Rust core (magika detection, fastembed embeddings), which loads ORT dynamically on every platform. Auto-pinned at import headroom to the library inside the onnxruntime pip package (onnxruntime.dll / libonnxruntime.so* / libonnxruntime*.dylib); set it yourself to override. Without a pin, ML detection degrades to the non-ONNX tiers — and on Windows the bare DLL search can resolve to the Windows ML System32 build (1.17.x on Win11 24H2+), which deadlocks ONNX session init — see Troubleshooting. | auto-pinned |
HEADROOM_MAGIKA_INIT_TIMEOUT_SECS | Upper bound (integer seconds, > 0) on magika's one-time ONNX session init in the Rust detection chain. On timeout the init error is cached and detection uses the non-ML fallback tiers for the rest of the process; a warning is logged. Safety net for environments where the dylib pin above does not apply. | 5 |
HEADROOM_REQUEST_TIMEOUT | Request timeout in seconds | 300 |
HEADROOM_BETA_HEADER_STICKY | Controls per-session anthropic-beta / OpenAI-Beta re-echo. enabled (default): the proxy unions beta tokens across turns within a session — if the client sends a token in turn N and omits it in turn N+1, the proxy re-injects it to preserve prefix-cache stability. disabled: the client's value is forwarded verbatim with no accumulation. Any other value raises at request time. See Session Beta Header Tracking. | enabled |
HEADROOM_BETA_TRACKER_MAX_SESSIONS | LRU capacity of the in-memory session beta tracker. Once full, the oldest session entry is evicted. | 1000 |
HEADROOM_PROXY_BETA_HEADER_STICKY | Rust proxy: same per-conversation beta-token union as HEADROOM_BETA_HEADER_STICKY, applied to anthropic-beta / openai-beta on the intercepted /v1/messages, /v1/chat/completions, and /v1/responses routes. Requires the compression interceptor (HEADROOM_PROXY_COMPRESSION=1) — with it off the Rust proxy is a strict byte-pipe and this flag has no effect (startup warns). Unlike the Python tracker (keyed on model + system prompt), sessions are keyed per conversation, shared with the cache-drift detector — parallel conversations never inherit each other's tokens. enabled default; disabled forwards the client value verbatim and keeps no state. Tracker capacity is fixed at 1000 sessions. | enabled |
HEADROOM_MODEL_ROUTER_ENABLED | Enable cost-aware model routing. 1/true/yes/on/enabled turns it on and requires HEADROOM_MODEL_ROUTES. See Cost-aware model routing. | off |
HEADROOM_MODEL_ROUTES | JSON array of ordered routing rules for cost-aware model routing (schema below). | -- |
HEADROOM_THINKING_COMPACT | Compact plain-text reasoning that models re-send every turn (Kimi/GLM/DeepSeek reasoning_content / inline <think>): Kompress it on warm turns, drop it on cold turns. No-op for Claude/Codex/OpenAI (encrypted reasoning). See Cold-prefix hook. | off |
HEADROOM_THINKING_COMPACT_KEEP_LAST | Most-recent assistant turns whose reasoning is left intact (the active reasoning the model still uses). Only applies with HEADROOM_THINKING_COMPACT. | 1 |
HEADROOM_COLD_RECOMPACT | On a confirmed-cold turn (idle past the real cache TTL), recompact the whole prefix — cross-turn dedupe + superseded-read drop + lossless folds — instead of forwarding a byte-identical prefix to a dead cache. Warm turns unchanged. Pair with HEADROOM_DEDUPE. See Cold-prefix hook. | off |
HEADROOM_DEDUPE | Whole-conversation verbatim cross-turn dedup in the router (cache-safe, information-preserving via retrieval markers). Superseded-read drop + lossless folds run without it; this adds verbatim dedup. | off |
HEADROOM_CACHE_TTL_LEARN | Append per-turn cache-outcome observations (provider, model, idle, hit/miss) to cache_ttl_observations.jsonl for the offline headroom-cache-ttl learner. Observation-only (no request-behavior change); respects HEADROOM_STATELESS; the log is size-bounded. | off |
HEADROOM_KOMPRESS_ENDPOINT / HEADROOM_KOMPRESS_ENDPOINT_TOKEN | Offload ML compression (Kompress) to a remote endpoint instead of the local ONNX model — used by reasoning compaction and the router when set. | -- |
HEADROOM_1M_MODEL | Fallback model that headroom wrap claude --1m targets when neither --model nor ANTHROPIC_MODEL is set. Accepts the id with or without the [1m] suffix (added when absent); an explicit --model / ANTHROPIC_MODEL always wins. See Claude 1M context window. | claude-opus-5 |
For provider-only proxying, prefer HEADROOM_HTTP_PROXY over process-wide variables such as HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, or NO_PROXY. HTTPX reads those global variables, but Headroom also passes them through to tool executions.
Cold-prefix hook & reasoning compaction
Two related optimizations target tokens that agent harnesses re-send every turn: model reasoning (re-billed as input on Kimi/GLM/DeepSeek and on Claude 4.6+), and the prefix itself once its prompt cache has lapsed. All flags below are off by default — the base proxy is unchanged until you opt in.
What to set for what:
| Goal | Set | Notes |
|---|---|---|
| Shrink Kimi/GLM/DeepSeek reasoning re-sent each turn | HEADROOM_THINKING_COMPACT=1 (+ HEADROOM_KOMPRESS_ENDPOINT for the best ratio) | Warm turns Kompress the reasoning; cold turns drop it. No-op for Claude/Codex/OpenAI (their reasoning is an encrypted handle, already cheap on resend). |
| Recompact a dead-cache prefix instead of re-sending it whole | HEADROOM_COLD_RECOMPACT=1 (+ HEADROOM_DEDUPE=1) | Fires only when the cache has genuinely lapsed. Works in both cache and token mode. |
| Learn each provider's real cache TTL | HEADROOM_CACHE_TTL_LEARN=1, then run the headroom-cache-ttl estimator periodically | Sharpens cold detection for providers that don't expose a TTL (Kimi/OpenAI). |
How cold detection knows the TTL. A wrong "cold" call would recompact a warm prefix and bust the cache, so the TTL must be right:
- Claude Code: read exactly, from the request's
cache_control.ttlplus CC's own controls —ENABLE_PROMPT_CACHING_1H(1h),FORCE_PROMPT_CACHING_5M(5m), andDISABLE_PROMPT_CACHING(+ per-modelDISABLE_PROMPT_CACHING_<FAMILY>), which turns caching off and makes every turn a free recompaction candidate. - Kimi / OpenAI / Codex: they don't expose a TTL, so detection uses a
conservative default until the learner (
HEADROOM_CACHE_TTL_LEARN+ theheadroom-cache-ttlplugin) fills in the real value from observed hits/misses.
Can these be on by default?
HEADROOM_THINKING_COMPACT— stays opt-in. It rewrites model inputs (reasoning the model actively uses) and depends on Kompress, so its quality / latency trade should be a deliberate choice.HEADROOM_COLD_RECOMPACT— opt-in today; a candidate to default for Claude Code once TTL detection is field-validated. It only fires on confirmed-cold turns and recompacts losslessly, but a mis-read TTL would bust a warm cache (expensive), so it waits for confidence. For Kimi/OpenAI it should stay opt-in until the learner has data.HEADROOM_CACHE_TTL_LEARN— the safest to default on: observation-only, a size-bounded local log, and it respectsHEADROOM_STATELESS. Kept opt-in for now so nothing is written to disk unasked.
Cost-aware model routing
Complementary to content compression, Headroom can rewrite the upstream model per request to stretch quota and control spend, for example by sending small, tool-free requests to a cheaper model. Routing is opt-in and disabled by default, so behavior is unchanged unless you configure it.
Enable it with HEADROOM_MODEL_ROUTER_ENABLED=1 and declare ordered rules in HEADROOM_MODEL_ROUTES (a JSON array). The router evaluates rules top to bottom and the first rule whose conditions all match wins; every decision is logged with a reason so routing stays observable. Each rule object supports:
| Field | Type | Meaning |
|---|---|---|
to_model | string (required) | Model to route to when the rule matches. |
max_input_tokens | integer | Match only when the estimated input size is at or below this. |
min_input_tokens | integer | Match only when the estimated input size is at or above this. |
require_no_tools | boolean | Match only when the request declares no tools (a proxy for low-risk work). |
from_models | list of strings | Restrict the rule to these source models. Omit for any source model. |
name | string | Label surfaced in the decision log. |
export HEADROOM_MODEL_ROUTER_ENABLED=1
export HEADROOM_MODEL_ROUTES='[
{"name": "small-no-tools", "max_input_tokens": 4000, "require_no_tools": true,
"from_models": ["claude-sonnet-4-6"], "to_model": "claude-haiku-4-5"}
]'Notes:
- Input size is a fast, tokenizer-free estimate over the messages, tools, and top-level
systemprompt, meant for tier selection rather than exact accounting. - A malformed rule fails open: it is skipped (never silently widened), and the rest of the rules still apply.
- Routing is skipped for byte-faithful passthrough requests (
x-headroom-bypass: trueorx-headroom-mode: passthrough), so those are never model-rewritten. - Routing currently applies on the Anthropic
/v1/messagespath.
Session Beta Header Tracking
When running as a proxy, Headroom maintains a per-session union of anthropic-beta (and OpenAI-Beta) tokens via SessionBetaTracker. The session key is derived from the x-headroom-session-id header if present, otherwise from md5(model + system_prompt[:500])[:16] — stable across turns of the same conversation.
Why: clients such as Claude Code and Codex CLI may drop a beta token between consecutive turns. Because anthropic-beta is part of the request bytes that determine the upstream prefix-cache key, a dropped token would bust the cache mid-conversation. The tracker re-injects any token seen earlier in the session so the cache key stays stable.
Trade-off: once the proxy has seen a beta token in a session it will continue re-sending it for the rest of that session, even if the client stops including it. Stopping the token on the client side alone is not sufficient — the proxy re-injects it. Set HEADROOM_BETA_HEADER_STICKY=disabled to pass the client's anthropic-beta value verbatim and bypass this accumulation.
# Disable sticky beta re-echo
export HEADROOM_BETA_HEADER_STICKY=disabled
headroom proxy ...Note: disabling sticky mode may reduce prefix-cache hit rates for clients that legitimately drop-and-re-add beta tokens across turns.
Filesystem Contract
Headroom resolves every on-disk resource through a two-root model
(HEADROOM_CONFIG_DIR + HEADROOM_WORKSPACE_DIR) with additive
precedence rules: explicit argument > per-resource env var > derived
from canonical root > default. Every legacy env var continues to work
unchanged.
See the Filesystem Contract
page for the full bucket table, plugin-author guidance, and the Docker
naming overlap note (HEADROOM_WORKSPACE is not the same as
HEADROOM_WORKSPACE_DIR).
Custom Model Configuration
Configure context limits and pricing for new or custom models:
{
"anthropic": {
"context_limits": {
"claude-4-opus-20250301": 200000,
"claude-custom-finetune": 128000
},
"pricing": {
"claude-4-opus-20250301": {
"input": 15.00,
"output": 75.00,
"cached_input": 1.50
}
}
},
"openai": {
"context_limits": {
"gpt-5": 256000,
"ft:gpt-4o:my-org": 128000
}
}
}Save as ${HEADROOM_CONFIG_DIR}/models.json (defaults to
~/.headroom/config/models.json), or set HEADROOM_MODEL_LIMITS to a
JSON string or file path. Installs that still have
~/.headroom/models.json (the legacy location) continue to work.
Settings are resolved in this order (later overrides earlier):
- Built-in defaults
${HEADROOM_CONFIG_DIR}/models.json(new canonical location); falls back to~/.headroom/models.json(legacy) when the canonical file is absentHEADROOM_MODEL_LIMITSenvironment variable- SDK constructor arguments
Pattern-Based Inference
Unknown models are automatically inferred from naming patterns:
| Pattern | Inferred Settings |
|---|---|
*opus* | 200K context, Opus-tier pricing |
*sonnet* | 200K context, Sonnet-tier pricing |
*haiku* | 200K context, Haiku-tier pricing |
gpt-4o* | 128K context, GPT-4o pricing |
o1*, o3* | 200K context, reasoning model pricing |
Provider-Specific Settings
from headroom import OpenAIProvider
provider = OpenAIProvider(
enable_prefix_caching=True,
)from headroom import AnthropicProvider
provider = AnthropicProvider(
enable_cache_control=True,
)from headroom.providers import GoogleProvider
provider = GoogleProvider(
enable_context_caching=True,
)Tool Profiles
Skip or customize compression for specific tools:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
headroom_tool_profiles={
"important_tool": {"skip_compression": True},
"search_tool": {"max_items_after_crush": 25},
},
)Configuration Precedence
Settings are applied in this order (later overrides earlier):
- Default values
- Environment variables
- SDK constructor arguments
- Per-request overrides
Validation
Validate your configuration at startup:
result = client.validate_setup()
if not result["valid"]:
print("Configuration issues:")
for issue in result["issues"]:
print(f" - {issue}")