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.2
langstate demo

It prints the compressed messages and a machine-readable receipt showing that both named facts survived. 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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langstate-0.2.2.tar.gz (19.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langstate-0.2.2-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file langstate-0.2.2.tar.gz.

File metadata

  • Download URL: langstate-0.2.2.tar.gz
  • Upload date:
  • Size: 19.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for langstate-0.2.2.tar.gz
Algorithm Hash digest
SHA256 dd3fa79b60c2c401b594e67f2c6d72c29cb65fd00e5502a20be6f0f5c0cfe17c
MD5 537e6ce86842418ff582fa26ef999284
BLAKE2b-256 e7527a0ab52015fdbd12223c6cb3f7e547c9ae896b4e987e330ad1295a8d744b

See more details on using hashes here.

Provenance

The following attestation bundles were made for langstate-0.2.2.tar.gz:

Publisher: publish.yml on hermes-labs-ai/langstate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file langstate-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: langstate-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 17.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for langstate-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f01ec164bfb69eed1f2f9b92bf9f7407820c55f265586c9203f7bb4e36133032
MD5 e0f13bde8c5f3ee4e6875a75c4b122d9
BLAKE2b-256 2ccb2fdb954c08eed1aa48eb6905cc882247d3dd50af00b23b189baeff90f42d

See more details on using hashes here.

Provenance

The following attestation bundles were made for langstate-0.2.2-py3-none-any.whl:

Publisher: publish.yml on hermes-labs-ai/langstate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 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