Skip to main content

langstate

Compress long LLM conversations into visible working state — then check that the literal facts you care about survived.

langstate is a small experimental Python library for OpenAI-format message lists. It keeps system messages and recent turns verbatim, summarizes older history into a visible [SCAFFOLD STATE] system message, and returns the same list-shaped interface that chat clients already accept.

Most context compression gives you a summary and asks you to trust it. LangState makes that lossy step inspectable: the compressed state is an ordinary message you can view, log, edit, replace, or reject. validate(...) then gives you a deterministic receipt for the literal facts you name explicitly.

This is a functional prototype/library, not a lossless archive, a structured state store, or production infrastructure. Summary quality depends on the model and the input; treat validate as a narrow check, not a guarantee of semantic fidelity.

Try it in two minutes

python -m pip install langstate==0.2.3
langstate demo

It prints the compressed messages and a machine-readable receipt showing that both named facts survived and that the history got smaller. The proof needs no model, API key, network call, or Ollama installation.

Python 3.10+; no runtime dependencies beyond the standard library. To use the default summarizer after the proof, prepare a local Ollama model once:

ollama pull qwen3:4b

Reproduce the API flow

This deterministic example produces a real scaffold and receipt without a model call. This is the expanded API equivalent of the one-command proof above. It injects a tiny summarizer so the result is reproducible; remove summarizer=demo_summary afterward to use local Ollama instead.

from langstate import compress, validate

messages = [{"role": "system", "content": "Be concise."}]
for user, assistant in [
    (
        "We are launching the developer preview on May 5. Keep the rollout "
        "private until the invitation list is approved, and cap the launch "
        "budget at $4,000.",
        "Understood. I will treat May 5, a private preview, and the $4,000 "
        "cap as launch constraints.",
    ),
    (
        "Dana owns the release checklist. Morgan owns the API migration. "
        "The only blocker is the billing webhook retry bug in staging.",
        "I recorded Dana as release owner, Morgan as migration owner, and "
        "the staging billing webhook as the blocker.",
    ),
    (
        "The first cohort is 25 developers using Python clients. We will not "
        "invite JavaScript users until the second week.",
        "The first cohort is 25 Python developers; JavaScript waits until week two.",
    ),
    (
        "If the blocker is still open on May 3, move the preview to May 12 "
        "rather than cutting the verification pass.",
        "Unresolved on May 3 means move to May 12, never skip verification.",
    ),
    ("What should the launch note emphasize?", "The private, Python-first preview."),
    ("Who gives final approval?", "Dana, after webhook verification passes."),
]:
    messages.extend(({"role": "user", "content": user},
                     {"role": "assistant", "content": assistant}))

def demo_summary(_prompt):
    return (
        "- Preview: May 5; budget cap: $4,000.\n"
        "- Dana owns release; Morgan owns API migration.\n"
        "- Blocker: staging billing webhook retries.\n"
        "- If still blocked May 3, move to May 12."
    )

compressed = compress(messages, preserve_recent=2, summarizer=demo_summary)

receipt = validate(
    messages,
    compressed,
    facts=["May 5", "$4,000", "Dana", "Morgan", "May 12"],
)
assert receipt.ok
print(compressed[1]["content"])
print(receipt.summary())

The result makes the compressed state visible before you send it anywhere:

[SCAFFOLD STATE — compressed from 8 earlier messages]
- Preview: May 5; budget cap: $4,000.
- Dana owns release; Morgan owns API migration.
- Blocker: staging billing webhook retries.
- If still blocked May 3, move to May 12.

5/5 facts survived (100%) · 62% smaller

Now omit summarizer=demo_summary after preparing Ollama to judge a real local model against the facts your application actually needs. Receipt.ok is true only when every requested string occurs in the compressed messages after case-and-whitespace normalization. It cannot credit a paraphrase, so it is intentionally conservative. Use explicit facts=[...] for a focused contract; automatic fact extraction is a convenience heuristic.

How it works

For conversations of at least six user/assistant turns, compress:

  1. retains all system messages and the requested recent suffix verbatim;
  2. sends the older non-system messages to the selected summarizer;
  3. inserts that result as [SCAFFOLD STATE — compressed from N earlier messages];
  4. returns the resulting OpenAI-format list.

You can use the result with an OpenAI-compatible chat client, or keep the scaffold as an auditable intermediate artifact. The library does not make a semantic preservation claim about the model-generated summary.

Choose a summarizer

Option Default/model What you provide
Local Ollama qwen3:4b Ollama at localhost:11434
OpenAI gpt-4o-mini OPENAI_API_KEY
Anthropic claude-haiku-4-5 ANTHROPIC_API_KEY
Custom (prompt: str) -> str Your callable
from langstate import compress
from langstate.adapters import build

local = compress(messages)
openai = compress(messages, summarizer=build("openai"))
anthropic = compress(messages, summarizer=build("anthropic"))
custom = compress(messages, summarizer=my_summarizer)

Use probe(name) to see whether a configured adapter is currently usable.

Boundaries and current evidence

  • The library’s deterministic tests cover message shaping, injected summarizers, adapter-unavailable errors, lexical receipts, and version consistency. They do not establish the quality of any live model.
  • Repository benchmark JSON files record single, synthetic-corpus runs for the named adapter and model. They are leads for model selection, not general performance claims. Their exact historical provenance and current-release exclusion are recorded in BENCHMARK-PROVENANCE.md.
  • validate checks literal text only. It neither establishes semantic equivalence nor detects an invented claim that happens to reuse a checked phrase.
  • Use original messages for exact replay, regulated records, tool-call semantics, or any workflow where a lossy summary is unacceptable.

API

compress(
    messages,
    preserve_recent=4,
    min_turns_to_compress=6,
    model="qwen3:4b",
    summarizer=None,
)

validate(before, after, facts=None)

See Receipt.as_dict() for a JSON-friendly receipt. The package is Apache-2.0 licensed.

Metadata

Release files for langstate 0.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for langstate 0.2.3
File Size Uploaded
langstate-0.2.3.tar.gz 20.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for langstate 0.2.3
File Interpreter ABI Platform
langstate-0.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 38.3 kB

Release files / langstate-0.2.3.tar.gz

Download URL langstate-0.2.3.tar.gz
Size 20.4 kB
Tags Source
SHA-256 checksum
How to use checksums
f1e373978630788a82719811a97432a6fa2b0bfbc2c6abb3988b772fc078daef
BLAKE2b-256 checksum
How to use checksums
dc3d610c67497a5c8880572706405edb147a808478ee1afa3753c9e2744e48a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release files / langstate-0.2.3-py3-none-any.whl

Download URL langstate-0.2.3-py3-none-any.whl
Size 18.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0a3641c3783f65b04648da843eaf3e2c46b3bf48cf60fed52f4a5fc40fb438e1
BLAKE2b-256 checksum
How to use checksums
bc85129e57f193d5a1448e6259cd8a70d135435b9a4ffaa542c66b8beb2be759
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.4

2 release files

This release

0.2.3 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page