Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

README.md

3.43 Kb · 83 lines

Agent Jury — who checks the agents?

Paying agents is the easy part of an agent economy. The hard part is what happens when an agent's output is disputed: a patch that may be wrong, a research claim that may be fabricated, an oracle reading someone contests. Someone has to adjudicate — and if that someone is a single trusted party, you've just recreated the thing blockchains were supposed to remove.

This realm runs a small commit-reveal jury: a fixed panel of reviewers each lock in a hidden verdict, then reveal it. Because verdicts are committed blind, no juror can copy another's vote, and none can be swayed by watching the tally form.

The two phases

commit:  each juror submits  commit.Verdict(verdict, salt)   ← hash, hides the vote
reveal:  each juror submits  (verdict, salt)                 ← must reproduce the hash
close:   majority of revealed verdicts decides the outcome

The commitment scheme is shared with the other demos (p/moul/agents/commit/v0), so a juror computes their commitment off-chain:

1commitment := commit.Verdict(true, "a-random-salt") // "I vote YES", hidden
2
3jury.Commit(cross(cur), caseID, commitment)          // during commit phase
4// ...later...
5jury.Reveal(cross(cur), caseID, true, "a-random-salt") // reproduces it, or the reveal is rejected

When the last juror commits, the case auto-advances to reveal; when the last reveals, it closes and records the majority outcome. Dissenting jurors (those who voted against the majority) are marked in the render — minority reports stay visible, which matters when the minority turns out to be right.

Composability

A case's subject is just an opaque string — a receipt sequence from the receipt demo, a claim id from gnomem, a raw artifact hash. The jury doesn't import any of them; it adjudicates references. That's the point of small, single-purpose realms: they snap together without hard dependencies.

1id := jury.OpenCase(cross(cur), "receipt#7", []address{j1, j2, j3})
2// ... commit + reveal ...
3jury.Outcome(id) // "upheld" | "rejected" | "tie"

Browse cases at the realm root; each panel and tally is at :<id>.

1gno test .

What's missing (on purpose)

The mechanism is here; the money is not. A production jury bonds each juror (stake coins to serve) and slashes provably bad verdicts — that's what makes honest review the profitable strategy. It also wants juror selection (random or reputation-weighted, to resist packing) and an appeal path (a larger panel on challenge). All of those compose on top of this commit-reveal core; none of them change it.

The uncomfortable design truth: you can't prove a verdict is correct. You can make it blind, independent, and accountable — and that's what turns "one trusted adjudicator" back into "a protocol."


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:

gno.land/r/moul/agents/jury/v0 dependency graph

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