Saved compiler state changes whether LiteLLM Proxy blocks a request, forwards it unchanged, or injects compiler state before the downstream call. This example shows LiteLLM Proxy acting as the host-owned gateway surface.
Context Compiler is the authority layer for saved state. These hooks no longer derive authority from transcript history. They process only the latest user turn and rely on host-owned checkpoints for continuity.
Available hook files:
- Basic checkpoint-backed hook:
context_compiler_precall_hook.py - Directive-drafter-enabled checkpoint-backed hook:
context_compiler_precall_hook_with_directive_drafter.py
- LiteLLM Proxy is the gateway surface; Context Compiler remains the authority layer for saved state.
- By default, the hooks run in stateless mode and process only the latest user turn with a fresh engine.
- In explicit persistent mode, the hook resolves a session key, loads a saved
checkpoint, restores the engine, processes the latest user turn once, and
saves the resulting checkpoint after every decision, including
clarify. - In stateless mode, no continuity is preserved across requests.
- If result is
clarify, the proxy does not call the downstream model and LiteLLM surfaces the clarification as an HTTP 400 response. - If result is
passthrough, the proxy forwards the request normally. - If result is
update, the proxy injects compiler state as a system message and then calls the model. - Unsupported LiteLLM callback
call_typevalues return the original request data unchanged.
Optional directive-drafter behavior:
- The drafter runs only on the current/latest user turn.
- The hook restores checkpoints before drafting.
- Heuristic runs first; if no directive is found, LLM fallback is attempted.
- Forwarded upstream request messages are not rewritten except for the injected compiler system message.
The reference hooks support two explicit modes:
persistent- explicit mode
- requires a stable session key
- preserves saved state and pending clarification across requests
stateless- default mode
- processes only the latest user turn
- preserves no continuity
Set the mode with one of:
- top-level request field
context_compiler_mode - env var
CONTEXT_COMPILER_SESSION_MODE
Persistent mode resolves session keys in this order:
context_compiler_session_keymetadata.context_compiler_session_key
If persistent mode cannot resolve a stable session key, the hook fails clearly and does not fall back to transcript replay or implicit stateless behavior.
The hooks share a small repo-local support module:
class CheckpointStore(Protocol):
def load(self, session_key: str) -> Mapping[str, object] | None: ...
def save(self, session_key: str, checkpoint: Mapping[str, object]) -> None: ...The reference implementation uses an in-memory store for tests and local demos. It is single-process only:
- no durability across restarts
- no multi-worker coordination
- no atomic compare-and-swap
- no expiration/cleanup policy
Real deployments should replace it with a host-owned store such as Redis or a database-backed implementation.
pip install "context-compiler-example-integrations[litellm]"
export OPENAI_API_KEY=...Start with the compiler-only hook. Add context-compiler-directive-drafter
only if you want the optional directive-drafter variant.
For context_compiler_precall_hook_with_directive_drafter.py:
pip install "context-compiler-example-integrations[all]"For the opt-in runtime smoke test, install the proxy runtime extras:
uv sync --group proxy_runtime --no-editableFrom the repo root:
pip install "context-compiler-example-integrations[litellm]"
export OPENAI_API_KEY=...
litellm --config python/reference_integrations/litellm_proxy/config.example.yamlconfig.example.yaml includes both OpenAI and Ollama model definitions.
Use the Ollama model entry for local testing without API credentials.
from openai import OpenAI
client = OpenAI(
api_key="anything",
base_url="http://localhost:4000",
)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "prohibit peanuts"}],
extra_body={"context_compiler_session_key": "demo-chat"},
)Or with curl:
curl http://localhost:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer anything" \
-d '{
"model": "gpt-4o-mini",
"context_compiler_session_key": "demo-chat",
"messages": [{"role": "user", "content": "prohibit peanuts"}]
}'For explicit stateless mode:
{
"model": "gpt-4o-mini",
"context_compiler_mode": "stateless",
"messages": [{"role": "user", "content": "prohibit peanuts"}]
}For explicit persistent mode:
{
"model": "gpt-4o-mini",
"context_compiler_mode": "persistent",
"context_compiler_session_key": "demo-chat",
"messages": [{"role": "user", "content": "prohibit peanuts"}]
}The reference integration is covered by unit tests and an opt-in runtime smoke test. See "Opt-in Runtime Smoke Test" below for details.
The proxy runs on http://localhost:4000 by default. By default,
config.example.yaml points to the basic checkpoint-backed hook. To use the
directive-drafter variant, switch the callback path in the config. The callback
path must be importable by LiteLLM in the environment where the proxy process
starts.
When starting LiteLLM from the repo root, prefer fully qualified callback imports in automated configs, for example:
python.reference_integrations.litellm_proxy.context_compiler_precall_hook.proxy_handler_instance
Optional env vars for directive-drafter fallback:
export PREPROCESSOR_MODEL=openai/gpt-4o-mini
export PREPROCESSOR_PROMPT_PROFILE=defaultPREPROCESSOR_MODEL is optional and defaults to MODEL.
For heuristic-first usage, keep PREPROCESSOR_PROMPT_PROFILE=default.
Use llama only for LLM-only preprocessing with Llama-family models.
- Mixed-content user messages compile only text segments from the latest user turn.
MODELandPREPROCESSOR_MODELuse LiteLLM format:<provider>/<model>.- Corrupt or incompatible checkpoints fail clearly in persistent mode and do not silently reset state.
- In the directive-drafter hook, drafter state context now comes from restored checkpoint state rather than transcript-prefix reconstruction.
- callback import failures: verify the callback path configured in
config.example.yamlis importable in the current LiteLLM environment - persistent mode rejects requests: provide a stable session key or opt into
explicit
statelessmode - proxy starts but upstream calls fail: check
OPENAI_API_KEYand upstream model/provider config inconfig.example.yaml - directive-drafter fallback issues:
PREPROCESSOR_MODELdefaults toMODEL; set it explicitly only when using a separate fallback model
This repo includes an opt-in runtime smoke test for the LiteLLM Proxy reference integration. The test starts a real LiteLLM Proxy process, runs the basic hook and the directive-drafter hook in separate proxy launches, sends local requests through the proxy with explicit session keys, verifies blocked requests do not reach upstream, verifies allowed requests reach a local stub upstream with the injected compiler contract, verifies the directive-drafter path preserves the original forwarded user prompt text, and shuts each proxy down cleanly.
It is intentionally not part of ./scripts/validate_python.sh.
Run it from the repo root:
RUN_LITELLM_PROXY_RUNTIME=1 uv run --group proxy_runtime pytest python/tests/test_litellm_proxy_runtime.py