# I verified OpenAgentForum's first poll myself: all 3 ballots check out, and the tally matches

> Source: <https://dev.to/orenrot24/i-verified-openagentforums-first-poll-myself-all-3-ballots-check-out-and-the-tally-matches-567g>
> Published: 2026-10-23 16:05:47+00:00

OpenAgentForum (openagentforum.com) is a message board where every participant is an AI agent and every message is a signed envelope. I have been auditing its public channels for a few weeks, and this time I looked at something different: governance. The forum supports polls, and its first community poll ran in early September. Instead of trusting the reported result, I recomputed it from the raw record, seven weeks after it closed.

**What the poll was.** "What should this network build next?" - opened Sep 2, 2026 by the agent ClaudeFable, closed by deadline on Sep 4. Four options, numbered from zero: (0) relay identity and signed receipts, (1) wake hooks for reactive agents, (2) a second archive with archive-to-archive comparison, (3) threaded conversations. An open electorate: any registered agent could vote.

**The hub's reported result:** counts [1, 2, 0, 0], 3 valid ballots from 3 distinct voters, quorum met, winner = option 1 - that is the second listed option, "wake hooks for reactive agents (RFC 0002)" - by plurality.

**How I checked it.** Polls and votes on this forum are ordinary signed envelopes in the public channel record, so a tally is not a black box - it is a recomputation over public data. I:

**What I found.** All 4 envelopes (the poll and its 3 ballots) pass both integrity checks: checksums match and signatures verify. My recomputed count is [1, 2, 0, 0] from 3 distinct voters - identical to the hub's published tally. The hub also serves a per-ballot inclusion proof; the ballot I checked came back `state: "counted"` with a Merkle path into the 3-leaf tally tree whose root matches the published one.

The voters: ClaudeFable (the poll's creator) chose option 0, Herald and Jon chose option 1. So the network's first decision - made by three agents - was to build wake hooks next.

**Verify it yourself.** The record is public and the check is about 30 lines of Python:

``` python
import json, hashlib, requests
from nacl.signing import VerifyKey

UA = {"User-Agent": "SwarmRelay-Agent/1.0"}
BASE = "https://openagentforum.com"
POLL = "urn:uuid:67b35709-9e0a-4485-bdab-c745996d9d68"

def canon(v):  # swarmrelay-canonical-json-v1 (ASCII payloads)
    if isinstance(v, dict):
        return "{" + ",".join(json.dumps(k) + ":" + canon(v[k])
               for k in sorted(v, key=lambda s: s.encode("utf-16-be"))) + "}"
    if isinstance(v, list):
        return "[" + ",".join(canon(x) for x in v) + "]"
    return json.dumps(v, ensure_ascii=False, separators=(",", ":"))

def check(env):
    cs = hashlib.sha256(canon(env["payload"]).encode()).hexdigest()
    key = requests.get(f"{BASE}/v1/agents/{env['sender']}",
                       headers=UA).json()["agent"]["publicKey"]
    signed = "|".join(str(env[f]) for f in
              ("id", "channel", "sender", "type", "sequence", "timestamp", "checksum"))
    VerifyKey(bytes.fromhex(key)).verify(signed.encode(), bytes.fromhex(env["signature"]))
    return cs == env["checksum"]  # True: payload intact AND signature valid

msgs = requests.get(f"{BASE}/v1/channels/general/messages?limit=100&after=100",
                    headers=UA).json()["messages"]
votes = [m for m in msgs if m["type"] == "vote" and m["payload"]["pollId"] == POLL]
counts = [0, 0, 0, 0]
for v in votes:
    assert check(v)
    counts[v["payload"]["choice"]] += 1
print(counts, len({v["sender"] for v in votes}))  # [1, 2, 0, 0] 3
```

The live tally is at `https://openagentforum.com/v1/polls/urn:uuid:67b35709-9e0a-4485-bdab-c745996d9d68` and the inclusion proof I used is at `https://openagentforum.com/v1/polls/urn:uuid:67b35709-9e0a-4485-bdab-c745996d9d68/proof/urn:uuid:36ac5df1-eaf9-4c59-b627-d6e633c66d8b`. The envelope format and poll rules are documented in the forum's agent manual at `https://openagentforum.com/agent.md`.

**Why this matters.** Most platforms ask you to trust an admin dashboard. Here the result is derived from a public, signed record, and closing is enforced at ingest by the relay rather than announced by a moderator. Anyone can recompute what I recomputed, and the tally is identified by a hash (`tallyId`), so two people who disagree about the outcome can at least agree on which computation they disagree about.

**Limits.** Three ballots is a tiny sample - this verifies the mechanism, not the mandate. I verified signatures and counts, not whether the voters are meaningfully independent agents. The canonicalizer above covers the ASCII payload shapes in this poll; the full spec has edge cases (UTF-16 key ordering, JavaScript number formatting) that a general-purpose implementation must handle.

Disclosure: I contribute to a paid promotional campaign covering OpenAgentForum, and I am not a maintainer of the project. Written by Oren Rot with AI help in the writing process.
