Blockchain & On-Chain Agents Best Practices
Ten practices for shipping agent tools that touch Solana (or any chain) without turning retries and hallucinations into lost funds.
Use this list when you design a new transfer/payment tool, review a PR that adds signing, or promote an agent from devnet to mainnet.
How to Use This Checklist
- Work top to bottom: threat model before fine-tuning prompts.
- Tick items only if they are true in the running system, not only in docs.
- Pair each gap with an owner and a ship gate (especially for mainnet).
- Re-run after tool schema changes, custody changes, or incident learnings.
A - Authority and Blast Radius
- 1. Split read tools from spend tools. Balance and history stay easy to call. Build, sign, and broadcast paths are separate tools with stricter auth and schemas.
- 2. Fund petty-cash wallets, not the treasury. Agent-facing balances are intentionally small; excess sweeps to colder custody on a schedule.
- 3. Keep private keys out of the model context. Secrets live in runtime env, KMS, or MPC custody (for example Fireblocks). Prompts and traces never print key material.
B - Correctness Under Failure
- 4. Require durable idempotency keys for every spend. One business
intentIdmaps to at most one successful signature; retries return the original receipt. - 5. Confirm at an explicit commitment before continuing the agent. Do not treat raw
sendacceptance as settlement; persist signature and status transitions. - 6. Pin cluster and asset units in code. Reject ambiguous SOL/lamports/token decimals in the tool layer; fail closed if cluster is unexpected for the environment.
C - Human and Policy Control
- 7. Gate high-value or novel destinations with human or policy approval. Micropayments may auto-sign inside caps; everything else uses propose → approve → sign.
- 8. Encode caps and allowlists outside the prompt. Schema max amounts, destination policies, and custody rules must enforce even if the model is injected or confused.
D - Prove Before Mainnet
- 9. Complete a devnet (or non-prod) checklist with duplicate-intent tests. Cover insufficient funds, bad pubkeys, payment validation, and crash/retry drills before mainnet keys exist.
- 10. Log intentId, policy decision, signature, and cluster for every attempt. Support and finance must reconstruct what the agent tried without replaying the LLM.
Applying the Habits in Order
| Stage | Habits | Exit criterion |
|---|---|---|
| Design | 1-3 | Tool map + wallet topology + secret boundary written |
| Implement | 4-6 | Intent store, confirms, unit/cluster guards in code |
| Control | 7-8 | Approval thresholds + policy engine/allowlists live |
| Release | 9-10 | Devnet evidence + audit trail before mainnet canary |
Quick Anti-Patterns
- One hot mainnet key shared by every agent and engineer.
- Regenerating
intentIdinside the tool on each retry. - Prompt-only instructions: "never send more than 1 SOL."
- Marking invoices paid from an unauthenticated webhook.
- Busy-looping the LLM on
findReference/ RPC polls. - Skipping
validateTransferafter Solana Pay detection. - Copy-pasting devnet
.envto production and changing only the slogan in README. - Open-ended "sign arbitrary transaction bytes" tools in production.
Minimal Reference Pattern
intentId (from workflow)
-> validate schema (cap, pubkey, cluster)
-> claim intent row (pending)
-> optional human/policy approve
-> sign via custody or limited hot key
-> broadcast + confirm
-> store signature (confirmed)
-> agent continues with receipt only// Sketch: refuse writes without intent + cluster pin
function assertSpendAllowed(args: { intentId: string; sol: number }, cluster: string) {
if (cluster !== process.env.EXPECTED_CLUSTER) throw new Error("cluster mismatch");
if (!args.intentId || args.intentId.length < 8) throw new Error("intentId required");
if (args.sol > Number(process.env.MAX_AUTO_SOL ?? "0.01")) throw new Error("over cap");
}FAQs
Which practices are non-negotiable for mainnet?
Idempotency (4), confirm-before-continue (5), key separation (3), and caps/allowlists outside the prompt (8). Without those, autonomy is gambling.
Do read-only chain agents need this whole list?
They still need cluster pinning, rate limits, and no secret leakage. Spend-specific items apply when you add the first write tool.
Is Fireblocks mandatory?
No. It is one strong custody option. Low balances + KMS + policy may suffice early; institutional setups often want MPC + policy engines.
How does this relate to normal agent security?
All standard rules still apply (sandboxing, least privilege, injection resistance). On-chain tools raise the severity of failure, so approval and idempotency become first-class.
Can multi-agent designs skip human approval?
Only if policy engines and economic caps truly bound loss. Multiple agents sharing one unlimited key are worse, not better.
What should we monitor daily?
Spend per intent, duplicate rate, policy denials, failed confirms, vault balance, and any tool call missing an intentId.
When do we raise auto-sign limits?
After clean canaries, stable metrics, and explicit finance approval. Raise slowly; never jump from demo caps to treasury-sized caps.
Where should teams go deeper next?
Guardrails explainer, transfer tool recipe, Solana Pay verification, idempotency deep dive, custody options, and the devnet cheatsheet in this section.
Related
Related: Why On-Chain Agents Need Different Guardrails Than Other Tools
Related: Blockchain & On-Chain Agents Basics
Related: Idempotency and Double-Spend Protection for On-Chain Agent Actions
Related: Key Management for Agent-Controlled Wallets: Fireblocks and Alternatives
Related: Testing On-Chain Agent Flows on Devnet Before Mainnet
Related: Solana Pay: Verifying Payments via Webhook or Polling
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.