Deterministic conversational state engine for LLM applications.
Project description
Context Compiler
Context Compiler is a deterministic conversational state authority for LLM applications. It handles explicit state changes, clarification and confirmation flows, checkpoint restore, and structured authoritative state for the host.
What Context Compiler provides
Context Compiler gives hosts fixed state rules:
- handle explicit user state changes with deterministic rules
- clarification instead of silent overwrite for blocked/ambiguous changes
- pending confirmation flows that must resolve before anything else changes
- export and import checkpoints to restore saved state and pending confirmation flow
- produce structured authoritative state for downstream host decisions
The model generates responses. The compiler owns state.
How the compiler metaphor works
Like a compiler, it parses input, validates it, applies fixed rules, and produces a stable result the host can use. It treats important instructions as structured state instead of temporary prompt text. It is not source-code compilation and not a reasoning model.
10-Second Example
User sets a premise once:
User: set premise current project uses uv
Outcome: premise state includes "current project uses uv".
Later in the conversation:
User: how should I run the tests?
Your host sends the saved authoritative state with this later request, so the
model answers in the context of the saved premise (current project uses uv)
instead of relying on memory of earlier conversation text.
Deterministic behavior (examples)
Context Compiler makes state-change rules explicit so behavior stays repeatable.
Explicit directive
set premise concise replies
- Base model: silently accepts / rewrites
- Context Compiler: applies a repeatable state update
Single-directive grammar
use docker and prohibit peanuts
- Without an authority layer: host/model behavior varies
- Context Compiler: returns
clarify, keeps authoritative state unchanged, and asks for separate directives
State-dependent operation
clear state
use podman instead of docker
- Without explicit state transition rules: behavior depends on host/model handling
- Context Compiler: returns
clarifybefore changing state
Lifecycle enforcement
clear state
change premise to formal tone
- Without explicit transition checks: behavior depends on host/model handling
- Context Compiler: asks for clarification and keeps saved state unchanged
Architecture
User Input
│
▼
Context Compiler
│
▼
Decision
│
▼
Host Application
├─ clarify → ask user
├─ passthrough → call LLM
└─ update → authoritative state mutated; host may call LLM with compiled state
The compiler never calls the LLM. Your app decides what to do with the returned
Decision.
Quickstart
Use Context Compiler in your host application first:
from context_compiler import (
create_engine,
get_clarify_prompt,
is_clarify,
is_update,
)
engine = create_engine()
user_input = "set premise current project uses uv"
decision = engine.step(user_input)
if is_clarify(decision):
show_to_user(get_clarify_prompt(decision))
elif is_update(decision):
messages = build_messages(engine.state, user_input)
render(call_llm(messages))
else:
render(call_llm(user_input))
This is the main integration path: your app owns the model call and uses the compiler as the authority layer for state transitions.
For runnable application-layer examples, see
context-compiler-example-integrations.
That companion repository shows enforcement points built on compiler state,
including retrieval filtering, schema selection, tool gating, execution
authorization, gateway middleware, checkpoint continuation, and prompt
construction.
Does it Work?
Yes. The current demo suite in this repository contains 8 scored demos
(01-05, 07, 08, 09) plus 1 informational demo (06).
The current published verification matrix combines 7 current model runs across hosted/frontier providers and local Ollama models. In those current runs, baseline passed 24 / 56, reinjected-state passed 40 / 56, and both compiler paths passed 56 / 56.
→ Current demo set and output modes Current and historical published results: docs/demos-results.md
Interactive Playground
Use the REPL to explore behavior, learn the directive grammar, and debug or test host-side state rules.
pip install context-compiler
context-compiler
Preload options keep saved rules separate from confirmation state in progress:
--initial-state-json/--initial-state-fileload saved state (via exported state JSON).--initial-checkpoint-json/--initial-checkpoint-filerestore full continuation checkpoint (saved state + pending confirmation state).
REPL commands (controller layer, not engine directives):
stateshows current saved state.preview <input>runs deterministic dry-run without mutating live state.step <input>is an explicit alias of normal bare-input step behavior.
Bare REPL input behavior remains unchanged.
Machine-Readable CLI Usage
Use --json when you want one complete JSON object per processed input line
for non-interactive usage.
context-compiler --json < input.txt
Preload options keep saved rules separate from confirmation state in progress:
--initial-state-json/--initial-state-fileload saved state (via exported state JSON).--initial-checkpoint-json/--initial-checkpoint-filerestore full continuation checkpoint (saved state + pending confirmation state).
Installation
Requirements:
- Python 3.11+
Install:
pip install context-compiler
Packaging notes:
- Base install includes the core authority-layer engine and CLI.
- Example and demo source files are available in the repository and source distribution.
- To run the demos from this repository, clone the repo and install
context-compiler[demos]. - The
[demos]extra installs optional dependencies such as LiteLLM. It does not install demo source files into site-packages.
Development
uv sync --group dev
uv run pytest
Decision API
Each user message produces a Decision.
class Decision(TypedDict):
kind: Literal["passthrough", "update", "clarify"]
state: dict | None
prompt_to_user: str | None
Meaning:
| kind | host behavior |
|---|---|
| passthrough | forward user input to LLM |
| update | authoritative state mutated; host may call LLM with updated state |
| clarify | show prompt_to_user and do not call the LLM |
For normal app code, prefer the exported decision helpers (is_clarify,
is_update, is_passthrough, get_clarify_prompt, get_decision_state)
instead of direct key traversal.
See docs/api-reference.md for the full public API reference.
Common API entry points:
- engine lifecycle:
create_engine(...),engine.step(...),engine.state,engine.has_pending_clarification() - decision helpers:
is_clarify(...),is_update(...),is_passthrough(...),get_clarify_prompt(...),get_decision_state(...) - state helpers:
get_premise_value(...),get_policy_items(...) - state and checkpoint transport:
export_json(...),import_json(...),export_checkpoint(...),import_checkpoint(...) - controller APIs:
preview(...),step(...),state_diff(...)
Controller API (Reusable Outside REPL)
preview(engine, user_input)performs a deterministic dry run and restores live engine state afterwardstep(engine, user_input)returns a reusable result envelope around one engine turnstate_diff(state_before, state_after)summarizes structural state changes
For examples and helper accessors such as get_step_decision(...),
get_preview_state_after(...), preview_would_mutate(...), and
diff_has_changes(...), see docs/api-reference.md.
State Model
The state model holds explicit user commitments that the host can treat as authoritative in future turns.
-
premise= authoritative context that changes how future answers should be interpreted -
use= affirmative selection or preference -
prohibit= explicit exclusion -
Premise is a single value that can be set or replaced
-
Policies are per-item (
useorprohibit) -
State changes only through explicit directives
-
No inference or semantic reasoning
Identical input sequences always produce identical state.
The internal structure of the state is intentionally opaque to host applications.
For normal reads, prefer get_premise_value(state) and
get_policy_items(state, ...) over direct key traversal.
When to use premise
Use premise for persistent context that changes how all answers should be interpreted, especially when it:
- applies across many turns
- significantly changes what solutions are valid
- cannot be fully captured as simple
use/prohibitpolicies
Examples:
- “Current medications: …”
- “Outdoor event; no seating available”
- “GDPR data handling requirements apply”
- “System is deployed across multiple regions”
- “Limited time available”
In these cases, the premise acts as an authoritative context anchor that the host supplies to the model on every turn.
Use policies instead when the constraint is explicit and enforceable:
- “prohibit foods that may cause GI upset”
- “use handheld foods”
- “prohibit storing personal data beyond immediate use”
- “prohibit introducing new external dependencies”
- “use single-step preparation methods”
Example domains
Hosts define what policy items and premise mean in context. Common patterns include:
- safety-oriented constraints (for example, prohibited materials or tools)
- authority/evidence constraints (for example, cite only approved sources)
- software workflow constraints (for example, require
uv, prohibitnpm) - accessibility/environment constraints (for example, no audio-only outputs)
Context Compiler enforces explicit directive and state rules. Domain reasoning still belongs to the host and model workflow.
Checkpoint Contract
export_json() / import_json() and the checkpoint APIs serve different boundaries:
export_json()/import_json()transport authoritative state only- checkpoint APIs transport serialized continuation:
- authoritative state
- pending confirmation flow state
Use state JSON when you only need authoritative state. Use checkpoint APIs when you also need resumable continuation state across process or request boundaries.
For the checkpoint object shape, API-level usage notes, and serialization details, see docs/api-reference.md.
Directive Examples
Set and change premise:
User: set premise concise replies
User: change premise to concise bullet points
Per-item policies:
User: use docker
User: prohibit peanuts
Replacement:
User: use podman instead of docker
Removal and reset:
User: remove policy peanuts
User: reset policies
User: clear state
Grammar invariant: one input may contain at most one canonical directive.
If another canonical directive start appears later in the same input, the
input is invalid and Context Compiler returns clarify without mutating
authoritative state or creating pending confirmation state.
Examples:
Valid:
use docker
use podman instead of docker
clear state
Invalid:
use docker and prohibit peanuts
set premise vegetarian and use docker
clear state then set premise new project
Quote behavior follows the current grammar literally:
Passthrough:
"use docker and prohibit peanuts"
Invalid:
use "docker and prohibit peanuts"
set premise "use docker and prohibit peanuts"
Quotes do not create protected literal regions inside a recognized directive payload.
Conflicting directives also trigger clarification instead of changing state.
For full directive grammar and edge-case behavior, see DirectiveGrammarSpec.md.
Examples
- examples — minimal usage patterns for the core authority layer
- demos — concrete scenarios showing how behavior differs with and without the compiler
context-compiler-example-integrations— runnable application-layer enforcement examples built around compiler state
FAQ
Isn't this just prompt reinjection?
No. Prompt construction is one downstream use of authoritative state.
Context Compiler is the authority layer that decides when state changes are
allowed, when clarification is required, and how continuation state is
restored. For runnable application-layer examples, see
context-compiler-example-integrations.
Why not just use a plain dict? A plain dict can hold state for prompt construction, schema selection, tool gating, and other host behavior.
Context Compiler solves the authority problem: who updates that state, under which rules, and what happens when instructions conflict.
User: use python_script
User: prohibit python_script
Without an authority layer, the application must invent conflict-resolution and continuation rules itself. Context Compiler applies deterministic state-transition rules and can return clarification instead of silently overwriting state.
Advanced topics
Guarantees
- State changes only through explicit user directives or confirmation.
- Identical input sequences produce identical compiler state.
- Model responses never modify compiler state.
- Ambiguous directives trigger clarification instead of changing state.
Behavioral tests and Hypothesis-based property tests verify these invariants.
Multiple engines
For a full documentation map, see docs/README.md.
Design Notes
These docs cover the design and milestone details:
Conformance Fixtures
tests/fixtures/ defines the cross-language conformance tests.
These fixtures serve as the behavioral contract for compiler semantics across implementations.
License
Apache-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file context_compiler-0.8.3.tar.gz.
File metadata
- Download URL: context_compiler-0.8.3.tar.gz
- Upload date:
- Size: 51.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
684f9b617c24833cb281c8a5b3458a45112a236e84da9659b889aa98a061187d
|
|
| MD5 |
87eae5a9c6f2dbe6623863e583380281
|
|
| BLAKE2b-256 |
cd4c595c0b96844579f169c8024312122b7998776331f48ae04787d8be339487
|
Provenance
The following attestation bundles were made for context_compiler-0.8.3.tar.gz:
Publisher:
publish-pypi.yml on rlippmann/context-compiler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
context_compiler-0.8.3.tar.gz -
Subject digest:
684f9b617c24833cb281c8a5b3458a45112a236e84da9659b889aa98a061187d - Sigstore transparency entry: 2141684827
- Sigstore integration time:
-
Permalink:
rlippmann/context-compiler@768fcc9b83e3223aa5a540156afbb50c0c8bd05d -
Branch / Tag:
refs/tags/v0.8.3 - Owner: https://github.com/rlippmann
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@768fcc9b83e3223aa5a540156afbb50c0c8bd05d -
Trigger Event:
release
-
Statement type:
File details
Details for the file context_compiler-0.8.3-py3-none-any.whl.
File metadata
- Download URL: context_compiler-0.8.3-py3-none-any.whl
- Upload date:
- Size: 23.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbe43870f628b4f8ef172ac58bcf347591491fa50a1a9cf8f50f06f734b506c1
|
|
| MD5 |
7ac2fa621ac550ad107d30bb25fd95d4
|
|
| BLAKE2b-256 |
ea161878057b23913bb2d397fe40e3cc834abc539b2aeac9e79914aca28c3c9b
|
Provenance
The following attestation bundles were made for context_compiler-0.8.3-py3-none-any.whl:
Publisher:
publish-pypi.yml on rlippmann/context-compiler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
context_compiler-0.8.3-py3-none-any.whl -
Subject digest:
bbe43870f628b4f8ef172ac58bcf347591491fa50a1a9cf8f50f06f734b506c1 - Sigstore transparency entry: 2141684853
- Sigstore integration time:
-
Permalink:
rlippmann/context-compiler@768fcc9b83e3223aa5a540156afbb50c0c8bd05d -
Branch / Tag:
refs/tags/v0.8.3 - Owner: https://github.com/rlippmann
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@768fcc9b83e3223aa5a540156afbb50c0c8bd05d -
Trigger Event:
release
-
Statement type: