Skip to main content
LearnGuidesSecure your agent wallet
GUIDE

Secure your agent wallet before going live.

15 minutes
SHORT ANSWER

Going to production with agent payments is not the same checklist as a normal API integration. Add: a deliberate wallet-type choice, a tuned spend policy (not defaults), API and webhook secret rotation on a stated cadence, a weekly audit-log review, and an incident-response runbook that has been drilled at least once. Without these, you ship and learn the hard way.

PREREQUISITES

Before you start.

  • A working agent integration end-to-end on test - see add-payments-to-agent and test-without-real-money.
  • Spend controls configured - see spend controls (this guide assumes a policy is already in place).
  • A secret manager (AWS Secrets Manager, GCP Secret Manager, Vault, 1Password, etc) - secrets in .env files are not enough.
  • A clearly identified on-call engineer with admin access to the wallet dashboard.
  • 15 minutes of focused time. The checklist below is not aspirational - work through it line by line.
STEP 1 OF 4

Run the pre-launch checklist.

Eleven items. Each one is a yes/no question with a single owner. If any item is unchecked, do not go live - work that item to closure first. The cost of a missed item in production is always larger than the cost of finishing it now.

# Pre-launch security checklist for agent wallets.

[ ] Wallet type chosen with reasoned trade-offs (smart wallet vs EOA).
[ ] Spend policy in place: daily cap, per-payment cap, default_action.
[ ] Counterparty allowlist on, OR an explicit decision to leave it off.
[ ] All API keys stored in a secret manager (not env files committed to git).
[ ] Test keys and live keys cannot be swapped (boot-time prefix check in place).
[ ] Webhook signing secret rotated within the last 90 days.
[ ] Webhook URL pointed at production, not a tunnel.
[ ] Audit-log retention reviewed; alerting in place for unusual events.
[ ] policy_violation events trigger an alert (>5/hour from one agent).
[ ] Incident runbook exists, has been read by someone other than the author.
[ ] One person other than you knows how to revoke an API key in < 5 minutes.
STEP 2 OF 4

Schedule API key and webhook secret rotation.

Quarterly is the default cadence; rotate immediately on any of: suspected leak, lead engineer departure, security incident elsewhere in the company. The two-key window pattern lets you swap keys with zero downtime: create the new key, deploy it everywhere, verify, then revoke the old one.

TypeScript
// One-time key rotation script. Run quarterly, on lead departure, on suspected leak.
import { Blockchain0x } from "@blockchain0x/sdk";

const adminClient = new Blockchain0x({ apiKey: process.env.BLOCKCHAIN0X_ADMIN_KEY! });

async function rotate() {
  const fresh = await adminClient.apiKeys.create({
    name: `prod-${new Date().toISOString().slice(0, 10)}`,
    scope: ["payments:read", "payments:write", "policy:write"],
  });
  console.log("NEW KEY:", fresh.secret);            // Store in secret manager NOW.

  // Wait until the new key is deployed and verified working, THEN:
  // await adminClient.apiKeys.revoke(OLD_KEY_ID);
}
Python
# One-time key rotation script. Run quarterly, on lead departure, on suspected leak.
from blockchain0x import Client
import datetime, os

admin = Client(api_key=os.environ["BLOCKCHAIN0X_ADMIN_KEY"])

def rotate():
    fresh = admin.api_keys.create(
        name=f"prod-{datetime.date.today().isoformat()}",
        scope=["payments:read", "payments:write", "policy:write"],
    )
    print("NEW KEY:", fresh.secret)   # Store in secret manager NOW.

    # Wait until new key is deployed and verified, THEN:
    # admin.api_keys.revoke(OLD_KEY_ID)

Webhook signing secrets rotate similarly through the dashboard - enable a second secret, redeploy the handler to accept either, then retire the old one. Both at quarterly cadence with calendar reminders.

STEP 3 OF 4

Set up the weekly audit review.

Three things to look at every week: new counterparties (anything not seen before deserves a 30-second sanity check), policy_violation events (the policy did its job - did the agent get stuck somewhere?), and off-hours payments (a payment at 3am from an agent that nominally only runs business hours is the kind of signal that catches injection attacks early).

TypeScript
// Weekly audit query: anything that looks unusual.
const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
const txns = await client.transactions.list({
  status: "confirmed",
  since,
  limit: 500,
});

// Heuristics worth looking at:
const newCounterparties = txns.data.filter((t) => t.counterparty_first_seen);
const policyHits = txns.data.filter((t) => t.policy_decision !== "allow");
const offHours = txns.data.filter((t) => {
  const h = new Date(t.confirmed_at).getUTCHours();
  return h < 5 || h > 22;
});

