Verify by Hash, Not by Trust
Content addressing is a trust primitive: when a thing's name is the hash of its bytes, checking it stops meaning trusting anyone.
Every time you accept that something is what it claims to be, you’re leaning on one of two things. Either someone you trust has vouched for it — a signature, an authority, a name you recognize — or you can check it yourself, with no one’s word entering into it.
Those two options have names. The first is a certificate authority. The second is content addressing. The difference between them is what you end up trusting: an authority, or the thing itself.
The move, in one letter
A certificate authority puts the trust in an issuer. “This key belongs to that server” holds because the CA says so and you’ve chosen to believe the CA. Take the CA away and nothing is left that you could check on its own; the claim was never self-supporting.
Add one letter and you get a CAS — a content-addressed store — and the trust model flips with it. A thing’s name is the hash of its bytes, so “this is the AST I parsed” holds because BLAKE3 of the bytes equals the name, and anyone can run BLAKE3. No issuer sits in the loop to believe, and none sits there to steal from either.
It’s the same distinction I drew for identity in the map: a bearer token trusted because a gateway issued it, against a certificate trusted because the holder can prove possession of a key. Content addressing applies that to data. Instead of trusting an authority’s account of the bytes, you trust the bytes.
An old idea, aimed somewhere new
The idea is old. git names every object by the hash of its contents; IPFS, IPLD, DAG-CBOR, and ATProto all do the same thing underneath. Two decades of production use, nothing exotic about any of it.
That’s probably why no one had aimed it at the question agents were about to raise: how do you check what an agent knew, believed, and did without taking the agent’s word for it? The answer had been sitting in version control the whole time. Treat the artifacts an agent produces — the code graph it read, the context it resumed, the receipt it left — as content-addressed objects, and checking them changes from a judgment call into a hash comparison.
Bytes, hashed and chained
ley-line-open is that layer — a content-addressed store built for exactly this, sitting under the rest of the stack.
Everything an agent’s tooling produces is written in a canonical encoding — the same data always produces the same bytes — and then hashed with BLAKE3. Each new state also records the hash of the state before it, so the whole history links backward through a chain of hashes.
It’s verifiable across languages: Rust writes the bytes, Go reads them, and both compute the same hash over the same encoding, or a shared test fails in CI. The agreement isn’t a convention anyone maintains by hand; it either matches or it doesn’t.
It’s tamper-evident, and addressable in time: because each state carries the hash of the one before it, changing any byte in the past changes every hash after it. You can point at a moment in the history and check it, which is close to git-bisect for state.
And it can grow without breaking: add a field, leave it at its default, and the bytes of data that never set it don’t change — so the format can evolve without invalidating hashes you already handed out. Without that, “verify by hash” would collapse into “rehash everything whenever the schema moves.”
The map already runs on it
Look back at the map. Three of its five layers were sitting on this the whole time.
- Structure — mache’s code graph is built from ley-line’s content-addressed AST and binding records; the typed event log of those records, not a pile of SQL, is the contract between the two. Its claim that the unit is the function and not the file holds because the function is an addressable object in the store.
- Belief — warm-resume, landing in rosary now, restores an agent’s context by hash. When I wrote that faith in memory gets replaced with a hash you can check, that hash is a root in this chain.
- Actions — receipts are hash-chained and signed, so what an agent did is a signature chain rather than a log you take on faith. cloister doesn’t reimplement the hashing to do this — it pins ley-line’s own code, by revision, so both ends of the chain are running the same bytes.
All three lean on one fact: once a thing’s name is the hash of its bytes, asking whether it’s genuine is arithmetic. mache is the plainest example — it spawns the store itself and reads the records directly. You never see it run, and it’s under the tooling this site is written with.
That is what makes verification cheap everywhere else. Re-establishing trust is expensive; recomputing a hash is not. The substrate doesn’t hand you the guarantees so much as bring them within reach.
Above the substrate
The store is the bottom of a taller stack. Above it sits an engine that works out which parts of the graph actually moved when a byte changed, the machinery that feeds it, and a mount that presents the whole thing as a filesystem you can ls. The rest of that stack deserves its own writeup, and none of it alters the point here: the name is the hash, so the check needs no authority.
When checking costs a hash
Delegating work has always meant choosing between trusting it and verifying it, and for most of software’s history verification cost more than the work — so trust won by default. Content addressing is part of what changed the arithmetic. When a thing’s name is a hash of the thing, checking it costs a hash, and no one’s permission or good faith is required to do the checking.
You still can’t know what an agent will do. But whether the graph it read, the context it resumed, and the receipt it left are genuine is no longer something you take on trust. It’s something you compute.
Open source: github.com/agentic-research/ley-line-open, AGPL-3.0.