README.md
GnoMem — can autonomous agents share a memory without sharing a database operator?
Most "agent memory" products are a vector store: dump text, retrieve similar chunks. That is fine when one agent is talking to itself. It falls apart the moment several independent agents — different owners, different models, run at different times — have to maintain a shared understanding of the same world and occasionally disagree about it.
Whoever operates the database wins every disagreement. They can silently edit a memory, drop an inconvenient finding, or reorder history, and no other agent can tell. The question this demo asks is: what does shared agent memory look like when nobody owns the database?
Memory as a contestable claim graph
The core move is to stop storing memory as text and start storing it as a graph of structured claims:
1type Claim struct {
2 ID uint64
3 Subject string
4 Predicate string
5 Object string // the (S, P, O) triple
6 Author address
7 Confidence uint8 // 0..100
8 Status Status
9 Supports []Endorsement
10 Contests []Endorsement
11 Evidence []Evidence // commitments to off-chain material
12 SupersededBy uint64
13 Supersedes uint64
14 // ...
15}
A claim moves through an explicit lifecycle:
proposed → supported → contested → { accepted | retracted | superseded }
The terminal states are the interesting design decision. An agent that dislikes a claim cannot delete it. It can:
- contest it (with refuting evidence), flipping it to
contested; - supersede it with a better claim — the old one becomes
supersededand is linked to its replacement, so the correction is a visible edge in the graph, not an overwrite; - retract it via adjudication.
History stays visible and ordered in every case. Support never silently overrides a live contest, either: a contested claim stays contested until someone adjudicates it.
The canonical run
1// A researcher proposes.
2id := gnomem.ProposeClaim(cross(cur),
3 "foo/v2", "is", "safe to deploy", "report#H1", 82)
4
5// A skeptic contests, with an exploit.
6gnomem.ContestClaim(cross(cur), id, "unbounded allocation", "exploit#H2")
7
8// An adjudicator supersedes with the corrected claim.
9newID := gnomem.SupersedeClaim(cross(cur),
10 id, "foo/v2", "is", "unsafe before commit abc123", "report#H3", 95)
Render the graph at the realm root, and any claim's full argument tree —
support, contest, evidence, supersession links — at :<id>. You get a
"view source for the argument": not just the current answer, but how the
agents got there and who dissented.
# Claim #1
> foo/v2 — is — safe to deploy
- Status: ♻️ superseded
- Superseded by: #2
## ⚔ Contest (1)
| skeptic | 0 | unbounded allocation | 12 |
Why Gno specifically
- The claim graph is ordinary persistent objects — structs, slices, pointers — not hand-serialized contract storage. You write Go, the graph persists.
- Every realm has
Render, so the argument tree is browsable in a normal web view with no separate frontend. - Because it's an importable package, a research-protocol realm can sit on top and enforce process: "≥3 independent agents, each must cite evidence, one assigned devil's advocate, 2/3 needed to accept, unresolved disagreements stay visible."
What this demo intentionally leaves out
Access control. Anyone can write to any open claim here, because the point is the structure of contested knowledge, not who's allowed to touch it. Gating "which agent may support/contest/resolve which claim, under what budget" is a capability question — a natural next realm, not this one's job.
There's also no economic layer: no staking behind a claim, no reward for finding the flaw that gets a claim superseded, no bond to slash for bad adjudication. Those make the incentives real, and they compose on top of this graph rather than being baked into it.
Run the tests:
1gno test .
The uncomfortable truth it's built around: different agents will always produce incompatible, mutable, poorly-sourced views of the same world. You can't prevent that. You can refuse to let any one of them quietly win.
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.