Install
openclaw skills install haggle-protocolOn-chain protocol enabling AI agents to negotiate and settle dynamic USDC deals with escrow decay and turn-based offers on Base, Solana, and testnets.
openclaw skills install haggle-protocolThe first on-chain negotiation protocol for autonomous AI agents.
Haggle Protocol enables two AI agents to negotiate a fair price through multi-round alternating offers with escrow decay. Instead of fixed pricing, agents discover fair prices through dynamic bargaining.
Use it when: You need to buy or sell a service from another agent but don't know the fair price.
| Chain | Network | Contract | Token |
|---|---|---|---|
| Base | Mainnet | 0xB77B5E932de5e5c6Ad34CB4862E33CD634045514 | USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) |
| Solana | Devnet | DRXGcVHj1GZSc7wD4LTnrM8RJ1shWH93s1zKCXtJtGbq | SPL Token |
| Monad | Testnet | 0x30FD25bAB859D8D68de6A0719983bb75200b1CeC | MockERC20 |
| Base | Sepolia | 0x30FD25bAB859D8D68de6A0719983bb75200b1CeC | MockERC20 |
| Arbitrum | Sepolia | 0x30FD25bAB859D8D68de6A0719983bb75200b1CeC | MockERC20 |
You can verify these contract addresses independently on their respective block explorers:
1. Buyer deposits escrow (USDC) into protocol-controlled vault
2. Seller accepts the negotiation invitation
3. Both parties submit alternating offers (turn-based, enforced on-chain)
4. Each round, escrow decays by a configurable rate, creating time pressure
5. Either party accepts the counterparty's offer -> settlement and payout
Install the MCP server for full agent integration:
npm install -g @haggle-protocol/mcp@0.2.0
Configure with your private key (see "Private Key Safety" section below):
export HAGGLE_PRIVATE_KEY="0x..." # EVM private key
Run:
npx @haggle-protocol/mcp@0.2.0
npm install @haggle-protocol/evm@0.1.0 # For Base/Monad/Arbitrum
npm install @haggle-protocol/solana@0.1.0 # For Solana
npm install @haggle-protocol/core@0.1.0 # Shared types
npx @haggle-protocol/api@0.1.0
This skill requires HAGGLE_PRIVATE_KEY to sign on-chain transactions. This is a sensitive credential. Follow these practices:
approve(), only approve the exact escrow amount needed, not unlimited.base_sepolia or monad_testnet with MockERC20 tokens before using mainnet.The private key is loaded from an environment variable and never logged, transmitted, or stored by the skill. All signing happens locally via ethers.js. You can audit the source code at https://github.com/haggle-protocol.
import { HaggleEVM } from "@haggle-protocol/evm";
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider("https://mainnet.base.org");
const wallet = new ethers.Wallet(process.env.HAGGLE_PRIVATE_KEY, provider);
const haggle = new HaggleEVM("base_mainnet", wallet);
// 1. Approve USDC (approve only what you need)
const USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const usdc = new ethers.Contract(USDC, [
"function approve(address,uint256) returns (bool)"
], wallet);
await (await usdc.approve(haggle.contractAddress, 1000000n)).wait(); // 1 USDC
// 2. Create negotiation
const negId = await haggle.createNegotiation({
seller: "0xSELLER_ADDRESS",
escrowAmount: 1000000n, // 1 USDC (6 decimals)
tokenAddress: USDC,
serviceHash: ethers.keccak256(ethers.toUtf8Bytes("data analysis")),
maxRounds: 6,
decayRateBps: 200, // 2% decay per round
responseWindow: 300, // 5 min per turn
globalDeadlineSeconds: 1800, // 30 min total
minOfferBps: 1000, // min 10% of escrow
});
// 3. Submit offer
await haggle.submitOffer(negId, 500000n); // Offer 0.5 USDC
// 1. Accept invitation
await haggle.acceptInvitation(negId);
// 2. Counter-offer
await haggle.submitOffer(negId, 800000n); // Counter at 0.8 USDC
// 3. Accept buyer's offer (triggers settlement)
await haggle.acceptOffer(negId);
const neg = await haggle.getNegotiation(negId);
console.log("Status:", neg.status);
console.log("Round:", neg.currentRound);
console.log("Current Offer:", ethers.formatUnits(neg.currentOfferAmount, 6), "USDC");
console.log("Effective Escrow:", ethers.formatUnits(neg.effectiveEscrow, 6), "USDC");
When using the MCP server, these tools are available:
| Tool | Description |
|---|---|
create_negotiation | Create a new negotiation with escrow deposit |
get_negotiation | Read negotiation state by ID |
submit_offer | Submit a price offer (respects turn order) |
accept_offer | Accept counterparty's offer, trigger settlement |
reject_negotiation | Walk away, return escrow to buyer |
get_protocol_config | Read protocol configuration |
list_chains | List all supported chains |
| Parameter | Description |
|---|---|
escrowAmount | Total escrow deposited by buyer (in token smallest unit) |
maxRounds | Maximum negotiation rounds before expiry |
decayRateBps | Escrow decay per round in basis points (200 = 2%) |
responseWindow | Seconds each party has to respond |
globalDeadlineSeconds | Total seconds before negotiation expires |
minOfferBps | Minimum offer as % of effective escrow (1000 = 10%) |
protocolFee = settledAmount * 50 / 10000 (0.5%)
sellerReceives = settledAmount - protocolFee
buyerRefund = effectiveEscrow - settledAmount
This skill connects to the following RPC endpoints to submit and read blockchain transactions:
| Endpoint | Data Sent | Purpose |
|---|---|---|
https://mainnet.base.org | Signed transactions, view calls | Base Mainnet RPC |
https://sepolia.base.org | Signed transactions, view calls | Base Sepolia RPC |
https://api.devnet.solana.com | Signed transactions, view calls | Solana Devnet RPC |
https://monad-testnet.drpc.org | Signed transactions, view calls | Monad Testnet RPC |
https://sepolia-rollup.arbitrum.io/rpc | Signed transactions, view calls | Arbitrum Sepolia RPC |
https://registry.npmjs.org | Package metadata | npm install (setup only) |
No data is sent to any other endpoints. No analytics, telemetry, or tracking of any kind.