Register as a producer
Publish anchors for your own signed trust records under your own key. The conventions, naming, and submission path are documented in the repository.
Read the contributor guide →The TRACE Registry is a public logbook for signed receipts of what AI agents did. Entries can be added but never edited or removed, and the whole log is a set of files anyone can download and check on their own computer, with no account. Two things need evidence from outside the log: who really controls the signing key, and whether everyone is being shown the same history.
Counted at registry commit ba566ed (October 6, 2026). The first two entries (June 12 and September 1) were produced by us and are not production evidence. The third, anchored September 25, is the first from an outside producer: one software-only record from a real run of Bernstein 3.20.0 (trace-registry #85). Checkpoint 1 has an outside witness receipt; checkpoint 2 does not. The verifier on PyPI is trace-verify 0.4.3.
| Term | What it means here |
|---|---|
| Transparency log | A public list that can only grow. Anyone can download it, and old entries cannot be changed without the change showing up. |
| Anchor | A short fingerprint of a signed receipt. The registry stores the fingerprint, not the receipt, so the receipt itself stays with whoever made it. |
| Checkpoint | A signed snapshot of the whole log at one moment: how many entries it holds, one fingerprint covering all of them, and the same two facts from the snapshot before. If anyone rewrites an earlier entry, the snapshots stop matching. |
| Witness | An outside party, run by someone else, that signs a receipt saying it saw a given checkpoint. A witness makes it harder for the log to quietly show different histories to different people, but catching that still needs people to keep and compare what they were shown. |
| Mirror | A full copy of the log kept by another organization, so the history does not depend on one operator staying honest or online. |
A signature proves a record has not been changed. It does not prove that everyone is seeing the same set of records. An operator who shows one history to an auditor and a different one to everyone else has defeated the point, and signing alone cannot catch that.
"Trust our database" fails in exactly the moments a registry exists for: disputes, audits and attacks. So the rules are simple and testable. The log only grows, and proving that is cheap. It can be checked offline. Nothing sensitive leaves the producer by default. And over time, its integrity is backed by parties the operator does not control.
This is the first signed snapshot of the log, from the file registry/2026/09/01.ndjson. It says the log held one entry, gives the fingerprint covering it (root), and records that the snapshot before it was empty (prev_size 0). A second checkpoint, signed September 25, 2026, extends it to cover the third entry.
The key_id is the public half of the signing key. A matching signature shows the snapshot was signed with that key. It does not tell you who holds the key; check that separately before you trust the signer.
A checkpoint holds fingerprints, never the content of any receipt. It is a few hundred bytes describing the shape of the log. The receipts themselves stay with whoever produced them.
The key_id is the raw 32-byte Ed25519 public key in hex. The verification command below reads the complete checkpoint, including its signature, and checks it against that key.
Whoever runs the agent signs the receipt with their own key, on their own system. The registry never sees a private key and never signs for anyone.
The registry stores a short fingerprint calculated from the exact signed receipt, not the receipt. Change one character of the receipt and its fingerprint no longer matches.
A short proof can show that one entry is in a given snapshot, and another can show that a later snapshot contains everything in an earlier one. Keep the snapshot that goes with each proof.
On a schedule, the registry signs a new snapshot that also names the snapshot before it. A checker confirms the link, confirms the proof that the log only grew, and recalculates the fingerprints from the entries themselves.
Each anchor leaf is derived from the exact signed bytes under Anchor Format v1. Checkpointed entries accumulate in a Merkle Mountain Range (MMR). Inclusion proofs bind an entry to a particular root; consistency proofs connect an earlier root to a later one. Each signed checkpoint carries the log's size and root plus the previous checkpoint's size and root. A verifier checks predecessor linkage and the MMR consistency proof, then recomputes the covered entries. Equality of the previous size and root alone does not prove append-only growth.
On September 7, 2026, we sent checkpoint 1 to a witness run by a separate operator. The witness signed a receipt saying it had recorded that checkpoint. The receipt we got back matches two copies fetched separately, and anyone can check it offline against the witness's published key.
The receipt proves the witness saw checkpoint 1. It does not prove when, it does not vouch for the log's later history, and the registry's own signature is checked separately.
Checkpoint 1's signing-body digest is included under a Merkle root signed by the witness, and verification runs against an explicitly pinned witness key. This was demonstrated ahead of the September 9 briefing. The response reports countersigned-observed. Whether a receipt carries a witness time or a signed grade is a property of that receipt rather than of the profile, so the verifier reports witness_time_established and grade_cryptographically_bound instead of asserting either. Both are false for the September 7 capture and stay false for it: that receipt's protected header is algorithm and tree profile only, and the witness signature covers that header, so a receipt carrying either field is a separately signed receipt rather than this one re-read. The witness deployed support for both fields on September 12, 2026, and that does not change this capture: it registers a checkpoint by a content-addressed entry hash and deduplicates on it, so re-submitting checkpoint 1 returns the original receipt. Because that hash is derived from the signed fields rather than the submitted bytes, reformatting the submission does not produce a new one either. A receipt carrying a witness time therefore requires a checkpoint the witness has not seen. The receipt does not certify registry continuity. It authenticates inclusion of the signing-body digest, with the registry signature checked separately.
The registry does not yet send every new checkpoint to a witness, and there is no second witness. More independent witnesses can be added as a deployment choice. The original receipts stay with their holders throughout.
Receipt, key provenance and offline verificationThree commands download the log and check it on your computer. The checker confirms each snapshot's signature, confirms each one only adds to the last, and recalculates the fingerprints from the entries. It does not tell you who the signer is just because a snapshot names a key.
Use Python 3.11+, Git, and Bash on macOS, Linux, or Windows with WSL. Create an isolated environment before installing.
python3 -m venv trace-verify-env source trace-verify-env/bin/activate python -m pip install trace-verify
The entire published history is in the repository. There is nothing held back on a server.
git clone https://github.com/agentrust-io/trace-registry cd trace-registry
Checks each snapshot's signature against its own key_id, then checks that each one extends the last and matches the entries it claims to cover.
python tools/verify_checkpoint_chain.py \ registry/2026/06/12.ndjson \ registry/2026/09/01.ndjson
Expected: OK: with the verified checkpoint count, MMR size, and root, then exit 0. FAIL: exits 1. "No entries with mmr_checkpoint" means nothing was verified. This command checks the two named historical files, not every later registry entry.
An entry in the registry shows a receipt existed and has not changed since. It does not show the receipt's claims are true, and it does not vouch for whoever produced it. The time on a checkpoint is the signer's own statement; no outside party confirmed it.
| Limit | Why it stands |
|---|---|
| It cannot show what was never sent | The snapshots prove that what they cover has not been altered. They cannot prove every receipt that should be here was sent. Completeness depends on producers keeping their own records. |
| The June 2026 entry is outside the chain | It was published before snapshots started, and it is deliberately not added after the fact. Backdating it in would make the chain claim more than it checked. |
| One witness receipt, with limits | The receipt proves the witness recorded checkpoint 1. It does not confirm a time or a grade, vouch for later history, stop the log showing different histories to different people, or cover the June entry or checkpoint 2. See the evidence packet and verifier results. |
| One producer key is used once by design | The key behind the first anchored record will never sign another, because the demo that made it creates a fresh key each run and never saves the private half. That is true of that entry only, not a general guarantee. |
A witness attesting to more than it checked is worse than no witness. That principle is why the limits above are on this page instead of in a footnote, why the entry counts here are the real ones, and why the receipt announcement names exactly which properties were verified.
Publish anchors for your own signed trust records under your own key. The conventions, naming, and submission path are documented in the repository.
Read the contributor guide →Depending on one operator is a weakness, and we say so. Copies kept by others, and witnesses run by others, reduce it when people keep and compare what they were shown. Two organizations outside AgenTrust already run registered mirrors. Neither mirrors nor witnesses fully stop a log from showing different histories to different people.
Mirroring guide → Witness guide →The most useful contribution is a demonstration that something on this page overstates what the code actually does. Open an issue in public.
Open an issue →