Direct answer
AER-1 in Python
Python is the shortest path into AER-1. The conformance runner is a single Python file in the open kit: clone the repository, run it with Python 3, and you have exercised the full draft -24 corpus, 119 vectors and 122 checks, with no other dependencies to install. From there, the same ideas verify a live receipt and emit receipts from your own Python agent code.
Updated October 20, 2026.
Run the Python conformance runner
Two commands, needing only git and Python 3:
git clone https://gitlab.com/rambozambodotdev/zambo.git
python3 aer-1/conformance.py
Exit 0 means every valid vector verified, every altered or invalid vector was rejected for the stated reason, and every boundary case landed on the side the draft specifies, including the id-binding outcomes from draft -21 and the anchor outcomes from draft -23. A failure names the check, and the check names the section of the draft to re-read. The runner is one of the kit's runners in 7 languages, and the runners cross-verify: 52 agreements and 0 disagreements at kit 1.5.6.
Verify a live receipt, worked end to end
Use a real record: https://zambo.dev/run/28c79cde-20a0-48a3-b4ec-e5d0e3ac104d, a delivery receipt from an independent verification service that ships AER-1 receipts with its work. The Python procedure is the draft procedure:
- Fetch the record and read its core fields: receipt id, tool, inputs reference, output hash, timestamps, and any anchors.
- Rebuild the canonical bytes from the record exactly as the draft specifies. This receipt publishes its canonical bytes: 2,078 of them.
- Recompute the hash. SHA-256 over those bytes gives
5f06acfbe2ff6254f7bd3a494ef9848551a0946a305d82c4ac9da410a07dd2a5, exactly the output hash the receipt carries. - Report each part separately: the digest check, the canonical reconstruction, the id state, and each anchor outcome, including any outcome that honestly comes back not checked.
Change one byte before hashing and the recomputed value diverges, and the check says so. No account and no permission are involved at any step.
Emit receipts from Python
Emitting is the mirror of verifying. When your agent makes a tool call, capture the call as it runs: the tool name, an inputs reference, the saved result, and the timestamps. Build the record's core fields, reduce them to the canonical bytes the draft specifies, compute the output hash over those bytes, and store the receipt with the hash committed. Add the receipt id as the record's locator, remembering the draft -21 rule: the id binds only via an expected id supplied externally or Section 9 resolution with digest comparison. Attach an external anchor only when you actually create one, and report its outcome under the Section 6 vocabulary. The kit's Python code is the reference for each of these steps, and the corpus tells you whether your emitter's output verifies the way the draft requires.
The PyPI package: aer1kit
For projects that prefer a package over a clone, the AER-1 kit is published on PyPI as aer1kit. Use the package for the library path and the repository for the draft text, vectors, and runners: the two version together, and the repository is where a question about a specific revision gets answered. Either way, finish by running the conformance corpus against your build before you call it conformant.
Cite this draft
Cite AER-1 as the IETF Internet-Draft draft-zambo-aer1, current revision -24, posted October 20, 2026 and expiring April 23, 2027, at datatracker.ietf.org/doc/draft-zambo-aer1.
@misc{zambo-aer1,
author = {Brennan Zambo},
title = {AER-1: Agent Execution Receipt, version 1},
howpublished = {IETF Internet-Draft draft-zambo-aer1-24},
year = {2026},
url = {https://datatracker.ietf.org/doc/draft-zambo-aer1/}
}Honest limits
The Python runner needs git and Python 3; this page claims no other tooling is required because the runner is built that way, and other stacks in your own project are your choice, not the kit's. The worked example verifies one live receipt; it does not certify the service that issued it or the work inside it. And the standing limit applies in Python exactly as everywhere else: a verified receipt proves the saved result was not changed after the fact, never that the work was correct.
Frequently asked questions
How do I run AER-1 conformance in Python?
Clone the kit repository and run the Python runner: git clone https://gitlab.com/rambozambodotdev/zambo.git, then python3 aer-1/conformance.py. Git and Python 3 are the only requirements, with no other dependencies. Exit 0 means your environment reproduces the corpus verdicts: 119 vectors and 122 checks at draft -24, kit 1.5.6.
How do I verify an AER-1 receipt in Python?
Fetch the record, rebuild its canonical bytes exactly as the draft specifies, recompute the SHA-256 output hash, and compare it with the hash the receipt carries. Then report the id state and each anchor outcome separately, including not checked for an anchor that was not evaluated. The worked example on this page, zambo.dev/run/28c79cde-20a0-48a3-b4ec-e5d0e3ac104d, recomputes to the exact hash its receipt commits to.
How do I emit an AER-1 receipt from Python?
Capture the tool call as it runs: tool name, inputs reference, saved result, and timestamps. Build the core fields, reduce them to the canonical bytes the draft specifies, compute the output hash over those bytes, and store the receipt with the hash committed. Add an anchor only when you actually create one, and report its outcome with the Section 6 vocabulary.
Is there an AER-1 package on PyPI?
Yes. The kit is published on PyPI as aer1kit, for projects that prefer a package over cloning the repository. The repository remains the home of the draft text, the test vectors, and the runners in 7 languages, and it is where questions about a specific revision get answered.
What does a verified AER-1 receipt prove in Python?
The same thing it proves in every language: the saved result was not changed after the fact, because the recomputed output hash over the canonical bytes matches the hash the receipt carries. It never proves the work was correct. Conformance means your Python code reaches the same verdicts as the corpus and the other runners, 52 agreements and 0 disagreements at kit 1.5.6.