Trustless escrow protocol for autonomous agent-to-agent transactions. Agents lock funds in on-chain vaults, define success criteria, and auto-settle based on verifiable outcomes. Works on Solana (SPL tokens) and Base (ERC-20 tokens) with the same API.
bash
# Install escrow skills into your AI agent (Cursor, Claude Code, Codex, Copilot, ...)
npx skills add cruellacodes/escrowagent
# TypeScript SDK (core)
npm install escrowagent-sdk@latest
# Agent tools (LangChain, Vercel AI, MCP adapters)
npm install escrowagent-agent-tools@latest
# Or scaffold everything into the project
npx escrowagent@latest init
# Start MCP server for Claude / Cursor
npx escrowagent@latest mcp
The
class provides a unified API across both chains.
typescript
import { AgentVault, USDC_DEVNET_MINT } from "escrowagent-sdk";
import { Connection, Keypair } from "@solana/web3.js";
const vault = new AgentVault({
chain: "solana",
connection: new Connection("https://api.devnet.solana.com"),
wallet: Keypair.fromSecretKey(Uint8Array.from(JSON.parse(process.env.AGENT_PRIVATE_KEY!))),
programId: "8rXSN62qT7hb3DkcYrMmi6osPxak7nhXi2cBGDNbh7Py",
});
typescript
import { AgentVault, USDC_BASE } from "escrowagent-sdk";
const vault = new AgentVault({
chain: "base",
privateKey: process.env.BASE_PRIVATE_KEY!, // 0x...
contractAddress: "0xddBC03546BcFDf55c550F5982BaAEB37202fEB11",
rpcUrl: "https://mainnet.base.org",
chainId: 8453,
});
typescript
// 1. Client creates escrow
const { escrowAddress } = await vault.createEscrow({
provider: "ProviderAgentAddress",
amount: 50_000_000, // 50 USDC (6 decimals)
tokenMint: USDC_DEVNET_MINT, // or USDC_BASE for Base chain
deadline: Date.now() + 600_000, // 10 minutes
task: {
description: "Swap 10 USDC to SOL on Jupiter at best price",
criteria: [
{ type: "TransactionExecuted", description: "Swap tx confirmed on-chain" },
],
},
verification: "OnChain", // or "MultiSigConfirm", "OracleCallback", "AutoRelease"
arbitrator: "ArbitratorAddress", // optional
});
// 2. Provider accepts the escrow
await vault.acceptEscrow(escrowAddress);
// 3. Provider does the work, then submits proof
await vault.submitProof(escrowAddress, {
type: "TransactionSignature", // or "OracleAttestation", "SignedConfirmation"
data: swapTxSignature,
});
// 4. Client confirms completion -> funds release to provider
await vault.confirmCompletion(escrowAddress);
typescript
// Cancel (only before provider accepts)
await vault.cancelEscrow(escrowAddress);
// Raise a dispute (freezes funds)
await vault.raiseDispute(escrowAddress, { reason: "Work not completed as specified" });
// Resolve a dispute (arbitrator only)
await vault.resolveDispute(escrowAddress, { type: "PayProvider" });
// or: { type: "PayClient" }
// or: { type: "Split", clientBps: 5000, providerBps: 5000 }
// Query
const info = await vault.getEscrow(escrowAddress);
const escrows = await vault.listEscrows({ status: "AwaitingProvider", limit: 10 });
const stats = await vault.getAgentStats("AgentAddress");
Add to Claude Desktop config (
claude_desktop_config.json
):
json
{
"mcpServers": {
"escrowagent": {
"command": "npx",
"args": ["escrowagent@latest", "mcp"],
"env": {
"SOLANA_RPC_URL": "https://api.devnet.solana.com",
"AGENT_PRIVATE_KEY": "[your,keypair,bytes]"
}
}
}
}