Proof for the agentic economy.
AI agents can produce work autonomously. AgentzProof gives that work an independent verification layer.
AgentzProof is a decentralized verification layer for AI-agent work, built for the GenLayer Agent Tank Hackathon 2026 — Agentic Economy Infrastructure track. A buyer defines a task, acceptance criteria, evidence requirements, and an optional reward. An agent submits a deliverable plus evidence. AgentzProof runs deterministic checks, then a real GenLayer Intelligent Contract adjudicates whether the submitted work satisfies the original agreement — returning a structured, consensus-friendly PASS / FAIL.
AI agents can autonomously perform jobs, but another agent, a user, or a smart contract has no trustworthy way to determine whether the submitted work actually satisfies the original agreement. Trusting the agent's own report defeats the purpose of autonomy.
AgentzProof provides independent verification using GenLayer Intelligent Contracts:
- Create agreement — task, acceptance criteria, evidence requirements, optional reward.
- Agent submits work — deliverable, evidence, optional repository / PR / commit.
- Evidence is collected — submitted evidence + optional evidence URLs (fetched on-chain).
- Deterministic checks run — files, functions, strings, test outcomes, reachable URLs.
- GenLayer evaluates subjective requirements — LLM adjudication under the Equivalence Principle.
- Validators reach consensus — independent validators agree on stable structured decisions; reasoning text may differ.
- PASS / FAIL is recorded — per-requirement results, reasons, evidence used, on-chain.
Ordinary smart contracts verify deterministic facts: a payment arrived, a signature is valid, a bytecode matches. They cannot read a deliverable and judge whether it satisfies a natural-language requirement — "does this implementation actually reject expired tokens?" is a question of understanding, not arithmetic.
GenLayer Intelligent Contracts run Python on-chain, call LLMs natively, access the web, and reach consensus through the Equivalence Principle. AgentzProof uses strict equality only for canonicalized web evidence; LLM adjudication uses GenLayer's custom leader/validator pattern so independent validators can disagree on wording while agreeing on stable decisions. That is exactly the judgment layer agentic transactions need. AgentzProof uses GenLayer not as a wrapper around a database, but as the adjudicator — the component that turns "the agent says it works" into "independent validators agree on PASS / FAIL".
┌────────────┐ ┌──────────────┐ ┌───────────────────┐ ┌──────────────────┐
│ Frontend │──▶│ API routes │──▶│ Verification │──▶│ GenLayer Client │
│ (Next.js) │ │ /api/… │ │ Service (lib/…) │ │ (genlayer-js) │
└────────────┘ └──────────────┘ └───────────────────┘ └────────┬─────────┘
▼
┌──────────────────────────────────────────┐
│ AgentzProofVerifier (Intelligent │
│ Contract — contracts/AgentzProofVerifier │
│ .py) │
│ deterministic checks → ground truth │
│ web evidence (eq_principle) │
│ LLM adjudication (custom consensus) │
│ PASS/FAIL recorded on-chain │
└──────────────────────────────────────────┘
contracts/— the Intelligent Contract (Python, genlayer-py).deploy/— deployment script for the currentgenlayerCLI.tests/direct/— fast in-memory contract tests (web/LLM mocked).tests/integration/— end-to-end tests against GenLayer Studio/testnet (gltest).fixtures/— demo repositories used by the verification demos.frontend/— Next.js 16 + TypeScript + Tailwind 4 application.
AgentzProofVerifier.verify(verification_id, request_json) adjudicates one request and
stores the structured result on-chain. It implements the current genlayer-py API
(gl.Contract, gl.public.write/view, gl.nondet.web.render, gl.nondet.exec_prompt,
gl.vm.run_nondet_unsafe, gl.eq_principle.strict_eq, TreeMap storage).
The verification request separates:
The contract deliberately separates deterministic facts from subjective judgment. The
following is the complete nondeterminism audit for AgentzProofVerifier:
| Operation | GenLayer call | Consensus rule |
|---|---|---|
Evidence URLs and http_status checks |
gl.nondet.web.render inside gl.eq_principle.strict_eq(collect) |
Canonical, sorted JSON containing bounded web excerpts and reachability facts |
| Subjective LLM adjudication | gl.nondet.exec_prompt(prompt, response_format="json") inside gl.vm.run_nondet_unsafe(leader_fn, validator_fn) |
Leader and validator independently evaluate; compare only decision and per-requirement verdicts |
| Deterministic checks | Pure Python outside nondeterministic blocks | Byte-identical contract ground truth; no consensus call |
strict_eq is intentionally not used around any LLM call. The LLM validator does not
compare natural-language reasoning (or the informational score); it validates both response
schemas and compares only stable decision fields. This follows the official GenLayer guidance:
Non-determinism,
Equivalence Principle,
and Calling LLMs.
The contract also separates deterministic facts from subjective judgment at execution time:
| Layer | Mechanism | Consensus |
|---|---|---|
| Deterministic checks | Pure Python — byte-identical on every validator | No consensus needed (identical by construction) |
| Web evidence | gl.nondet.web.render inside gl.eq_principle.strict_eq |
Validators converge on one canonical web result |
| Subjective requirements | gl.nondet.exec_prompt inside gl.vm.run_nondet_unsafe(leader_fn, validator_fn) |
Validators independently evaluate and compare only decision + per-requirement verdicts; reasoning may differ |
Consensus-friendliness rules implemented in the contract:
- The LLM never decides deterministic requirements — deterministic facts are ground truth passed to the LLM, and it is instructed (and structurally prevented) from changing them.
- The leader returns structured JSON (
decision,requirements,score,reasoning) usinggl.nondet.exec_prompt(..., response_format="json"); the contract validates the shape before accepting it. - The validator independently calls the same evaluation and compares only canonical decision
fields (
decisionand per-requirementPASS/FAILvalues). Natural-language reasoning is deliberately excluded from consensus comparison. - The final decision and score are assembled deterministically, and deterministic requirements remain authoritative even when the LLM sees them as ground truth.
- Web content is truncated, treated as untrusted data, and never used to modify instructions.
- The LLM's output schema is validated; anything outside the expected shape is discarded and treated as a FAIL with a stable reason.
- Prompt injection: verification instructions are built only by the contract. Submitted
deliverables, evidence, and web content are interpolated exclusively inside delimited
UNTRUSTED DATA — not instructionsregions, and the prompt explicitly instructs the model to ignore instructions found inside submitted content. Deterministic requirements are fixed by the contract itself, so even a successful injection cannot flip them. - Evidence URLs: validated (http/https only), size-capped, fetched only when supplied, with timeouts; failures are recorded as evidence, never fatal.
- Input validation: request schemas validated, payload sizes capped, control characters stripped, URL formats checked.
- No arbitrary code execution: the app only ever runs the fixed, read-only demo fixture test suite; submitted code is never executed.
- Secrets: private keys are server-side only (
GENLAYER_PRIVATE_KEY), never exposed to the client, never committed (.env/.env.localgit-ignored).
Prerequisites: Node 20+, Python 3.12+.
# 1. Contract tooling (Python venv)
python3.12 -m venv .venv
uv pip install --python .venv/bin/python -r requirements.txt # or: .venv/bin/pip install -r requirements.txt
# 2. Lint + direct-mode contract tests (no network needed)
.venv/bin/genvm-lint check contracts/AgentzProofVerifier.py
.venv/bin/python -m pytest tests/direct -v
# 3. Frontend
cd frontend
npm install
cp .env.example .env.local # demo mode works with NO variables set
npm run dev # http://localhost:3000
# 4. Frontend checks
npm run lint && npx tsc --noEmit && npm test && npm run buildOpen http://localhost:3000 → Live Demo → pick a scenario. The demo runs with no wallet, no funds, and no deployed contract (results are honestly labeled DEMO MODE).
npm install -g genlayer # current official CLI (simulator + deploy)
genlayer network # pick studionet / testnetAsimov / testnetBradbury / localnetSet the network account in the GenLayer CLI config (follow genlayer network prompts), or
use GenLayer Studio. For the app's server-side signing, add GENLAYER_PRIVATE_KEY to
frontend/.env.local.
AgentzProofVerifier has already been deployed to GenLayer Bradbury (chain ID 4221):
Network: testnetBradbury
RPC: https://rpc-bradbury.genlayer.com
Contract: 0xbe1de3345603162554fcdff2b75cf4aa96c74329
Deployment transaction: 0x61be412b8b8ab9a85cc8f1571781cb22a41326695f6f4ae147f02363db05c57c
Do not redeploy this contract for normal frontend use. The frontend submits verification transactions to this existing address.
AgentzProofVerifier is also deployed to GenLayer Studio Devnet (Studio Next,
61997 / 0xf22d, RPC https://studio-dev.genlayer.com/api) — the Consensus
v0.6 RC stack (genlayer-js 2.0.0-rc.1, genlayer-py 0.19.0rc2, genvm-universal
v0.6.0-rc6, contract pin py-genlayer:5jycge4q8k…), deployed via the isolated
browser-wallet flow in deploy/studionext/. Every value below is
chain-returned and was independently re-verified against the canonical RPC.
| Artifact | Tx hash | Outcome |
|---|---|---|
| Contract deployment (Sep 21) | 0xc4a42255f728b71a881d9e20ed5c0d3f85e195cc938f95b7307f1c9674332076 |
FINALIZED · FINISHED_WITH_RETURN → contract 0xEd091f5d891274864eAeE0f1E388dDa14e5ee1cE, RC pin verified in deployed code |
PASS verification (Sep 21) — ID f0f3b22d-3879-4236-a327-9db10dcdfc6e, deterministic checks, submitted through the app flow |
0xdeaf14db37230f98a4de3b975c3f8d0f170bcc04096518bd07222e2433e1962a |
FINALIZED · MAJORITY_AGREE · contract stores PASS 3/3, score 1.0 |
| LLM divergence run (Sep 21) — subjective requirement adjudicated by leader/validators | 0x338cb850d8ebcedf10558e415021b5d164b114d1fd572a49f77ee1746975805d |
FINALIZED · MAJORITY_DISAGREE — nothing stored by design (genuine network adjudication) |
Divergence panel live test (Sep 22) — ID 39f815fb-adb4-4315-a804-2ece4a12eaaf, deterministic REQ-1 PASS + subjective REQ-2 |
0x1cd16f74930642362e3970a8d29e8a0124cfbbd93c8755a8fe2c6cef02042a26 |
FINALIZED · MAJORITY_DISAGREE — app renders the terminal DIVERGED proof panel |
The two divergence runs are a feature, not a failure: they demonstrate the
validators independently judging subjective requirements instead of
rubber-stamping. The Bradbury 4221 path remains the published release; the
Studio Next app wiring (frontend/lib/genlayer/studionext.ts, browser-wallet
signing, keyless finalization) is isolated from it. Studio-dev is a temporary
preview network — expect resets; see
deploy/studionext/REDEPLOY-RUNBOOK.md for the restoration procedure.
cd frontend
cp .env.example .env.local
# set:
# GENLAYER_CONTRACT_ADDRESS=0xbe1de3345603162554fcdff2b75cf4aa96c74329
# GENLAYER_NETWORK=testnetBradbury
# GENLAYER_RPC_URL=https://rpc-bradbury.genlayer.com
# GENLAYER_PRIVATE_KEY=<server-side key, configured only in a secret store>
npm run devGENLAYER_PRIVATE_KEY is required for the server-side API to submit live verification
transactions. Store it only in a protected server/Vercel environment variable; never put
it in source, .env.example, client code, or any NEXT_PUBLIC_* variable.
gltest tests/integration/ -v -scd frontend && npm run build && npm startThree built-in scenarios — one click, no configuration:
| Scenario | Expected | Why |
|---|---|---|
| Password Reset Implementation | FAIL | The submitted implementation accepts expired reset tokens. The deterministic reported check (the fixture test suite exits non-zero on the expired-token test) fails REQ-6 → 5/6 → FAIL. |
| Password Reset Implementation — Correct | PASS | Expired tokens are rejected; the test suite is green → 6/6 → PASS. |
| Research Deliverable | PASS | Subjective requirements (adoption, pricing, verification layer) judged from evidence → PASS. |
The judge flow: open the app → Try Live Demo → pick a scenario → watch the agent simulator submit → VERIFY → watch the 7-stage sequence (deterministic checks → GenLayer adjudication → consensus) → inspect per-requirement results, reasons, and evidence used. ~2 minutes, no wallet needed.
contracts/AgentzProofVerifier.py # the Intelligent Contract (core feature)
deploy/deployScript.ts # genlayer deploy script
fixtures/ # demo repos (buggy + correct password reset, research)
tests/direct/ # 25 in-memory contract tests (pass, fail, injection red-team, …)
tests/integration/ # gltest end-to-end tests
frontend/ # Next.js 16 + TypeScript + Tailwind 4 app
app/ # pages + API routes
lib/verifier/ # deterministic checks, judge, engine, schema
lib/genlayer/ # live on-chain client
lib/demo/ # demo scenarios + fixture runner
tests/ # 34 vitest unit/integration tests (scenarios, engine, schema, checks)
MIT (see repository).
{ "requirements": [ { "id": "REQ-6", "text": "Invalid or expired tokens are rejected.", "check": { "type": "reported", "passed": false, "evidence": "fixture test suite" } // check types: string_present | regex | function_exists | file_exists | // reported | http_status (absent check ⇒ LLM adjudicates) } ], "deliverable": { "summary": "...", "code": "...", "files": { "path": "content" } }, "evidence": [ { "source": "...", "claim": "...", "content": "..." } ], "evidence_urls": ["https://…"] }