Proofline
Proofline is a model-agnostic protocol and reference implementation for verifiable AI runs.
A run bundle is a single JSON document that records the inputs, code revision, model/tool steps, outputs, costs, redactions, and hashes needed to replay, diff, and audit LLM or agent executions. The core is a versioned schema; SDKs, storage backends, and framework adapters are replaceable layers around it.
Why
- Regression testing.
proofline diffcompares two runs semantically. Run ids, timestamps, and derived digests never show up as noise; what changed in inputs, outputs, and costs does. See CI regression gates for the end-to-end recipe. - Replay. A bundle doubles as a test fixture: recorded responses are served back through the wrappers, so pipelines re-run deterministically, offline, and for free — and diffing a replayed run against its baseline tells you whether a change came from your code or from model drift. See replay.
- Audit and forensics. Bundles are tamper-evident: a stable SHA-256 digest covers everything that can affect replay decisions, and
proofline verifyre-checks every stored hash, redaction path, and secret pattern. - Portability. A bundle is one JSON file with a published schema and spec. No server, no vendor lock-in.
Non-goals
- Not another chat UI or agent framework.
- Not a model provider or prompt registry.
- Not a claim that reruns are bit-identical when the underlying model or tools are nondeterministic.
Install
pip install proofline
Provider integrations are optional extras: pip install "proofline[openai]" or pip install "proofline[anthropic]". For development installs, see CONTRIBUTING.md.
Quickstart
Record the same command twice, then prove the runs are semantically identical:
proofline run --out a.run.json -- python -c "print('hello agent')"
proofline run --out b.run.json -- python -c "print('hello agent')"
proofline verify a.run.json
# OK a.run.json
proofline diff a.run.json b.run.json
# no semantic differences
Timestamps and run ids differ between the two bundles, but both are excluded from the stable digest and from semantic diffs, so identical work produces an empty diff. For agent-shaped runs with tool, model, and check steps, clone the repo and try examples/code_fix_agent.py and examples/rag_citation_check.py.
SDK
from proofline import RunRecorder
with RunRecorder(out_path="artifacts/demo.run.json") as recorder:
with recorder.step("model", "draft", input={"prompt": "hi"}) as step:
step["output"] = {"text": "ok"}
step["cost"] = {"input_tokens": 3, "output_tokens": 1}
Secrets are redacted before anything touches disk: keys like api_key / credentials and values like sk-..., AKIA..., Bearer ..., or JWTs are replaced with [REDACTED], and each redaction site is recorded as a JSON Pointer in the bundle.
See examples/rag_citation_check.py and examples/code_fix_agent.py for full agent-shaped runs.
Replay
Any bundle recorded through the wrappers can answer the same pipeline again — no API key, no network, no cost:
from proofline.replay import ReplaySource
client = wrap(OpenAI(), recorder, replay=ReplaySource("baseline.run.json"))
Or, with zero code changes, set PROOFLINE_REPLAY=baseline.run.json in the environment. Strict matching turns the baseline into a fixture; ordered matching lets a changed pipeline complete so the bundle diff shows exactly what your code changed. docs/replay.md covers strategies, streaming fidelity, and the attribution workflow.
Integrations
OpenAI
python -m pip install -e ".[openai]"
from openai import OpenAI
from proofline import RunRecorder
from proofline.openai import wrap
with RunRecorder(out_path="artifacts/openai.run.json") as recorder:
client = wrap(OpenAI(), recorder)
client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "ping"}],
)
Each chat.completions.create call is recorded as a model step with the request as input, the response as output, and token usage as cost. Streaming calls are recorded too: the accumulated text is stored together with a truncated flag, and a failed request records an error step. AsyncOpenAI clients are wrapped by the same wrap() call. Run examples/openai_chat.py for an end-to-end recorded call.
Anthropic
python -m pip install -e ".[anthropic]"
from anthropic import Anthropic
from proofline import RunRecorder
from proofline.anthropic import wrap
with RunRecorder(out_path="artifacts/anthropic.run.json") as recorder:
client = wrap(Anthropic(), recorder)
client.messages.create(
model="claude-sonnet-4-5",
max_tokens=256,
messages=[{"role": "user", "content": "ping"}],
)
messages.create is recorded the same way, including stream=True event iteration, and AsyncAnthropic clients are wrapped by the same wrap() call. Run examples/anthropic_chat.py for an end-to-end recorded call.
Bundle anatomy
{
"schema_version": "0.1",
"run_id": "6f0c0f1e-…",
"created_at": "2026-08-11T15:00:00.000Z",
"actor": {"type": "human+agent", "name": "powfu", "version": "0.2.0"},
"project": {"name": "proofline", "revision": "9dd5f0a…", "dirty": false},
"invocation": {"argv": ["python", "agent.py"], "cwd": "…", "env_keys": ["PATH"], "python": "3.11.15"},
"steps": [
{
"step_id": "step-1",
"kind": "model",
"name": "draft",
"status": "ok",
"started_at": "…",
"ended_at": "…",
"input": {"prompt": "hi"},
"output": {"text": "ok"},
"error": null,
"cost": {"input_tokens": 3, "output_tokens": 1},
"metadata": {},
"input_digest": "…",
"output_digest": "…"
}
],
"redactions": [],
"metadata": {},
"bundle_digest": "…"
}
Core invariant
A bundle is portable evidence. Any field that cannot affect replay decisions, such as wall-clock timestamps or a fresh run id, is excluded from the stable digest and from semantic diffs. bundle_digest is SHA-256 over canonical JSON of the bundle with volatile fields removed; see the spec for the exact normalization and verification rules.
FAQ
How is this different from LangSmith, Langfuse, or other tracing platforms? Those are observability platforms: hosted dashboards for exploring traces at scale. Proofline is an evidence format: a single verifiable JSON file you can commit to a repo, diff in CI, attach to an incident report, or hand to an auditor. No server, no account, no SDK lock-in. If you already run a tracing platform, proofline is complementary — it is the artifact you keep when a specific run has to be provable.
Is a bundle proof that the model would answer the same way again? No, and the spec is explicit about this non-goal. A bundle proves what was sent, what came back, what it cost, and that nobody altered the record afterwards. Determinism is your pipeline's job; the CI recipe shows how to get there where it matters.
Does redaction make bundles safe to share?
Redaction is pattern-based and best-effort — it catches well-known key names and token formats before anything touches disk, and verify re-scans as a second line of defense. It is not a guarantee; review bundles like any fixture before publishing them. See SECURITY.md for the exact boundary.
When should I not use proofline? If you want live dashboards, sampling analytics, or fleet-wide monitoring, use a tracing platform. If your pipeline has no decisions worth auditing or regressing, a bundle is overhead. Proofline earns its keep where runs are consequential: agents that touch code, money, or user data, and pipelines whose behavior changes must be caught in review.
Development
python -m pip install -e ".[dev]"
ruff check src tests examples
pytest -q
License
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 proofline-0.2.0.tar.gz.
File metadata
- Download URL: proofline-0.2.0.tar.gz
- Upload date:
- Size: 30.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7becc56515a5cc7b4bd3dd45aaca56f5258fd4a2cc69ecb2f963c13ff12ca8b9
|
|
| MD5 |
1b4a6a08d6524b91b652ea7e738421d0
|
|
| BLAKE2b-256 |
99b8f81da83dec756d80779b508e6e672c2e3ed7f14d4b7134f691574b6d02e5
|
Provenance
The following attestation bundles were made for proofline-0.2.0.tar.gz:
Publisher:
release.yml on Powfu-zwx/proofline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proofline-0.2.0.tar.gz -
Subject digest:
7becc56515a5cc7b4bd3dd45aaca56f5258fd4a2cc69ecb2f963c13ff12ca8b9 - Sigstore transparency entry: 2430061734
- Sigstore integration time:
-
Permalink:
Powfu-zwx/proofline@8c8ae42e1a55487b4d005bedce95e8eeb5996340 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Powfu-zwx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8c8ae42e1a55487b4d005bedce95e8eeb5996340 -
Trigger Event:
push
-
Statement type:
File details
Details for the file proofline-0.2.0-py3-none-any.whl.
File metadata
- Download URL: proofline-0.2.0-py3-none-any.whl
- Upload date:
- Size: 22.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f57026e671d271a4aa6df5c851a9ddde72bc2a0f1d7ca08db040df301dbdd70
|
|
| MD5 |
0721e9ab6a3e0b2fa591304f263570db
|
|
| BLAKE2b-256 |
8cd8c6bbc0177c348ccaab760a8dc1eb16b4dd7ad6c61278cfec667e6f8a71e7
|
Provenance
The following attestation bundles were made for proofline-0.2.0-py3-none-any.whl:
Publisher:
release.yml on Powfu-zwx/proofline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proofline-0.2.0-py3-none-any.whl -
Subject digest:
4f57026e671d271a4aa6df5c851a9ddde72bc2a0f1d7ca08db040df301dbdd70 - Sigstore transparency entry: 2430061772
- Sigstore integration time:
-
Permalink:
Powfu-zwx/proofline@8c8ae42e1a55487b4d005bedce95e8eeb5996340 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Powfu-zwx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8c8ae42e1a55487b4d005bedce95e8eeb5996340 -
Trigger Event:
push
-
Statement type: