Skip to main content

bellbook (Python)

Python bindings for Bellbook: validate tamper-evident, replay-verifiable records of agent activity offline, from Python.

This is a thin PyO3 wrapper over the Rust bellbook crate, which stays the single source of truth for canonicalization, verification, and the conformance vectors. It is not a reimplementation. (The independent from-scratch validator under conformance/python/ in the repository is a separate thing: a deliberate second implementation that exists to cross-check the specification.)

Status

Validation, reading, and writing (issue #13).

Validate

validate(bytes) -> Report reaches the same Clean / Tainted / Invalid decision as the bellbook validate CLI, over the same core.

import bellbook

report = bellbook.validate(open("receipt.json", "rb").read())

print(report.status)          # "clean" | "tainted" | "invalid"
print(report.spec_version)    # "0.3"
print(report.record_count)
print(report.head_hash)       # lowercase hex; compare against an anchored head
print(report.rules_hash)      # compare against rules you trust
print(report.retracted, report.tainted)
print(report.standing)        # {"compromised": [...], "unsound": [...], "restorations": {...}}
print(report)                 # the full human-readable report (same as the CLI)

Validation never raises for a bad receipt: an unparseable or failing receipt returns a Report with status == "invalid" and a problem or reason set. As with the CLI, Clean is relative to the rules embedded in the receipt - compare rules_hash against a rule set you trust.

Read

read(bytes) -> Receipt parses a receipt for inspection. Reading does not verify - call validate for the decision.

import json

receipt = bellbook.read(open("receipt.json", "rb").read())

print(receipt.spec_version, len(receipt))
for r in receipt.records:
    print(r.kind, r.time, r.author_id, r.author_type, r.evidence)
    for ref in r.refs:
        print("  ", ref["type"], "->", ref["target"])
    payload = json.loads(r.payload_json)

A Record exposes id, kind, time, author_id, author_type, signed, evidence, schema, refs, and payload_json. The enum-valued fields (kind, author_type, evidence, and each ref's type) are the record's Rust variant names, e.g. "Candidate", "Provider", "Reported", "Use". read raises ValueError on bytes that are not a parseable receipt.

Write

Writer(log_dir, rules) records evolution to a persistent, single-writer log. It holds the same exclusive lock and runs the same replay-on-commit the Rust LogWriter does. rules is a JSON string: the verifier rules the log is committed under, the same object a receipt embeds under rules.

default_rules(authors, max_context=200, admins=None, reaffirmers=None) builds that string for you - the Python counterpart to bellbook rules init - so you never hand-author a rules object. authors maps an actor id to a role (user, provider, system, executor, or verifier, case-insensitive). admins lists actors allowed to retract records they did not author; reaffirmers, when given, restricts reaffirming selections to the listed actors. Both must also appear in authors:

import bellbook

rules_json = bellbook.default_rules({"agent": "provider", "evaluator": "provider"})
w = bellbook.Writer("./mylog", rules_json)

c0 = w.candidate(author="agent", git_tree="a1b2...")            # a Root candidate
e0 = w.evaluate(author="agent", candidate=c0.id, criterion="builds", passed=True)
s0 = w.select(author="agent", objective="ship it",
              consider=[c0.id], choose=[c0.id], uses_eval=[e0.id])

print(c0.id, c0.accepted, c0.reason)   # each commit returns a Commit

# Export and verify in the same process:
report = bellbook.validate(w.receipt())
assert report.status == "clean"

Each of candidate, evaluate, select, and retract commits one record and returns a Commit (id, accepted, result, reason). A record is durably committed whether accepted or rejected - a rejected record is evidence a proposal was refused - so accepted may be False without an exception. Statically-knowable payload violations (an unregistered author, a score scale above 12, an upgrade whose tree differs from its target) raise ValueError before anything is written.

  • candidate(author, git_tree, *, git_commit=None, algo="sha1", note=None, continues=None, parent=None, derives_from=None, upgrades=None, manifest=None)
    • basis is exactly one of continues (with parent), derives_from (a list of record ids), or upgrades; omit all three for a Root. manifest (a directory path) binds the source by a canonical manifest hash instead of a reported tree. A derives_from member may be a candidate or an evaluation: a repair motivated by an evaluation names it there alongside the candidate it derives from (derives_from=[sound_parent.id, failing_eval.id]), and because Cause carries intent, not taint, retracting that evaluation later does not taint the repair.
  • evaluate(author, candidate, criterion, *, passed=False, failed=False, score=None, scale=None, procedure=None, uses=None) - exactly one of passed, failed, or a score (with scale, a decimal exponent 0-12).
  • select(author, objective, consider, *, choose=None, uses_eval=None, none=False, replaces=None, rationale=None) - exactly one of choose (with uses_eval) or none=True; replaces reaffirms a prior selection. consider, choose, and uses_eval are lists of record ids.

Retract

retract(author, target, reason) asserts a committed record's content is wrong. The target stays in the log; its id enters the retracted set, its epistemic dependents become tainted, and the receipt reports Tainted from then on - permanently. A later reaffirming selection (one that replaces the unsound one on surviving evidence) restores the line's standing, but never turns the receipt Clean again: the episode is part of history, and that is the point.

r = w.retract(author="evaluator", target=e0.id,
              reason="benchmark harness measured the wrong thing")
assert r.accepted
assert bellbook.validate(w.receipt()).status == "tainted"

Retraction is ownership-bound (SPEC section 2): it is accepted only when author is the target's author, or is listed in the rules' admin_retraction_actors (set via default_rules(..., admins=[...])). An Executor may never author a retraction, so Executor-authored records are retractable only through an admin actor. A Verdict or a Retraction cannot be retracted. As with the other verbs, a rejected retraction is still durably committed with accepted == False and the verifier's reason.

The writer is deliberately single-writer (SPEC 5.1): it holds an exclusive lock for the log directory, so a second Writer on the same directory raises. Other useful members: w.head (current head, hex), w.records (the committed records, as Records), len(w), and w.receipt() (portable receipt bytes).

Build from source

pip install maturin
maturin develop            # build and install into the current venv
pytest bindings/python/tests

Prebuilt wheels (Linux, macOS, Windows) are published to PyPI, so pip install bellbook needs no Rust toolchain; the steps above are for local development against the working tree.

Licensed under MIT OR Apache-2.0.

Download files

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

Source Distribution

bellbook-0.5.0.tar.gz (24.6 kB view details)

Uploaded Source

Built Distributions

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

bellbook-0.5.0-cp39-abi3-win_amd64.whl (716.6 kB view details)

Uploaded CPython 3.9+Windows x86-64

bellbook-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (891.3 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

bellbook-0.5.0-cp39-abi3-macosx_11_0_arm64.whl (788.5 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

File details

Details for the file bellbook-0.5.0.tar.gz.

File metadata

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

File hashes

Hashes for bellbook-0.5.0.tar.gz
Algorithm Hash digest
SHA256 3df37724721cb5293a92e82208150b6e7ae66992edbf6657eb3a2761943c48ad
MD5 6987d7ceb21557dcd13a402c7bfa5bd5
BLAKE2b-256 ec960f06146211ea2f48c83fa611b84c99b28da6b726ff474c6c31c008563f93

See more details on using hashes here.

Provenance

The following attestation bundles were made for bellbook-0.5.0.tar.gz:

Publisher: publish-pypi.yml on bellbook-ai/bellbook

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

File details

Details for the file bellbook-0.5.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: bellbook-0.5.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 716.6 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for bellbook-0.5.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 415bcc19a077e520920c543fa19e605a5f767299b0c666cc8de62b6ecd463c80
MD5 61444464da812d0fe654bb3e2b704649
BLAKE2b-256 9219258da0b49f5bb1cbd059b7c48b8b2232124a185ae4a1c9e7a9c588d6e3b5

See more details on using hashes here.

Provenance

The following attestation bundles were made for bellbook-0.5.0-cp39-abi3-win_amd64.whl:

Publisher: publish-pypi.yml on bellbook-ai/bellbook

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

File details

Details for the file bellbook-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for bellbook-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e28d69c6e10c41d24445b38a285150aae7dc522433f681ecbd8bb4f39eb7fd44
MD5 661a184b06dcb6135b5d13695ad6e33e
BLAKE2b-256 b136716e1a77a095209fcf79141cb64049a9870bb6fba24f7add12a0f1bcb3a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for bellbook-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish-pypi.yml on bellbook-ai/bellbook

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

File details

Details for the file bellbook-0.5.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bellbook-0.5.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 efb1eed19edd486d2ff27575a15d9387ed2b8c5f77f31b6e48f14d789e8fc67d
MD5 6f8f7b3109160a537cd11cfc8d104b97
BLAKE2b-256 00e90d0544b7e3677df6d14c6a321080abe15ab29a8f376beacc35573faf38bf

See more details on using hashes here.

Provenance

The following attestation bundles were made for bellbook-0.5.0-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on bellbook-ai/bellbook

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

Release history Release notifications | RSS feed

0.6.0

4 files

This release

0.5.0 This release

4 files

0.4.0

4 files

0.3.0

4 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