README.md
Agent Receipts — provenance is not correctness
"Put it on the blockchain and now it's trustworthy" is one of the most durable misunderstandings in the space. A chain can prove a handful of things very well:
- who committed to an output (a signature),
- when they committed to it (ordering),
- that the bytes haven't changed since (integrity),
- what was staked or attested behind it.
It cannot, by itself, prove the output is correct. Integrity is "these bytes haven't changed." Truth is "the content of these bytes is right." A hash gives you the first for free and tells you nothing about the second.
This realm takes that limitation seriously and builds the useful thing that remains: an append-only log of execution receipts whose trust level is exactly the set of independent attestations they've collected — no more.
A receipt is commitments, not payloads
1type Receipt struct {
2 Seq uint64
3 Agent string // e.g. a passport agent id
4 TaskHash string // commitment to the task spec
5 InputCommitment string
6 OutputCommitment string
7 RuntimeID string // which runtime/model produced it
8 PolicyVersion string // policy in force at execution time
9 ToolCallsRoot string // root hash over the tool-call trace
10 HumanIntervened bool
11 Author address
12 Height int64
13 Attestations []Attestation
14}
Nothing here is the actual data. The transcript, the diff, the dataset, the full tool trace — all of that lives off-chain (content-addressed storage, a git commit, an artifact store). The chain stores commitments to them plus the lifecycle. This is the sane split: chains are terrible databases and excellent notaries.
Validation is a separate, explicit step
A fresh receipt is unverified by construction. Its render says so:
Unverified. This receipt proves the commitment above was made, nothing more.
Independent validators then attach verdicts:
1receipt.Attest(cross(cur), seq, receipt.VerdictReproduced, "re-ran, matched")
2receipt.Attest(cross(cur), seq, receipt.VerdictTestsPass, "suite green")
Two rules make the attestations mean something:
- the author cannot attest to their own receipt — self-attestation proves nothing;
- a validator cannot attest twice — one identity, one voice.
Confirmations(seq) returns (positive, rejections) as a raw count, and
deliberately not a boolean "is it true." The realm refuses to collapse
independent verdicts into a verdict of its own; the caller decides what
threshold it trusts (2-of-3? a specific validator set? a bonded quorum?).
That decision doesn't belong to the log.
The demo scenario
Three coding agents each fix a failing package and record a receipt committing
to their patch. CI publishes a tests-pass attestation; a reviewer agent
publishes reproduced or rejected. Every receipt — winner and losers —
stays browsable at :<seq>, so "why did we ship this patch and not that one"
is answerable months later.
1seq := receipt.Record(cross(cur),
2 "percy", // agent
3 "task#H", // task commitment
4 "in#H", "out#H", // input / output commitments
5 "claude-opus-4-8",
6 "policy-v1",
7 "tools#H", // tool-call trace root
8 false, // human intervened?
9)
Run the tests:
1gno test .
Honest limitations
- Attestations are only as good as the validators. This realm gives you the structure for independent verification; it does not solve validator Sybil resistance or collusion — that needs bonding, random selection, or a jury protocol layered on top.
- Commitments prove integrity, not that the committed artifact was ever produced honestly. A receipt is evidence in an audit, not a guarantee.
Which is the whole point: the receipt makes agent actions auditable and non-repudiable, and stops there. Correctness is earned by the attestations, out in the open, one verdict at a time.
Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.
Dependency graph:

⚠️ Disclaimer: provided as-is, without warranty; not security-audited. Full disclaimer: DISCLAIMER.