console.log({ newCounterparties, policyHits, offHours });
Python
from datetime import datetime, timedelta, timezone

since = (datetime.now(timezone.utc) - timedelta(days=7)).isoformat()
txns = client.transactions.list(status="confirmed", since=since, limit=500)

new_counterparties = [t for t in txns.data if t.counterparty_first_seen]
policy_hits = [t for t in txns.data if t.policy_decision != "allow"]
off_hours = [
    t for t in txns.data
    if not (5 <= datetime.fromisoformat(t.confirmed_at).hour <= 22)
]

print({"new_counterparties": new_counterparties, "policy_hits": policy_hits, "off_hours": off_hours})
STEP 4 OF 4

Write (and drill) the incident runbook.

A runbook is only as good as how recently it was tested. Below is the template - copy it into your team's wiki, edit for your specifics, and schedule a 30-minute drill in the next quarter. Time it; fix whatever the drill reveals as missing.

# Incident response runbook — Agent wallet compromise (suspected or confirmed)

## Trigger
Any of:
- Unrecognised counterparty receiving > $10 USDC.
- > 50 policy_violation events from one agent in an hour.
- Engineer reports they cannot account for a recent payment.
- A leaked API key surfaces in a public scan.

## Step 1 — Stop the bleeding (< 5 minutes)
- Revoke the suspect API key via dashboard or admin.apiKeys.revoke.
- Pause the agent: client.agents.update(id, { status: "paused" }).
- Lower the agent's daily cap to $0 as a belt-and-suspenders measure.

## Step 2 — Preserve evidence (< 15 minutes)
- Pull the last 24h of transaction logs and policy_violation events.
- Snapshot the agent's spend policy as it was at the time of the incident.
- Note the timestamps of any unrecognised payments and their tx_hash on Base.

## Step 3 — Communicate (< 30 minutes)
- Inform the on-call lead and finance.
- If customer funds are affected, draft a notification template (do not send
  until investigation is far enough along to be accurate).

## Step 4 — Root cause and remediation (24-72 hours)
- Determine: leaked key, compromised webhook secret, prompt-injection
  bypass, integration bug, or other.
- Rotate every secret that could have been exposed.
- Tighten the spend policy or counterparty allowlist to prevent recurrence.
- File a post-mortem with timeline, RCA, and follow-ups.
COMMON PITFALLS

Five things that catch teams in their first production incident.

Treating a new agent as 'just like the old one'

Every agent gets its own profile, its own keys, its own spend policy. If you reuse keys across agents 'because they are similar', a single key compromise blasts every agent at once. Spinning up a new agent profile takes one API call; the per-agent isolation is worth the minute it costs to do it correctly.

Spend caps tuned by default, not by data

The system defaults are conservative because they have to work for everyone. If you leave them in place at scale, the agent hits the cap mid-day every day and you spend hours debugging 'payment failed' before remembering the cap is too low. Within the first week, look at actual daily spend and set the cap at 2-3x that - not 1x (too tight) and not 100x (effectively unlimited).

Webhook signing secret never rotated

An incident that leaks the signing secret means an attacker can forge webhooks that look like legitimate payment.confirmed events, which can trick your handler into delivering work that was never paid for. Rotate the signing secret on the same cadence as API keys (quarterly) or any time you suspect exposure. The dashboard supports a no-downtime rotation: enable a second secret, deploy the handler that accepts either, retire the old one.

Audit logs that nobody reads

An audit log only catches things if someone looks at it. Most teams enable the log, never look at it, and find out about issues from customer complaints. Schedule a weekly 15-minute review: new counterparties, policy_violations, off-hours payments. The cost is tiny; the time to detect drops from weeks to days.

No drill on the incident runbook

A runbook that has never been exercised is fiction. Pick a quarterly date, simulate a leaked-key scenario, time how long it takes to revoke and contain. The first drill always reveals something missing (the engineer who knows how to rotate is on vacation, the runbook is behind an expired Notion link). Better to find that in a drill than at 3am during a real incident.

NEXT STEPS

After the security pass.

Security is never done, but the rest of the operational stack benefits from a clean baseline. Tighten spend controls as actual usage data accumulates, harden webhook handling against load, and verify agent identity so counterparties trust your public profile.

Full reference at docs.blockchain0x.com. Related glossary: Coinbase Smart Wallet. Product surface: Agent wallets.

Last reviewed: 2026-05-15. Published under CC BY 4.0.

Ship knowing the wallet is hardened.

Pre-flight checklist, rotation cadence, runbook drilled. Free to start.