Skip to content

Commit eb72707

Browse files
committed
feat: add detached mode capabilities
1 parent 2170a1b commit eb72707

16 files changed

Lines changed: 776 additions & 17 deletions

docs/content/docs/configuration.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ headroom proxy --learn --min-evidence 3
221221
| `HEADROOM_BUDGET` | Daily budget limit in USD | -- |
222222
| `HEADROOM_TELEMETRY` | Set to `off` to disable anonymous telemetry | enabled |
223223
| `HEADROOM_STATELESS` | Set to `true` to disable filesystem writes | `false` |
224+
| `HEADROOM_DETACHED_PROFILE` | Detached-mode capability policy: `strict`, `lenient`, or `silent` | `lenient` |
224225
| `HEADROOM_MODEL_LIMITS` | Custom model config (JSON string or file path) | -- |
225226
| `HEADROOM_BASE_URL` | Base URL of the Headroom proxy (TypeScript SDK) | `http://localhost:8787` |
226227
| `HEADROOM_API_KEY` | API key for Headroom Cloud authentication | -- |
@@ -248,6 +249,11 @@ page for the full bucket table, plugin-author guidance, and the Docker
248249
naming overlap note (`HEADROOM_WORKSPACE` is *not* the same as
249250
`HEADROOM_WORKSPACE_DIR`).
250251

252+
For deployments where the workspace root is intentionally unavailable or
253+
read-only, see [Detached Mode](/docs/detached-mode). It exposes the exact
254+
capability matrix through `/capabilities`, `/health`, `/stats`, and
255+
`headroom_feature_enabled` Prometheus gauges.
256+
251257
## Custom Model Configuration
252258

253259
Configure context limits and pricing for new or custom models:
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
title: Detached Mode
3+
description: Run Headroom in containers, CI, serverless, or read-only deployments with explicit capability degradation.
4+
---
5+
6+
Detached mode is Headroom's contract for deployments where local writable state is absent or intentionally disabled.
7+
8+
Use it for stateless containers, read-only filesystems, ephemeral CI runners, serverless processes, and load-balanced fleets where local process state should not be treated as durable.
9+
10+
## Enable detached mode
11+
12+
```bash
13+
HEADROOM_STATELESS=true headroom proxy
14+
```
15+
16+
or:
17+
18+
```bash
19+
headroom proxy --stateless
20+
```
21+
22+
`--stateless` disables avoidable filesystem writes such as proxy file logging, local TOIN persistence, memory, learning, and telemetry beacon lock files. Request handling and compression continue to run.
23+
24+
## Profiles
25+
26+
Set `HEADROOM_DETACHED_PROFILE` or pass `--detached-profile`:
27+
28+
| Profile | Behavior |
29+
|---|---|
30+
| `lenient` | Default. Start the proxy and log the capability matrix when detached. |
31+
| `strict` | Refuse startup when an explicitly enabled required local-state feature would degrade, such as `--memory` without available local state or a remote backend. |
32+
| `silent` | Start the proxy without startup degradation logs. `/capabilities`, `/stats`, `/health`, and `/metrics` still expose the matrix. |
33+
34+
```bash
35+
HEADROOM_STATELESS=true \
36+
HEADROOM_DETACHED_PROFILE=strict \
37+
headroom proxy
38+
```
39+
40+
## Capability endpoint
41+
42+
```bash
43+
curl http://localhost:8787/capabilities
44+
```
45+
46+
The response includes `detached`, `profile`, local-state availability, every feature's local-state dependency, current state, degradation mode, and strict-mode violations.
47+
48+
## Metrics
49+
50+
The Prometheus endpoint exposes one gauge per feature:
51+
52+
```text
53+
headroom_feature_enabled{feature="compression",state="full",degradation="full",dependency="none"} 1
54+
headroom_feature_enabled{feature="session_aggregation",state="disabled",degradation="disabled",dependency="required"} 0
55+
```
56+
57+
Use this to alert on degraded or disabled capabilities in managed deployments.

docs/content/docs/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"failure-learning",
2525
"---Proxy Server---",
2626
"proxy",
27+
"detached-mode",
2728
"---Integrations---",
2829
"vercel-ai-sdk",
2930
"openai-sdk",

