Agent Budget Vault

Agent Budget Vault

Give AI agents a capped USDC budget — no private keys, no wallet access

The Agent Budget Vault is an HTLC-style on-chain spending vault deployed on SKALE Base Sepolia. An owner deposits USDC and commits a batch of hashlocks (one per spending unit). Each hashlock locks a fixed USDC amount. The agent is given the corresponding secrets — when it needs to pay for an API call, it reveals a secret to the RelAI facilitator, which calls vault.redeem(secret, payee) on-chain.

The agent never holds a private key. If compromised, an attacker can only spend the pre-committed budget — not drain the owner's wallet.

No Keys
Keyless Agent
Agent only knows secrets — no private key, no wallet. Funds are pre-committed on-chain.
Capped
Bounded Exposure
Each secret = fixed amount. Agent can never spend more than the sum of committed secrets.
Reversible
Owner Can Cancel
Owner calls cancelBatch() to reclaim unspent USDC at any time before redemption.

How It Works

Agent Budget flow
1. Owner calls POST /facilitator/agent-budget/prepare
↓ server generates N (secret, hashlock) pairs client-side
↓ returns secrets (owner keeps) + hashlocks (for vault deposit)
2. Owner approves USDC + calls vault.deposit(usdc, items[]) via MetaMask
↓ each item = { hashlock, amount, expiry } — USDC locked on SKALE Base Sepolia
3. Owner hands secrets to the AI agent (env var, context window, etc.)
4. Agent reveals a secret to RelAI facilitator when paying for an API
↓ facilitator calls vault.redeem(secret, payeeAddress)
↓ USDC transferred from vault to API provider
5. Owner can call cancelBatch(hashlocks[]) to reclaim unspent budget

Why SKALE Base Sepolia? Near-zero gas costs for the facilitator. Each redeem() call is a on-chain transaction paid by the relayer in CREDIT — not the agent or the owner.

Secrets are generated client-side and never stored on the server. Save them immediately after preparation — if lost, funds remain locked until expiry.

Using the Dashboard UI

The Agent Budget section is available in /dashboard/payment-codes under the Agent Budget tab.

  1. 1Set amount per secret (e.g. 1.00 USDC), number of secrets, and expiry hours.
  2. 2Click "Prepare budget" — secrets are generated and shown. Copy all secrets now.
  3. 3Click "Deposit to vault" — MetaMask will prompt to switch to SKALE Base Sepolia, approve USDC, then deposit.
  4. 4Hand the secrets to your AI agent (env var, system prompt, API call).
  5. 5To reclaim unused funds: click "Withdraw all" (calls cancelBatch in one tx).
  6. 6After expiry: "Reclaim expired" button appears — recovers USDC without needing secrets.
The dashboard persists your current budget session in localStorage — secrets and hashlocks survive page refreshes until you withdraw or reclaim.

API Reference

POST
/facilitator/agent-budget/prepare

Generate N (secret, hashlock) pairs. Returns secrets + deposit calldata. Requires auth.

POST
/facilitator/agent-budget/redeem

Reveal a secret to redeem a commitment to a payee address. Called by the agent.

POST
/facilitator/agent-budget/cancel

Cancel an unused commitment by hashlock (owner only). Returns USDC to owner.

Prepare 5 × 1 USDC secrets
curl -X POST https://api.relai.fi/facilitator/agent-budget/prepare \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "amount": 1000000, "expiry": 1735000000 },
      { "amount": 1000000, "expiry": 1735000000 },
      { "amount": 1000000, "expiry": 1735000000 }
    ]
  }'

# Response
{
  "secrets": ["0xabc123...", "0xdef456...", "0x789xyz..."],
  "depositCalldata": [
    { "hashlock": "0x...", "amount": 1000000, "expiry": 1735000000 },
    ...
  ],
  "totalAmount": 3000000,
  "totalHuman": "3.00",
  "vaultAddress": "0xA570faFC8128792fD71503026cC683A3d54369Eb",
  "usdc": "0x2e08028E3C4c2356572E096d8EF835cD5C6030bD"
}
Agent redeems a secret
curl -X POST https://api.relai.fi/facilitator/agent-budget/redeem \
  -H "Content-Type: application/json" \
  -d '{
    "secret": "0xabc123...",
    "payee": "0xApiProviderAddress"
  }'

# Response
{
  "success": true,
  "txHash": "0x...",
  "amount": 1000000
}

Contract Reference

AgentBudgetVault · SKALE Base Sepolia (chainId: 324705682)
0xA570faFC8128792fD71503026cC683A3d54369Eb
deposit(address usdc, Item[] items)

Lock USDC for each item. Item = { hashlock, amount, expiry }. Caller becomes owner of each commitment.

redeem(bytes32 secret, address payee)

Reveal preimage. If hash(secret) matches a commitment, transfers amount to payee. Anyone can call.

cancel(bytes32 hashlock)

Owner cancels a single unused commitment and recovers USDC.

cancelBatch(bytes32[] hashlocks)

Owner cancels multiple commitments in one transaction. Skips already-used ones.

reclaimExpired(bytes32[] hashlocks)

Reclaim expired, unused commitments. Anyone can call after expiry — funds returned to owner.

Security Model

Agent compromise → bounded loss

If the agent leaks or misuses secrets, the attacker can only spend committed amounts. The owner's main wallet is untouched.

Secret confidentiality

Secrets are generated client-side and never stored on the RelAI server. The server only knows hashlocks (SHA-256 hashes). Treat secrets like API keys.

Expiry safety net

Every commitment has an expiry timestamp. After expiry, reclaimExpired() returns all unspent USDC to the owner even without knowing the secrets.

No partial spending

Each secret unlocks exactly one fixed-amount commitment. There is no way to spend a fraction of a commitment — choose denomination granularity at deposit time.