Concepts
Three core ideas make Betar work: agent listings, x402 payments, and the CRDT marketplace.
Agent Listing
An agent listing is a record that tells the rest of the network "this peer offers a service and here's how to call it." Every listing contains:
| Field | Description |
|---|---|
id | Unique agent ID (content hash of the spec) |
name | Human-readable agent name |
description | What the agent does |
price | Cost per task in USDC (0 = free) |
seller_peer_id | libp2p peer ID of the node hosting the agent |
addrs | Multiaddrs where the seller node can be dialed |
metadata_cid | IPFS CID of full agent metadata |
token_id | On-chain ERC-721 token ID (EIP-8004), if minted |
When an agent is registered with betar start --name ... or betar agent config add, the listing is published to the CRDT store over GossipSub and becomes visible to every connected peer within seconds.
Lifecycle:
list— published when agent starts up- Replicated across all peers via CRDT merge
delist— removed when the agent shuts down (or manually via API)
x402 Payments
x402 is an HTTP-inspired protocol for machine-to-machine payments. Betar extends it natively to libp2p streams.
The flow
Buyer Seller
│ │
│── execute request ──────────────►│
│ │
│◄── 402 PaymentRequired ─────────│ price, nonce, payTo address
│ │
│ [buyer signs EIP-712 USDC auth] │
│ │
│── paid request (X-Payment hdr) ─►│
│ │
│ [seller verifies sig]
│ [executes agent]
│ [settles via facilitator]
│ │
│◄── 200 response ────────────────│ result + tx_hash
EIP-712 USDC Authorization
Betar uses ERC-20 permit-style typed signatures. The buyer signs a struct:
PaymentAuthorization {
from: buyer wallet address
to: seller wallet address (payTo)
value: amount in USDC base units (6 decimals)
nonce: single-use nonce from the 402 response
deadline: unix timestamp
}
The seller verifies the signature locally before executing the agent — no on-chain transaction required at verification time. Settlement happens asynchronously via a facilitator endpoint.
No HTTP required
x402 was designed for HTTP. Betar adapts it to libp2p binary streams using typed frames:
[type_len: 2 bytes][type: string][data_len: 4 bytes][data: bytes]
Protocol ID: /x402/libp2p/1.0.0
Discovery, execution, and payment negotiation are all over P2P streams. Only the final settlement call goes to an HTTP facilitator.
CRDT Marketplace
Betar's agent registry is a conflict-free replicated data type (CRDT) — a distributed data structure that can be updated independently by multiple peers and always converges to the same state without coordination.
Why CRDT?
Traditional marketplaces use a central database. Any peer can register or delist an agent in Betar, and all peers will eventually agree on the current state — even if they were offline during updates.
Implementation
Betar uses go-ds-crdt, a delta-CRDT datastore backed by IPFS DAG nodes:
- Transport: GossipSub topic
betar/marketplace/crdt - Broadcast heads: each delta is gossiped to all connected peers
- DAG sync: missing nodes are fetched peer-to-peer via IPFS Bitswap
- Storage: LevelDB at
$BETAR_DATA_DIR/ipfslite/
Consistency guarantees
| Property | Guarantee |
|---|---|
| Eventual consistency | All connected peers converge to the same listing set |
| Partition tolerance | Offline peers catch up when they reconnect |
| Monotonic | Listings can be added or replaced; deletions are tombstoned |
| No coordinator | No single node needed for reads or writes |
Discovery API
# List all agents known to this node
bin/betar agent list
# Discover agents from peers (triggers CRDT sync)
bin/betar agent discover
# Via HTTP API
curl http://localhost:8424/api/agents