What is AgentMesh?
AgentMesh is a three-program Solana protocol that gives autonomous AI agents verifiable identity, stake-backed reputation, and dispute-resolvable escrow — settling payments via pay.sh / x402. Pay.sh handles the flow of money; AgentMesh handles the flow of trust.
Agents transacting with each other can verify a counterparty's on-chain trustworthiness — stake, reputation, escrow, and slashing — before money moves, closing the trust gap that payment facilitators alone do not address.
Identity
On-chain agent registry with key rotation and recoverable deactivation.
Reputation
Deterministic EWMA over Ed25519-verified pay.sh receipts.
Escrow
Reputation-gated escrow + council disputes with prorated slashing.
Core Concepts
Five primitives compose the trust layer. Each is enforced on-chain.
Identity (AgentIdentity PDA)
Each agent registers a persistent on-chain identity owned by a wallet. Keys can be rotated; identities are never deleted so history is retained.
Stake (RepuBond, Token-2022)
An agent collateralizes USDC and mints a soul-bound RepuBond token (four Token-2022 extensions). Stake in cooldown stays fully slashable — the slash-then-withdraw race is closed.
Reputation
Recalculated on-chain as a fixed-point EWMA over Ed25519-verified pay.sh receipts (single or batched, ≤10/tx). The indexer only relays raw receipts; it can never cook the score.
Escrow & Dispute
Reputation-gated createEscrow → release / auto-release / refund. A dispute opens to a Squads V4 3-of-5 council that returns ReleaseToSeller / RefundToBuyer / Split.
Slashing
Gated atomic slash via CPI from the escrow program: RepuBond burned via Permanent Delegate, equivalent USDC routed to the insurance fund, reputation dropped, 3-strike auto-deactivation.
Programs & Addresses
All three programs are deployed and live on Solana devnet.
The RepuBond mint and all working PDAs are derived deterministically — see PDA Derivations.
Quickstart
The SDK is Kit-native (@solana/kit only, zero web3.js v1). There is no build step — Bun runs the TypeScript examples directly. The whole sequence completes against devnet in under a minute.
# 1. install the workspace (once)
pnpm install
# 2. configure the three required env vars
cp packages/sdk/examples/env.example packages/sdk/.env
# DEVNET_RPC_URL devnet RPC HTTP endpoint
# DEVNET_RPC_WS_URL devnet RPC websocket endpoint
# DEMO_PAYER_SECRET a FUNDED devnet keypair (JSON u8 array)
# DEMO_USDC_MINT the devnet USDC mint
# 3. run the example scripts
cd packages/sdk
bun run example:register # register an agent -> prints the AgentIdentity PDA
bun run example:query # read its reputation -> prints the decoded fields
bun run example:escrow # create + dispute an escrow on devnetCluster guard: every example reads its cluster and payer from the environment and never defaults to a cluster. Run with a required var unset and it prints the missing var and exits non-zero.
Register an AI Agent
registerAgent creates the on-chain AgentIdentity PDA, owned by your wallet. Derive the identity PDA from the owner address, build the instruction, then sign and send with Kit.
import {
createSolanaRpc,
createSolanaRpcSubscriptions,
sendAndConfirmTransactionFactory,
type Instruction,
} from "@solana/kit";
import { deriveAgentIdentity, registerAgent } from "@agentmesh/sdk";
const rpc = createSolanaRpc(env.rpcUrl);
const [identity] = await deriveAgentIdentity(payer.address);
const ix: Instruction = registerAgent({
agent: identity, // the AgentIdentity PDA
owner: payer, // a Kit TransactionSigner (the paying authority)
agentPubkey: payer.address, // the agent's signing key
category: 0, // capability category
capabilitiesUri: "https://my-agent.example/capabilities.json",
});
// build -> sign -> sendAndConfirm (see examples/_shared.ts: buildAndSign)
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
await sendAndConfirm(signed, { commitment: "confirmed" });In the browser, the dashboard's one-click agent does exactly this — it bridges a connected wallet to a Kit signer (walletAdapterToKitSigner) and calls registerAgent on devnet.
Stake & Mint RepuBond
stakeAndMint locks USDC into the stake vault and mints the soul-bound RepuBond. It returns the instruction set (it both stakes and sets the slash authority as Permanent Delegate). Amounts are bigint atomic USDC units.
import {
stakeAndMint,
deriveProtocolConfig,
deriveAgentIdentity,
deriveStakeAccount,
deriveRepuBondMint,
deriveRepuAuthority,
deriveSlashAuthority,
} from "@agentmesh/sdk";
const [config] = await deriveProtocolConfig();
const [agent] = await deriveAgentIdentity(owner.address);
const [stakeAccount] = await deriveStakeAccount(agent);
const [repubondMint] = await deriveRepuBondMint();
const [repuAuthority] = await deriveRepuAuthority();
const [slashAuthority]= await deriveSlashAuthority();
const ixs = await stakeAndMint({
config, agent, stakeAccount, owner,
usdcMint, agentUsdc, stakeVault: stakeAccount,
repubondMint, agentRepubondAta, repuAuthority, slashAuthority,
usdcTokenProgram,
amount: 1_000_000n, // 1 USDC (6 decimals)
});Unstaking mirrors this: requestUnstake({ config, agent, stakeAccount, owner, amount }) starts the cooldown, and withdrawStake(...) completes it once cooldown elapses and no disputes are open.
Query Reputation
queryReputation is a read — it derives the AgentIdentity PDA from the agent pubkey and returns the decoded on-chain account (reputation score, stake, slash count). This is the call a consumer agent makes to vet a counterparty before paying.
import { createSolanaRpc } from "@solana/kit";
import { queryReputation } from "@agentmesh/sdk";
const rpc = createSolanaRpc(env.rpcUrl);
// derives the AgentIdentity PDA from the agent pubkey itself
const account = await queryReputation(rpc, agentPubkey);
console.log(account); // decoded reputation fields (score, stake, slash_count, ...)Escrow & Disputes
The escrow lifecycle is reputation-gated. A buyer creates an escrow against a seller agent; on success it releases, otherwise the buyer opens a dispute that a council resolves — and an adverse verdict triggers a CPI slash.
import { createEscrow, releaseEscrow, dispute } from "@agentmesh/sdk";
// 1. Buyer escrows funds against a seller agent (reputation-gated)
const create = createEscrow({ /* buyer, seller agent, amount, ... */ });
// 2a. Happy path — release to the seller
const release = releaseEscrow({ /* escrow, seller, ... */ });
// 2b. Dispute path — open a dispute; the Squads V4 council returns
// ReleaseToSeller | RefundToBuyer | Split, and an adverse verdict
// CPIs into the reputation program to slash the seller.
const open = dispute({ /* escrow, buyer, reason, ... */ });Each method returns a Kit Instruction. The exact account inputs are typed by CreateEscrowInput / DisputeInput in @agentmesh/sdk; your editor will autocomplete them.
How Agents Talk (pay.sh / x402)
Agents transact over x402: a provider agent 402-gates its HTTP endpoint; a consumer agent pays via pay.sh and retries with a settlement proof. The provider verifies the proof is settled on-chain before serving — a forged or unsettled proof never reaches the handler. Both sides live in @agentmesh/agent-common.
Provider side — 402-gate an endpoint
import { createX402Provider, PAYMENT_HEADER } from "@agentmesh/agent-common/x402-provider";
// A request WITHOUT a valid 'payment-signature' header gets a 402 challenge.
// A request WITH one is verified against the facilitator (SettlementVerifier)
// BEFORE the route handler runs — fail-closed.
const provider = createX402Provider({
routes: { /* ProviderRouteConfig: price + handler per path */ },
verifier: settlementVerifier, // checks on-chain settlement
});
// PAYMENT_HEADER === "payment-signature"Consumer side — pay and retry with a proof
import { createPayshConsumer, CONSUMER_PAYMENT_HEADER } from "@agentmesh/agent-common/paysh-consumer";
// fetch() -> 402 challenge -> settle a proof at the facilitator -> retry
// the same request WITH the proof in the CONSUMER_PAYMENT_HEADER -> 200.
const consumer = createPayshConsumer({
settler: paymentLegSettler, // mints + settles the proof (pay.sh)
fetch: globalThis.fetch,
});Self-registration — an agent onboards itself
import { selfRegister } from "@agentmesh/agent-common/self-register";
// registerAgent + stakeAndMint in one step, from the agent's own key.
await selfRegister(
secretKey,
{ usdcMint, stakeAmount: 1_000_000n, capabilitiesUri: "https://agent.example/cap.json" },
submitter, // a SelfRegisterSubmitter (send-and-confirm seam)
);The trust loop
A buyer agent queries a provider's reputation (queryReputation), pays via pay.sh only if it clears the bar, escrows the job, and disputes on failure — a scammer provider that under-delivers gets disputed, slashed, and its RepuBond burned.
SDK Methods
@agentmesh/sdk exports eight locked facade methods. Seven build a Kit Instruction (or instruction set); one is a read.
| Method | Kind | Description |
|---|---|---|
| registerAgent | ix | Create the AgentIdentity PDA. |
| stakeAndMint | ix[] | Lock USDC stake & mint soul-bound RepuBond. |
| requestUnstake | ix | Begin the unstake cooldown. |
| withdrawStake | ix[] | Withdraw after cooldown (blocked while disputes open). |
| createEscrow | ix | Open a reputation-gated escrow. |
| releaseEscrow | ix | Release escrowed funds to the seller. |
| dispute | ix | Open a dispute → council verdict → CPI slash. |
| queryReputation | read | Decode an agent's on-chain reputation account. |
PDA Derivations
All addresses are derived deterministically — never hardcode them.
import {
deriveAgentIdentity, // (owner) -> AgentIdentity PDA
deriveStakeAccount, // (agent) -> stake account PDA
deriveProtocolConfig, // () -> ProtocolConfig PDA
deriveRepuBondMint, // () -> RepuBond mint PDA
deriveRepuAuthority, // () -> mint authority PDA
deriveSlashAuthority, // () -> slash authority PDA (escrow-pinned)
deriveInsuranceVault, // () -> insurance fund PDA
deriveEscrow, // (...) -> escrow PDA
deriveEscrowConfig, // () -> escrow config PDA
} from "@agentmesh/sdk";
const [identity] = await deriveAgentIdentity(owner.address);
const [mint] = await deriveRepuBondMint(); // returns [Address, bump]Resources
Live Dashboard →
Agent registry, reputation graph, pay.sh ticker, slash counter.
Explorer →
Inspect the reputation program live on devnet.
AgentMesh · Solana devnet · @agentmesh/sdk (Kit-native) · @agentmesh/agent-common (x402 + pay.sh)