Context Compaction
Long conversations eventually exceed a model’s context window. The Responses API tracks how much of each model’s window a conversation is using and lets operators configure a threshold at which older turns get summarised into a single "compaction" entry, freeing room for the conversation to continue.
|
Status: this release ships the configuration only
The runtime features that consume this config (an explicit |
Configuration
Operators configure context limits and the compaction threshold via a single JSON document, delivered as one of:
-
CONTEXT_CONFIG_FILE: path to a JSON file. Preferred on Kubernetes: mount as a ConfigMap. -
CONTEXT_CONFIG_JSON: inline JSON string. Used when_FILEis unset.
If both are set, _FILE wins. If neither is set, built-in defaults apply.
A malformed config (invalid JSON, out-of-range percent, non-positive context) fails pod startup loudly. A misconfigured operator wants to know about it at boot, not when the first request lands.
Schema
{
"auto_trigger_enabled": true,
"default": {
"context": 32000,
"autocompact_at": 80,
"target_size_pct": 50
},
"models": {
"qwen3-32b": { "context": 10000 },
"gpt-oss-120b": { "context": 128000, "autocompact_at": 75, "target_size_pct": 40 }
}
}
| Field | Type | Range | Description |
|---|---|---|---|
|
bool |
— |
Deployment-wide on/off for the post-response auto-trigger. Default |
|
int |
|
Built-in fallback context-window size, in tokens. |
|
int |
|
Percent of |
|
int |
|
Approximate target compacted size, as a percent of |
|
object |
— |
Per-model override. Any subset of the three fields above. Names match the request’s |
All fields inside default and inside any models entry are optional. Omitted fields fall through the resolution chain below.
Resolution order
For each field on each request, the effective value is resolved per-field in this order:
-
models[<request.model>][<field>]: if the operator set it. -
Inference backend catalog value for the request’s model, if the catalog is reachable and reports that field (only
contexttoday). -
default[<field>]: if the operator set it. -
Built-in default (
context=32000,autocompact_at=80,target_size_pct=50).
The catalog comes from INFERENCE_MODELS_AVAILABLE_URL. On deployments where it’s directly reachable (Pharia AI), operators can omit per-model entries and let the catalog fill in context. On deployments where the AI gateway in front of inference does not expose the catalog (Platform), the chain skips step 2 and operators must list any model they care about; unrecognised models fall through to default.
autocompact_at and target_size_pct are policy, not backend properties, so they always come from operator config or the built-in default; the catalog has nothing to contribute there.
Worked examples
All examples assume the built-in default = {context: 32000, autocompact_at: 80, target_size_pct: 50}.
-
Platform deployment, catalog unreachable, no operator entry for the model.
context = 32000,autocompact_at = 80%. Auto-trigger would fire at 25,600 tokens. -
Pharia AI deployment, catalog reports
qwen3 = 40000, no operator entry for qwen3.context = 40000(from catalog),autocompact_at = 80%(catalog doesn’t carry this field, so the operator-default applies). Auto-trigger would fire at 32,000 tokens. -
Operator entry
qwen3: { context: 29000, autocompact_at: 50 }, catalog reportsqwen3 = 40000. Operator wins per field:context = 29000,autocompact_at = 50%. Auto-trigger would fire at 14,500 tokens. (Same outcome on Platform and Pharia AI; operator entry beats the catalog.)
Operational notes
-
No hot reload. A config change requires a pod restart. This matches the existing
GuardRailsConfigbehaviour and is intentional: context limits change on deployment timescales, not at runtime. -
No per-tenant or per-application overrides today. If they’re needed, they can layer on top later.
-
The catalog is consulted lazily through the same cached path the rest of the worker uses; there is no additional network call per request.