docs/content/docs/metrics.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,13 @@ headroom_latency_seconds_bucket{le="0.1"} 1150
8383
8484
# HELP headroom_cache_hits_total Cache hit counter
8585
headroom_cache_hits_total 456
86+
87+
# HELP headroom_feature_enabled Feature availability after detached-mode capability resolution
88+
headroom_feature_enabled{feature="compression",state="full",degradation="full",dependency="none"} 1
8689
```
8790

91+
`headroom_feature_enabled` mirrors the `/capabilities` payload. Use it to alert when an expected feature is degraded or disabled in detached/stateless deployments.
92+
8893
### Health Check
8994

9095
```bash

docs/content/docs/proxy.mdx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ headroom proxy \
2222

2323
Telemetry is enabled by default. Opt out with `HEADROOM_TELEMETRY=off` or `--no-telemetry`.
2424

25+
For read-only, container, CI, serverless, or load-balanced deployments, use [Detached Mode](/docs/detached-mode) to make local-state degradation explicit:
26+
27+
```bash
28+
headroom proxy --stateless --detached-profile lenient
29+
```
30+
2531
## CLI options
2632

2733
### Core
@@ -47,6 +53,7 @@ Telemetry is enabled by default. Opt out with `HEADROOM_TELEMETRY=off` or `--no-
4753
| `--backend` | `anthropic` | Backend: `anthropic`, `bedrock`, `openrouter`, `anyllm`, or `litellm-<provider>` |
4854
| `--no-telemetry` | `false` | Disable anonymous telemetry |
4955
| `--stateless` | `false` | Disable filesystem writes and keep runtime state in memory |
56+
| `--detached-profile` | `lenient` | Capability policy for detached/stateless deployments: `strict`, `lenient`, or `silent` |
5057

5158
### Context management
5259

@@ -121,6 +128,14 @@ Live session statistics plus durable `persistent_savings` totals. Stored at `~/.
121128
curl http://localhost:8787/stats
122129
```
123130

131+
### `GET /capabilities`
132+
133+
Resolved detached-mode capability matrix for operators and deployment automation.
134+
135+
```bash
136+
curl http://localhost:8787/capabilities
137+
```
138+
124139
### `GET /stats-history`
125140

126141
Durable history with hourly, daily, weekly, and monthly rollups. Powers the `/dashboard` view.

headroom/cli/proxy.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,17 @@ def _selected_context_tool() -> str:
432432
"For containerized / read-only / load-balanced deployments. "
433433
"(env: HEADROOM_STATELESS=true)",
434434
)
435+
@click.option(
436+
"--detached-profile",
437+
type=click.Choice(["strict", "lenient", "silent"], case_sensitive=False),
438+
default=None,
439+
envvar="HEADROOM_DETACHED_PROFILE",
440+
help=(
441+
"Detached-mode capability policy. strict refuses degraded explicitly "
442+
"enabled local-state features; lenient logs degradations; silent only "
443+
"exposes them through API/metrics. Env: HEADROOM_DETACHED_PROFILE."
444+
),
445+
)
435446
@click.pass_context
436447
def proxy(
437448
ctx: click.Context,
@@ -487,6 +498,7 @@ def proxy(
487498
bedrock_profile: str | None,
488499
no_telemetry: bool,
489500
stateless: bool,
501+
detached_profile: str | None,
490502
) -> None:
491503
"""Start the optimization proxy server.
492504
@@ -663,6 +675,10 @@ def proxy(
663675
license_key=license_key,
664676
# Stateless mode: disable all filesystem writes
665677
stateless=is_stateless,
678+
detached_profile=cast(
679+
Literal["strict", "lenient", "silent"],
680+
(detached_profile or os.environ.get("HEADROOM_DETACHED_PROFILE") or "lenient").lower(),
681+
),
666682
# Unit 4: bounded pre-upstream concurrency on the Anthropic HTTP
667683
# path. ``None`` -> HeadroomProxy computes ``max(2, min(8,
668684
# os.cpu_count() or 4))``; ``<= 0`` -> disabled (unbounded).
@@ -824,6 +840,7 @@ def proxy(
824840
GET /livez Process liveness
825841
GET /readyz Traffic readiness
826842
GET /health Aggregate health
843+
GET /capabilities Detached-mode capability matrix
827844
GET /stats Detailed statistics
828845
GET /stats-history Durable compression history + display session
829846
GET /metrics Prometheus metrics

0 commit comments

Comments
 (0)