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:
1typeClaimstruct{ 2IDuint64 3Subjectstring 4Predicatestring 5Objectstring// the (S, P, O) triple 6Authoraddress 7Confidenceuint8// 0..100 8StatusStatus 9Supports[]Endorsement10Contests[]Endorsement11Evidence[]Evidence// commitments to off-chain material12SupersededByuint6413Supersedesuint6414// ...15}
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 superseded and
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),10id,"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.
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.
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.
Overview
Package gnomem is a shared, contestable memory for multiple agents.
Most "agent memory" products store text and retrieve similar chunks. That works for one agent talking to itself. It breaks the moment several independent agents — possibly run by different people, on different models — must maintain a *shared* understanding of the same world and sometimes disagree about it.
gnomem models memory not as text but as a graph of structured claims. Each claim is a (subject, predicate, object) triple with an author, evidence and a confidence. Other agents can support it, contest it, add evidence, supersede it with a better claim, or trigger adjudication. No agent can silently erase an inconvenient finding: claims can be superseded or retracted, but the history stays visible and ordered.
The point of the demo is the structure, not access control: anyone may write. Gating *who* may write to which claim is exactly what the capability-wallet demo adds on top.
1const(2StatusProposedStatus="proposed"// asserted, no endorsements yet3StatusSupportedStatus="supported"// has support, no live contest4StatusContestedStatus="contested"// at least one live contest5StatusAcceptedStatus="accepted"// adjudicated true (terminal)6StatusRetractedStatus="retracted"// adjudicated false / withdrawn (terminal)7StatusSupersededStatus="superseded"// replaced by a better claim (terminal)8)
ResolveClaim adjudicates an open claim as accepted (true) or retracted (false/withdrawn). The resolver's address is recorded — resolution is itself a provenance-bearing act, not an anonymous verdict.
SupersedeClaim replaces an open claim with a new one. The old claim is marked superseded (terminal) and linked to its replacement, so the correction is visible rather than a silent overwrite.