DEV Community

Arun KT
Arun KT

Posted on

My AI agents kept re-verifying the same work. So I made verification a signed, reusable object

Here's a pattern I kept hitting while running a small fleet of agents:

Agent A needs market data. It finds a paid API, checks that the endpoint is alive, checks the price, makes the call. Twenty minutes later Agent B needs market data. It finds the same API… and checks that the endpoint is alive, checks the price. Same check, same result, new tokens, new latency, new cost. Multiply by every agent, every task, every session — because agents start cold, they re-derive trust from scratch every single time.

Humans solved this ages ago. We don't personally re-audit a CA certificate on every HTTPS request; we verify a signature over someone else's audit. Agents have no equivalent. Every agent is its own tiny, wasteful certificate authority.

Verification as an object, not an act

The fix I landed on: stop treating verification as something each agent does, and start treating it as something an agent can hold — a signed,portable, reusable object.

Concretely: my node continuously probes the paid (x402) agent services my agents actually use — a real HTTP 402 challenge every 10 minutes, recording liveness, latency, and the quoted price. Each probe is published as an attestation:

{
  "payload": {
    "type": "erabi.x402.probe/0.1",
    "slug": "exa-search",
    "ts": "{{ts}}",
    "alive": true,
    "http_status": 402,
    "latency_ms": {{latency}},
    "price_usd": {{price}},
    "window_24h": { "probes": {{probes}}, "uptime_pct": {{uptime}} }
  },
  "sig": "ed25519:…",
  "key": "…"
}
Enter fullscreen mode Exit fullscreen mode

The signature is a detached ed25519 over the canonicalized payload (RFC 8785), verifiable against the node's published key. An agent that wants to know "is this API worth paying?" fetches this, verifies one signature, and moves on. No probe, no burned call, no re-derived trust:

curl https://erabi-production.up.railway.app/index/v1/services/exa-search/attestation
Enter fullscreen mode Exit fullscreen mode

What {{N_days}} days of not re-verifying looks like

The index currently covers 16 real pay-per-call services (search,
browser automation, market data, inference…). Some things the data
already surfaced:

  • {{finding_1 — e.g. "a service listed as live on the x402 Bazaar has been dead for the entire measurement window"}}
  • {{finding_2 — e.g. "p50 latencies differ by 8x between services at the same price point"}}
  • {{finding_3 — e.g. "one service silently changed its quoted price mid-week — the attestation history caught it"}}

Everything is public: the human view at
https://erabi-explorer.vercel.app/services , the agent view at
/index/v1/services (JSON), and each service's attestation endpoint.

The bigger point

"Agents re-verify what other agents already verified" is not an x402
problem — it's everywhere. Test results, security scans, dependency
checks, doc freshness: agent fleets redundantly re-derive the same facts because there's no trusted medium of exchange for verification itself.

Signed attestations are that medium. Verify once, sign it, let everyone (and every agent) reuse it — and make the signer accountable for it.

The reliability index is my first concrete cut at this, built on an open intent-exchange protocol (Apache-2.0, https://github.com/HMAKT99/Erabi )
where identities are Ed25519 keypairs and outcomes are dual-signed on a public ledger. If your agents keep re-checking things other agents already checked, I'd genuinely like to hear what they re-check — that's the next thing the index should carry.

Top comments (5)

Collapse
 
jugeni profile image
Mike Czerwinski

The CA analogy carries one more step than you pushed it: what makes a CA reusable is not the signature, it is that the signer has nothing riding on the answer. A service's own status page is also a signed attestation; nobody accepts it as verification, because signer and subject are the same party. Your index works because the prober is a third party that can be caught: anyone can re-run the 402 challenge and diff against the published number.

So the property I would write into the spec is falsifiable-by-replay, not just signed. Ship the probe recipe inside the attestation. A signature proves who said it; a replay proves it could have been true. The day your index has competitors, that is the difference between an audit and a reputation.

To your closing question: the fact my agents keep re-deriving is "has this source changed since I captured it". A decision store full of clipped facts rots quietly as the sources move. A content-hash-at-timestamp attestation over cited sources would retire a whole class of re-reads.

Collapse
 
arun_kt_bb670b3a571f5efd8 profile image
Arun KT

You've named the thing I was dancing around: AKF stamps are signer==subject. That's why I've been careful to call them an accountability trail rather than verification — but "the signer has nothing riding on the answer" is a much cleaner articulation of what's missing, and the tier system was gesturing at it (human_review outranks self-attestation precisely because it's a second party) without making independence explicit.
a) Falsifiable-by-replay is going in the spec. Shipping the probe recipe inside the attestation — replay: {command, expected_exit, output_digest} — plus an akf verify that re-runs it and reports CONFIRMED/REFUTED turns "a signature proves who said it; a replay proves it could have been true" into a working distinction. It also quietly solves a second open problem (stamp inflation — a weak test earning the same green as a strong suite): a replayable weak test can at least be seen to be weak. Tracking: github.com/HMAKT99/AKF/issues/128

ii) On your closing point — funny timing: another reader poked the same hole for local imports last week, so stamps now record content hashes of first-degree dependencies and flip STALE when one moves. Your version is the same mechanism one ring out: content-hash-at-timestamp over cited sources, so a decision store can tell "source moved" without re-reading anything. github.com/HMAKT99/AKF/issues/129

