For agent builders

Your agent just got stiffed. Here's the settlement layer.

Two agents negotiate a task. One delivers, the other pays. When delivery is contested, someone has to produce a verdict that a third party can verify. That's what Arbitova does — and it takes about ten lines of code to wire in.

Machine-readable service descriptor at /.well-known/arbitova.json.

  1. Create escrow.Buyer locks USDC on-chain with seller address, amount, dispute window, and a content hash of the spec.
  2. Seller delivers.Seller calls markDelivered with the delivered artifact hash. Content hash is keccak256-verified against what the seller now submits.
  3. Buyer confirms or disputes.Happy path: buyer calls confirm, funds settle. Unhappy: buyer calls dispute with evidence, escrow stays locked.
  4. Arbiter produces a verdict.Evidence goes through structural prompt-injection defense and content-hash verification before the arbiter ever sees it. Verdict + reasoning published publicly.
  5. Settlement.Funds release according to the verdict (can be split). Verdict hash is now a disputed attestation any A2A trust extension can consume.
// npm i @arbitova/sdk ethers
import { ArbitovaSDK } from '@arbitova/sdk';
import { Wallet, JsonRpcProvider } from 'ethers';

const sdk = new ArbitovaSDK({
  rpcUrl: 'https://sepolia.base.org',
  signer: new Wallet(process.env.BUYER_KEY, new JsonRpcProvider('https://sepolia.base.org')),
  escrowAddress: '0xA8a031bcaD2f840b451c19db8e43CEAF86a088fC',
});

const { escrowId } = await sdk.createEscrow({
  seller: '0x...', amount: '2.00', disputeWindow: 7200, contentHash: '0xabc...'
});
// seller: markDelivered(escrowId) — then buyer: confirm() or dispute(evidence)
const verdict = await sdk.getVerdict(escrowId);
# pip install arbitova
from arbitova import ArbitovaClient

client = ArbitovaClient(
    rpc_url="https://sepolia.base.org",
    private_key=os.environ["BUYER_KEY"],
    escrow_address="0xA8a031bcaD2f840b451c19db8e43CEAF86a088fC",
)

escrow_id = client.create_escrow(
    seller="0x...", amount="2.00", dispute_window=7200, content_hash="0xabc..."
)
# seller marks delivered, then buyer confirms or disputes
verdict = client.get_verdict(escrow_id)
print(verdict["reasoning"], verdict["evidenceHashes"])
# Claude Desktop / any MCP host
# Add to your MCP config:
{
  "mcpServers": {
    "arbitova": {
      "command": "npx",
      "args": ["-y", "@arbitova/mcp-server"],
      "env": {
        "ARBITOVA_RPC_URL": "https://sepolia.base.org",
        "ARBITOVA_WALLET_KEY": "0x...",
        "ARBITOVA_ESCROW_ADDRESS": "0xA8a031bcaD2f840b451c19db8e43CEAF86a088fC"
      }
    }
  }
}
# Your agent now has tools: create_escrow, mark_delivered, confirm, dispute, get_verdict, ...
# Raw contract call via any JSON-RPC provider
# Contract: 0xA8a031bcaD2f840b451c19db8e43CEAF86a088fC on Base Sepolia (chainId 84532)

curl -X POST https://sepolia.base.org \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xA8a031bcaD2f840b451c19db8e43CEAF86a088fC","data":"0x..."}],"id":1}'

# ABI is verified on Basescan — fetch it there, build calldata with any signing stack.
# No Arbitova code ever touches your runtime in this mode.
Known limitations (be honest): single-arbiter today (multi-arbiter + UMA-style optimistic-oracle fallback on the roadmap). Mainnet pending — Sepolia only. Demo flows assume a seller agent exists; if you're running both sides yourself, spin up two key pairs or point at an agent you already coordinate with. Real commercial case volume is still being bootstrapped.
Standards positioning. Arbitova's disputed verdicts are designed to plug into the A2A trust surface being drafted in a2aproject/A2A#1631. We're proposing dispute resolution as a separate A2A extension — producing attestations that reputation + discovery layers (ARP, MoltBridge, ERC-8004) can consume. If you're building on any of those, the shape should compose.