# How to prove an AI agent output existed — x402 + NEAR anchoring in practice

> Source: <https://dev.to/gitsergecrypto/how-to-prove-an-ai-agent-output-existed-x402-near-anchoring-in-practice-2ede>
> Published: 2026-06-27 20:35:22+00:00

You deployed an AI agent. It generated a financial report, a code review, a medical summary. A week later, someone questions the output. Did the agent actually produce this? When? Was it modified after the fact?

**Logs are mutable. Timestamps lie. Git history can be rewritten.**

What you need is a cryptographic proof — signed by an independent notary — that binds a specific artifact hash to a specific point in time. And it should cost less than a cent.

This article walks through a real, working system: **AOTrust**, a notarization service that issues PDRs (Provenance Data Records) for $0.01 USDC via x402 on Base L2, with Merkle anchoring on NEAR.

`curl`

and `python3`

(for hashing)The x402 protocol handles payment inline — the API returns HTTP 402, you pay, you retry with the payment header. No billing portal, no subscription, no prepaid credits.

``` python
import hashlib

# Your agent produced this report
report = b"The Q3 revenue projection based on agent analysis is $2.4M..."

work_hash = hashlib.sha256(report).hexdigest()
print(work_hash)
# → e.g. "a1b2c3d4e5f6...64 hex chars..."
```

The hash is what gets notarized. You keep the actual artifact — the notary never sees it. This is a **blind notarization**: the PDR proves the hash existed at a point in time, without revealing the content.

```
curl -s https://api.aotrust.link/v1/notarize/quote \
  -H "Content-Type: application/json" \
  -d '{"work_hash":"a1b2c3d4e5f6...your_sha256_hash..."}'
```

The API responds with HTTP 402 — Payment Required — in x402 format:

```
{
  "x402Version": 1,
  "accepts": [{
    "scheme": "exact",
    "network": "base",
    "maxAmountRequired": "10000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA5fE48",
    "resource": "https://api.aotrust.link/v1/notarize"
  }]
}
```

That `maxAmountRequired: 10000`

is 10,000 micro-USDC = **$0.01**. The asset address is USDC on Base. No negotiation, no tiers — flat fee.

Sign an EIP-3009 `transferWithAuthorization`

message with your Base wallet (any wallet that supports EIP-3009 — most do). Then send the notarization request with the payment attached:

```
curl -s https://api.aotrust.link/v1/notarize \
  -H "Content-Type: application/json" \
  -H "X-Payment: <base64-encoded EIP-3009 payload>" \
  -d '{
    "work_hash": "a1b2c3d4e5f6...your_sha256_hash...",
    "agent_account": "your-agent.near",
    "tx_hash": "0x1234...evm_tx_hash_of_usdc_transfer..."
  }'
```

**What happens inside the notary:**

Response (HTTP 200):

```
{
  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "notarized",
  "network": "base",
  "pdr_b64": "AwFCAUJ...base64-encoded 239-byte PDR..."
}
```

The entire flow takes 2–5 seconds. No polling, no webhooks.

The PDR is a 239-byte binary record. The Ed25519 signature is self-contained — you can verify it without calling any API.

```
curl -s "https://api.aotrust.link/v1/pdr/verify/AwFCAUJ...your_pdr_b64..."
{
  "valid": true,
  "version": 3,
  "sig_scheme": 1,
  "payment_anchor_type": 5,
  "timestamp_utc": 1718900000,
  "issuer_id": "notary-node.near",
  "subject_hash": "a1b2...",
  "payload_hash": "b3c4...",
  "merkle_root": "d5e6...",
  "payment_hash": "f7a8...",
  "notary_pubkey": "490f51f23b993eacaff54fc977d9a7689ab7d4ae91504dc6cbdeadb2dbf1f462",
  "anchor": {
    "near_tx": "H4MaR5...",
    "confirmed": true
  }
}
```

The PDR binary format is an open standard. The parser is a single Python file with zero dependencies:

```
# Install the parser
curl -sO https://raw.githubusercontent.com/GitSerge-crypto/aotrust-skills/main/pdr_parser.py

# Verify any PDR offline
python3 pdr_parser.py --pdr "AwFCAUJ...your_pdr_b64..." \
  --pubkey "490f51f23b993eacaff54fc977d9a7689ab7d4ae91504dc6cbdeadb2dbf1f462"
```

Output:

```
PDR v2.3 — Valid ✓
  version:           3
  sig_scheme:        Ed25519
  payment_anchor:    X402_BASE (0x05)
  timestamp:         2026-06-20 14:32:11 UTC
  issuer:            notary-node.near
  subject_hash:      a1b2c3d4...
  payload_hash:      b3c4d5e6...
  merkle_root:       d5e6f7a8...
  payment_hash:      f7a8b9c0...
  signature:         VALID (Ed25519/NEP-413)
```

