Skip to content

StartOverview

Portable records for consequential actions.

Create an ActionReceipt when your application buys work, calls a tool, or accepts a result. Keep it with the supporting evidence so another system can inspect the record later. Local receipt checks do not require the original agent or platform.

Bulla creates and verifies portable ActionReceipts, applies receiver-supplied policies, reconciles receipt sets with application records, and captures completed stdio MCP calls. The application retains the transaction record alongside its evidence, so it can inspect the delivery after the original process is gone.

Bulla 0.49.4 · Python 3.10+ · Apache-2.0

Bulla Labs maintains this software alongside its applied research. Use Bulla on its own; the laboratory’s research and intellectual foundations provide additional context.

MCP capture is included in Bulla 0.49.4. It emits ActionReceipt v0.4, an experimental draft format; v0.2 remains the normative default for the general receipt tools.

Application code creates the receipt around the consequential call, so the model never has to generate the JSON. The receiver retains the file and applies its own verification context and policy.

$ python -m pip install "bulla==0.49.4"
$ bulla demo

This local scenario uses wrap_action to emit one receipt, checks a changed copy, and compares the receipt set with two customer-log entries. No payment network is contacted.

Each run creates a fresh directory. Look for its path on the final line after artifacts, then set BULLA_DEMO_DIR to that path, as shown in the quickstart.

Open receipts/pay_demo_042.json from that directory in Inspect a receipt. The browser reads that exact file and checks its structure and integrity without uploading it. Signatures, supporting files, receiver policy, and coverage remain separate checks.

bash
BULLA_DEMO_DIR="/paste/the/artifacts/path/here"
$ bulla receipt drill "$BULLA_DEMO_DIR/receipts/pay_demo_042.json" --format json

Run the drill to compare Bulla with the packaged standalone checker while network operations are denied. Output separates checks over saved files from questions that need another source.

Download the retained verification kit for offline command-line checking.

Verification kit details

Keep the archive and detached digest with the receipt set. Its manifest covers every member, and the signed release receipt authenticates the published archive.

Kit SHA-256: 8f2cdd16bcbd1a1121f49545b6a6512872b188221ca30ec054dfd6b2fb2142ab

Create a receipt around the consequential call

python
from bulla import wrap_action

with wrap_action(
    "payments.charge",
    {"event_id": "pay-1", "amount_minor": 12500},
) as action:
    receiver.charge(amount_minor=12500)

receipt = action.receipt

Read the Python integration guide →

A receiver is the system inspecting a record. A supplier can receive an order or authorization; a purchaser can receive a delivery. Receipt checks alone establish neither authorization nor payment assurance. How local policy differs from agreed terms.

One transaction, three records

The provider reports the action, an ActionReceipt crosses the boundary, and the receiving system compares the receipt with its own record.

Provider record → ActionReceipt → Receiver record

Provider-side log

Internal operational log

Provider systems keep this log for their own operation.

not supplied to this check

Retained boundary artifact

ActionReceipt

event
pay_demo_042
amount
USD 125.00
original integrity
CHECKING
changed copy
CHECKING

Customer record

Observed actions

actions
—
matching receipts
—
coverage
CHECKING

Computing receipt integrity and coverage…

Integrity checks the receipt in hand. Reconciliation compares the receipt set with the customer’s supplied action record.

This control changes an amount without recomputing the stored commitments. It does not authenticate the issuer or prove that a payment occurred. Reconciliation can find only actions present in the supplied customer record.

Inspect the receipt computation
Inputs
Customer actions pay_demo_042 and pay_demo_043; one receipt for pay_demo_042.
Checks
Recompute the stored commitments and compare bound action identifiers.
Result
Original record integrity VERIFIED to digest; coverage 1/2; unmatched pay_demo_043.
Boundary
An action omitted from both supplied inputs remains invisible.
Receiver suppliesBulla computesNever inferred
Receipt bytesRecord integrity and declared-convention checksWorldly truth or occurrence
Trusted keys or rootsSupported signature and inclusion checksKey custody or signer independence
Receiver action recordActions without matching receiptsCompleteness of that record
Pinned policy, time, and revocation contextRELY, REFUSE, or ESCALATEPolicy suitability, custody, or settlement

Why not signed JSON?

Signed JSON can carry the same facts. In our scheduling experiment, matched signed records produced the same decisions as ActionReceipts. Bulla supplies a versioned record format, local verification tools, receiver-policy evaluation, and receipt reconciliation. The adoption question is whether a shared convention removes enough bespoke coordination to justify producing, retaining, checking, and maintaining it. A competent conventional arrangement may suffice. Reduced integration effort and interoperability between independently operated systems remain unmeasured.

Four tasks

  1. 01CreateEmit a portable transaction record where an application accepts or completes an external action.
  2. 02CheckRecompute a saved receipt locally without contacting the provider.
  3. 03DecideApply a supplied receiver policy before another consequential action.
  4. 04ReconcileCompare a receipt set with customer records and identify actions with no receipt.

What ships where

SurfacePublic state
BullaPublished Python package 0.49.4
ActionReceipt v0.2Normative stable format
ActionReceipt v0.3Non-normative released draft
ActionReceipt v0.4Opt-in experimental draft
Answerability profilesRepository-source research profiles

Beyond the released tools

These repository-source experiments study institutional arrangements around records. They are not services supplied by the installed package.