DEV Community

Nikhil Ranka
Nikhil Ranka

Posted on

The Complete Guide to Agent-to-Agent Marketplaces in 2026

The Complete Guide to Agent‑to‑Agent Marketplaces in 2026

For developers building autonomous AI agents.


1. Introduction

Agent‑to‑agent (A2A) marketplaces enable independent software agents to discover, purchase, and invoke services offered by other agents. Unlike traditional API marketplaces that rely on human developers to negotiate contracts, A2A platforms automate negotiation, payment, and execution through on‑chain or off‑chain protocols.

In 2026 the most common pattern combines three layers:

  1. Discovery registry – a mutable list of agent capabilities, often backed by a decentralized identifier (DID) document or a lightweight IPFS‑based manifest.
  2. Payment settlement – a micro‑payment channel or escrow contract that settles in a stablecoin (USDC on Base, USDT on Polygon, etc.) with sub‑cent granularity.
  3. Trust & reputation – a lightweight scoring system that records successful invocations, dispute outcomes, and uptime.

The goal of this guide is to walk through the technical choices you’ll face when building or integrating with an A2A marketplace, provide concrete code snippets, and highlight the trade‑offs that remain unresolved today.


2. Core Components

2.1 Agent Manifest

Each agent publishes a JSON‑LD manifest that describes:

  • id – a DID (did:key:... or did:ethr:0x…).
  • endpoint – HTTPS URL where the agent receives JSON‑RPC‑style requests.
  • methods – array of RPC methods, each with input/output JSON Schema.
  • price – micro‑price per call, expressed in the smallest unit of the settlement token (e.g., wei for USDC on Base).
  • metadata – optional tags for discovery (e.g., ["vision","ocr"]).
{
  "@context": "https://schema.org",
  "id": "did:key:z6Mkk...",
  "endpoint": "https://agent.example.com/rpc",
  "methods": [
    {
      "name": "extractText",
      "inputSchema": {"type":"object","properties":{"imageUrl":{"type":"string"}},"required":["imageUrl"]},
      "outputSchema": {"type":"object","properties":{"text":{"type":"string"}},"required":["text"]},
      "price": 500000   // 0.0005 USDC (5 × 10⁻⁴) in wei-equivalent
    }
  ],
  "metadata": ["vision","ocr"]
}
Enter fullscreen mode Exit fullscreen mode

2.2 Discovery Registry

A minimal registry can be a smart contract that stores a mapping bytes32 agentId => ManifestURI. Agents register by calling register(string calldata manifestURI) and pay a small fee to prevent spam. Queries are performed via a view function getManifest(bytes32 agentId).

If you prefer off‑chain latency, you can mirror the same data to IPFS and pin the CID in the contract; the contract then only stores the CID, keeping gas costs low.

2.3 Payment & Settlement

Two dominant patterns in 2026:

Pattern How it works Pros Cons
Escrow smart contract Agent locks funds in a contract; consumer calls payAndInvoke(agentId, method, args); contract forwards call to agent’s endpoint after verifying payment. Atomicity, no need for off‑chain channels. Higher gas cost per call; latency added by contract execution.
Payment channel (e.g., Connext, Lightning‑like) Consumer opens a bidirectional channel with the marketplace, funds it once, then signs off‑chain messages for each call; settlement occurs periodically or on dispute. Near‑zero per‑call cost, sub‑second latency. Requires liquidity management, more complex client SDK, and watchtower reliance for security.

For most developer‑focused use‑cases where call volume is modest (<10⁴ calls/day) and latency tolerance is ~200 ms, the escrow pattern is simpler to audit and debug.

2.4 Reputation System

A reputation score can be kept as an integer in the registry contract, incremented on successful completion (fulfill) and decremented on a verified dispute (challenge). To avoid Sybil attacks, tie score changes to a bonded stake: agents must lock a minimum amount of USDC to be eligible for score updates.


3. Building Blocks for Developers

3.1 Agent SDK (Python example)

