Testing On-Chain Agent Flows on Devnet Before Mainnet
Prove the full agent path on Solana devnet (or another non-production cluster) before any mainnet key, RPC, or balance is introduced.
How to Use This Cheatsheet
- Run top to bottom for a new on-chain agent or a major tool change.
- Tick items only when automated or scripted evidence exists (CI log, saved signature, eval report).
- Keep mainnet credentials out of the environment until the Mainnet gate section is fully green.
- Re-run after dependency upgrades of
@solana/web3.js,@solana/spl-token,@solana/pay, or custody SDKs.
A - Environment Isolation
| Check | Pass criteria |
|---|---|
| Cluster pin | Config requires SOLANA_CLUSTER=devnet (or testnet) for CI and local agent runs |
| RPC URL | Points at devnet host; no mainnet-beta URL in .env.example for agent writes |
| Key material | Disposable keypairs only; secrets named *_DEVNET_* |
| Faucet funding | Payer has enough devnet SOL for fees + test transfers |
| Write flag | AGENT_CHAIN_WRITES enabled only in explicit test profiles |
| No prod custody | Fireblocks/prod API keys absent from dev profiles |
B - Tool Correctness on Devnet
| Check | Pass criteria |
|---|---|
| Read tools | getBalance / token balance match explorer for same address |
| transferSOL | Confirmed signature; lamports match args; recipient correct |
| createTransaction | Serialized tx simulates cleanly; blockhash fields present |
| Caps | Over-max amounts rejected without broadcast |
| Bad pubkey | Invalid destination returns structured error |
| Cluster label | Every tool result includes cluster: "devnet" |
C - Idempotency and Retries
| Check | Pass criteria |
|---|---|
| Stable intentId | Same business task reuses one id across retries |
| Duplicate call | Second transferSOL returns prior signature, not a new debit |
| Crash mid-flight | Restart reconciles pending/submitted without double pay |
| Arg conflict | Same intentId with different amount/destination fails conflict |
| Parallel workers | Two workers cannot both confirm different signatures for one intent |
D - Solana Pay / Incoming Payments (if used)
| Check | Pass criteria |
|---|---|
| Unique reference | New reference per intentId |
| Happy path | Pay request → user/script payment → validateTransfer → agent resumes |
| Wrong amount | Validation fails; fulfillment blocked |
| Webhook auth | Forged webhook without valid chain tx does not mark paid |
| Expiry | Stale intents expire; agent surfaces expired |
E - Agent Loop Behavior
| Check | Pass criteria |
|---|---|
| No secret leakage | Traces/prompts lack private keys and custody API secrets |
| Confirm-before-continue | Downstream steps wait for confirmed/paid status |
| Timeout handling | RPC timeout does not auto-mint a new intentId |
| Injection drill | Malicious tool args cannot exceed caps or leave allowlist |
| Stop conditions | Max spend per run enforced in runtime, not only in prompt |
F - Observability and Audit
| Check | Pass criteria |
|---|---|
| Intent log | DB/log has intentId, args hash, status, signature, cluster |
| Explorer link | Support can open signature on devnet explorer |
| Metrics | Counters for success, duplicate, fail, policy deny |
| Alert dry-run | Simulated double-spend attempt pages or tickets in staging |
G - Mainnet Gate (only after A-F)
| Check | Pass criteria |
|---|---|
| Separate config | New env/profile; no accidental URL swap |
| Petty cash vault | Low initial balance; sweep policy defined |
| Custody policy | Caps/allowlists live in signer policy (Fireblocks or equivalent) |
| Kill switch | Documented disable for write tools / API user |
| Canary amount | First live tests use minimal value and allowlisted dest |
| Rollback plan | How to halt agent and reconcile open intents |
Quick Command Pad
# Disposable devnet key (example)
node -e "const {Keypair}=require('@solana/web3.js');const k=Keypair.generate();console.log(k.publicKey.toBase58())"
# Sanity: RPC is devnet
# curl -s $SOLANA_CLUSTER_URL -X POST -H 'Content-Type: application/json' \
# -d '{"jsonrpc":"2.0","id":1,"method":"getGenesisHash"}'
# Compare with known devnet genesis (verify current value at build)CI suggestion:
unit: schema + intent store state machine (no RPC)
integration: devnet transfer + duplicate intent (RPC secret in CI vault)
eval: agent trajectories that must call createPayment / transfer with caps
forbid: mainnet private keys in CIFailure Patterns Cheatsheet
| Symptom | Likely cause | Fix |
|---|---|---|
| Insufficient funds | Empty faucet wallet | Airdrop/fund; assert balance preflight |
| Tx expired | Stale blockhash on delayed sign | Rebuild tx; reduce approval latency |
| Duplicate user debit | New intentId on retry | Bind intent in orchestrator |
| Tool says ok, explorer empty | Wrong cluster or only "sent" not confirmed | Pin cluster; wait on commitment |
| ATA errors | Missing token account | Gated create ATA; handle missing |
| Policy deny in prod only | Dev had no custody policy | Mirror policies on dev workspace |
FAQs
Is testnet better than devnet?
Either is fine if it is non-production and funded consistently. Pick one for CI stability and document it. Devnet is the common default for Solana public experiments.
Can I fork mainnet state instead?
Local validators / mainnet-beta clones help program tests. Agent custody, RPC config, and intent stores still need an explicit non-prod promotion path.
How many successful devnet transfers before mainnet?
Enough to cover happy path, duplicate intent, insufficient funds, bad destination, and approval deny. Quality of scenarios beats raw count.
Should evals hit real RPCs?
Yes for a small integration suite. Mock unit tests for schema and state machines; keep a scheduled devnet smoke so RPC and library drift show up.
What is the #1 mainnet accident?
Wrong cluster URL or shared hot key with high balance. The gate table exists to prevent that class of mistake.
Do I retest after raising amount caps?
Yes. Treat cap changes as production releases with the same checklist subset (C, E, G).
How do Fireblocks sandboxes fit?
Use non-prod workspaces with policies that mirror production. Never reuse production API users for agent CI.
When is mainnet canary done?
After multiple small live intents, monitoring is quiet, reconciliation matches explorer, and finance signs off on the vault balance risk.
Related
Related: Blockchain & On-Chain Agents Basics
Related: Idempotency and Double-Spend Protection for On-Chain Agent Actions
Related: Solana Pay: Verifying Payments via Webhook or Polling
Related: Key Management for Agent-Controlled Wallets: Fireblocks and Alternatives
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.