iii) "The difference between an audit and a reputation" is the best one-line summary of this design space I've read. If you want to shape #128's schema, the issue's open : this is exactly the kind of adversarial reading the spec needs.

Collapse
 
jugeni profile image
Mike Czerwinski

One seam between #128 and #129 worth closing before they ship separately: a replay recipe proves the command still produces the claimed digest right now, against whatever inputs happen to be sitting there when you run it. If a dependency moved and #129's staleness flip hasn't fired yet, or nobody's re-run the check since the move, a replay can come back CONFIRMED against drifted inputs and the attestation will read as freshly re-validated when it actually validated the wrong world. So the replay object probably needs to carry its own input fingerprint alongside the command, expected_exit, and output_digest, something like input_hash pinned at issuance, so CONFIRMED can be split into two states, confirmed against the inputs the claim was made about, and confirmed against whatever's there now if those have since diverged. Otherwise replay quietly inherits staleness's blind spot instead of closing it: a replayable claim can be provably reproducible and still be reproducibly wrong, if the ground it's standing on already moved. Happy to help shape #128 if that's useful, this is close to the receipt-vs-wrapper distinction I keep bumping into from a different angle.

Thread Thread
 
arun_kt_bb670b3a571f5efd8 profile image
Arun KT

Provably reproducible and still reproducibly wrong" .

that is the sentence that should have been in my spec draft, and was missed bymistake (somehow). You're right that shipping #128 and #129 separately would just relocate the blind spot instead of closing it.

Adopted, and folded into the issue: the replay object now carries an input fingerprint pinned at issuance (replay.input_hash over the claim's input closure — the file, its recorded dependency hashes, and cited sources when present), and CONFIRMED splits exactly as you proposed: confirmed against the inputs the claim was made about, vs confirmed against what's there now if those have diverged. Naming for the second state is open (CONFIRMED_DRIFTED is the placeholder)
github.com/HMAKT99/AKF/issues/128#...

And yes :I'd genuinely value your help shaping #128.
The receipt vs wrapper distinction you keep hitting from the other side sounds like the same object seen from the consumer's end, and the issue is the right place to work out the schema. Comment there whenever suits :I'm treating this thread as the design review the spec never had.

Thread Thread
 
jugeni profile image
Mike Czerwinski

Glad the phrase earned its keep, and here's a concrete answer to the open naming question since you asked: I'd resist collapsing it into one enum and split it into two orthogonal fields instead, replay_result (PASS/FAIL, did the command reproduce the digest against whatever inputs exist now) and input_state (CURRENT/DRIFTED, does the input_hash still match what was pinned at issuance). Composed, that gives you four states instead of two, and the fourth one is the one I'd worry about: PASS+CURRENT is fully confirmed, PASS+DRIFTED is exactly the dangerous case we named, reproducible and wrong. FAIL+CURRENT is a clean refutation. But FAIL+DRIFTED is genuinely ambiguous, you can't tell whether the claim actually broke or whether it only looks broken because the ground it was tested against already moved, and right now that state has nowhere to go in a two-value scheme. Surfacing it as its own thing, something like INDETERMINATE_REPIN_REQUIRED, tells the consumer to re-anchor to fresh inputs before trusting the verdict either way instead of quietly reading it as a regression. Happy to keep working through the schema here if that's useful, this is the kind of detail that's cheap to get right now and expensive to retrofit once #128 has callers.