No network calls. No API keys. No trust in any server. The signature is math.

The notary batches PDRs into Merkle trees every ~16 minutes and anchors the root on NEAR:

```
PDR₁ ─┐
PDR₂ ─┤── Merkle Tree ── Root ── NEAR tx (merkle_anchor contract)
PDR₃ ─┤
PDR₄ ─┘
```

This means:

`merkle_root`

field matches a NEAR transactionYou don't need to wait for anchoring to trust the PDR — the Ed25519 signature is immediate. The anchor adds a **second layer**: independent on-chain timestamp via NEAR consensus.

239 bytes, 10 fields, fully specified:

| Offset | Field | Size | Content |
|---|---|---|---|
| 0 | version | 1 | 0x03 |
| 1 | sig_scheme | 1 | 0x01 (Ed25519) |
| 2 | payment_anchor_type | 1 | 0x05 (X402_BASE) |
| 3 | timestamp_utc | 8 | Unix seconds |
| 11 | issuer_id | 36 | notary-node.near (NUL-padded) |
| 47 | subject_hash | 32 | SHA-256 of agent account |
| 79 | payload_hash | 32 | SHA-256 of work artifact |
| 111 | merkle_root | 32 | Merkle batch anchor |
| 143 | payment_hash | 32 | EVM tx hash (Base) |
| 175 | signature | 64 | Ed25519 (NEP-413) |

The `payment_anchor_type`

is inside the signed payload. This means the PDR self-proves how it was paid for — no external metadata needed. A PDR with `0x05`

cryptographically guarantees it was an x402 Base USDC payment.

**Spec:** [pdr-spec.md](https://github.com/GitSerge-crypto/aotrust-skills/blob/main/pdr-spec.md)

**Parser:** [pdr_parser.py](https://github.com/GitSerge-crypto/aotrust-skills/blob/main/pdr_parser.py) (standalone, MIT)

This is not a demo. 9 PDRs have been issued on Base Mainnet, all anchored to NEAR:

`490f51f23b993eacaff54fc977d9a7689ab7d4ae91504dc6cbdeadb2dbf1f462`

| Scenario | Why PDR helps |
|---|---|
| AI agent produces a financial report | Prove the report existed at time T, unmodified |
| Code review by autonomous agent | Cryptographic receipt of review output |
| Agent-generated medical summary | Timestamp + integrity proof for audit trail |
| Multi-agent pipeline (A→B→C) | Each stage notarized → full chain of custody |
| Agent dispute resolution | "Did the agent say X at time T?" → PDR answers |
| Compliance / regulatory | Signed timestamp from independent notary |

If your agent speaks MCP (Model Context Protocol), AOTrust exposes 4 tools:

```
{
  "tools": [
    {"name": "notary_quote", "description": "Get quote — amount, payment details"},
    {"name": "notary_notarize_paid", "description": "Notarize with x402 payment on Base"},
    {"name": "notary_verify", "description": "Verify any PDR — signature + on-chain anchor"},
    {"name": "notary_notarize", "description": "Notarize without payment (testnet only)"}
  ]
}
```

MCP endpoint: `https://api.aotrust.link/mcp`

(Streamable HTTP, OAuth 2.1)

Agent flow:

`notary_quote`

→ gets amount ($0.01) and payment details`notary_notarize_paid`

with payment + work_hash`notary_verify`

to confirm| Approach | Cost | Self-verifying | On-chain anchor | Setup |
|---|---|---|---|---|
| Chainlink oracle | $0.25–$1.00+ | No | Yes | Smart contract |
| Manual timestamp tx | gas cost | No | Yes | Manual |
| IPFS pin | free | No | No | IPFS node |
| Git commit | free | No | No | Git repo |
| AOTrust PDR | $0.01 |
Yes (Ed25519) |
Yes (NEAR) |
curl |

```
# Health check (no auth)
curl -s https://api.aotrust.link/health

# Get a quote (no auth, no signup)
curl -s https://api.aotrust.link/v1/notarize/quote \
  -H "Content-Type: application/json" \
  -d '{"work_hash":"0000000000000000000000000000000000000000000000000000000000000000"}'

# MCP discovery
curl -s https://api.aotrust.link/.well-known/mcp.json

# x402 discovery
curl -s https://api.aotrust.link/.well-known/x402
```

*The service is live on mainnet. 9 PDRs issued, all anchored on NEAR. If you are building autonomous agents and need cryptographic proof of output integrity — try it, break it, tell me what's missing.*