Below is a minimal SDK that:

  • Reads the agent’s manifest from env.
  • Signs a payment‑authorization message using an EIP‑712 typed struct (compatible with Base’s USDC contract).
  • Sends a JSON‑RPC request to the target agent, attaching the signature in the x-payment header.
# agent_sdk.py
import os, json, requests, time
from eth_account import Account
from eth_account.messages import encode_typed_data

AGENT_DID = os.getenv("AGENT_DID")          # e.g., did:key:z6Mkk...
AGENT_KEY = os.getenv("AGENT_PRIVATE_KEY")  # 0x-prefixed hex
BASE_USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"  # USDC on Base (mainnet)

def _build_eip712(agent_id, method, price, nonce):
    return {
        "types": {
            "EIP712Domain": [
                {"name":"name","type":"string"},
                {"name":"version","type":"string"},
                {"name":"chainId","type":"uint256"},
                {"name":"verifyingContract","type":"string"}
            ],
            "PaymentAuth":[
                {"name":"agentId","type":"string"},
                {"name":"method","type":"string"},
                {"name":"price","type":"uint256"},
                {"name":"nonce","type":"uint256"}
            ]
        },
        "primaryType":"PaymentAuth",
        "domain":{
            "name":"AgentPay",
            "version":"1",
            "chainId":8453,          # Base
            "verifyingContract":BASE_USDC
        },
        "message":{
            "agentId":agent_id,
            "method":method,
            "price":price,
            "nonce":nonce
        }
    }

def call_agent(target_did: str, method: str, args: dict):
    # 1. fetch manifest (simplified: assume you already know endpoint & price)
    manifest_url = f"https://registry.example.com/manifest/{target_did}"
    manifest = requests.get(manifest_url).json()
    endpoint = manifest["endpoint"]
    price = next(m["price"] for m in manifest["methods"] if m["name"] == method)

    # 2. build payment auth
    nonce = int(time.time())
    eip712 = _build_eip712(target_did, method, price, nonce)
    signed = Account.sign_typed_data(
        Account.from_key(AGENT_KEY).key,
        eip712
    )
    signature = signed.signature.hex()

    # 3. invoke
    payload = {
        "jsonrpc":"2.0",
        "method":method,
        "params":args,
        "id":1
    }
    headers = {
        "Content-Type":"application/json",
        "x-agent-did":AGENT_DID,
        "x-payment":f"{signature},{nonce}"
    }
    resp = requests.post(endpoint, json=payload, headers=headers, timeout=10)
    resp.raise_for_status()
    return resp.json()["result"]

# Example usage
if __name__ == "__main__":
    text = call_agent(
        target_did="did:key:z6Lkk...",
        method="extractText",
        args={"imageUrl":"https://example.com/img.png"}
    )
    print(text)
Enter fullscreen mode Exit fullscreen mode

What the SDK does:

  • Generates an EIP‑712 PaymentAuth that the target agent can verify against the USDC contract (the contract checks that the signer allowed the transfer of price tokens).
  • Sends the signature and a nonce in a custom header; the agent verifies the signature, increments a nonce map to prevent replay, then escrows the funds via a call to the USDC contract (transferFrom).

3.2 Agent Service (Node.js/Express example)

The service validates the payment header, executes the business logic, and returns a result.


javascript
// agent.js
const express = require('express');
const { ethers } = require('ethers');
const app = express();
app.use(express.json());

const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const USDC_ABI = [
  "function approve(address spender, uint256 amount) external returns (bool)",
  "function transferFrom(address sender, address recipient, uint256 amount) external returns (bool)"
];
const provider = new ethers.JsonRpcProvider("https://base.mainnet.rpc.cloud");
const usdc = new ethers.Contract(USDC_ADDRESS, USDC_ABI, provider);

// Wallet that holds the agent's USDC (funded via a faucet or bridge)
const
Enter fullscreen mode Exit fullscreen mode

Top comments (0)