How to Send Private Agent Payments on Solana
Guides & Tutorials

How to Send Private Agent Payments on Solana

Andy (Developer Relations)
Andy (Developer Relations)
@fauxfire_

Agents are amazing.

They can write code, summarize meetings, and argue with your linter for 45 minutes.

However there’s still one thing that’s awkward to do with them: payments

You can give your agent access to a virtual card or a crypto wallet. You can even hand it a private key directly (which is one of those ideas that works right up until it sends your entire wallet balance to a random X user)


The more reasonable pattern is: let the agent request a payment, let an API build the actual transaction, and let a wallet tool handle signing with human approval in the loop.MagicBlock's Private Payments API is built for exactly that pattern. It builds the private transfer transaction, returns it unsigned, and hands signing back to whatever wallet your agent is using. For this walkthrough I used Crossmint's agent wallet.

The Flow

LobsterCash (by Crossmint) gives your agent a managed wallet and CLI. The agent can ask it to sign and submit transactions, but you still have an approval step instead of letting the model directly run your wallet.


MagicBlock's Private Payments API does the other half. It builds the Solana transaction for a private SPL transfer and returns it unsigned.


So the agent doesn't need to know how to manually construct the full private transfer instruction. It just needs to:

1. Resolve the recipient address

2. Call the Private Payments API

3. Hand the returned serialized transaction to LobsterCash

4. Ask the user for approval

That sounds almost too simple, but that's kind of the point. Agents are good at orchestrating tools (especially if you are using a non-SOTA model to save costs on your harness). However, they are not where I want to construct complicated Solana transactions.

What are MagicBlock’s Private Payments?

A private USDC transfer through the MagicBlock payment API is a good example of the flow.


Under the hood, the transaction routes the funds through a Private Ephemeral Rollup. The rough version is:

1. USDC moves into a vault

2. The vault state is delegated into the Private Ephemeral Rollup, which is secured by a TEE

3. The transfer happens inside the PER.

4. The result is committed back to Solana mainnet


The important part is that the public transaction no longer looks like a normal "sender X transfers directly to recipient Y" SPL payment. The recipient's associated token account is not exposed in the same obvious account list next to the sender. The simple sender-to-recipient graph is broken.


This is useful for agent payments because payment intent can leak a lot. If your agent is paying for a hotel, a SaaS tool, a data endpoint, or some random API it found while doing work for you, you probably don't want the whole world trivially connecting that payment back to your main wallet.

Transfer API

One thing I think matters a lot for agents: an API that returns an unsigned transaction, not a server-side send. That means the server can own the construction logic, but the wallet still owns the signing.

For a private transfer, the request is just the fields a developer or agent can reason about:

curl --request POST \  
	--url https://payments.magicblock.app/v1/spl/transfer \  
	--header 'Content-Type: application/json' \  
    --data '{    
    "from": "<agent-wallet>",
    "to": "<recipient-wallet>",
    "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": 1000000,
    "visibility": "private",
    "fromBalance": "base",
    "toBalance": "base",
    "initIfMissing": true,
    "initAtasIfMissing": true,
    "initVaultIfMissing": true,
    "minDelayMs": "0",
    "maxDelayMs": "0",
    "split": 1
  }'


Amounts are in base units, so `1000000` is 1 USDC for a 6-decimal mint.

The response gives you a serialized unsigned transaction:

{  
  "kind": "transfer",
  "version": "legacy",
  "transactionBase64": "...",
  "sendTo": "base",
  "requiredSigners": ["<agent-wallet>"]
}


That `transactionBase64` is the boundary I like.

MagicBlock builds it. LobsterCash signs it. The agent coordinates the two.

If the way the private transfer is constructed changes in the future, the agent flow doesn't need to relearn Solana internals. The API changes, and the agent still receives the same kind of object.

Agent Skills

Skills make the handoff reliable.

At its core, a skill is just a text file that tells the agent what tool exists, when to use it, what commands to run, and what common failures look like. Not glamorous, but very useful.

For this flow, there are two relevant skills:

- LobsterCash's skill, which teaches the agent how to use the `lobstercash` CLI.

- MagicBlock's dev skill, which has a Private Payments section explaining the API shape.

You can check out the MagicBlock skill here: https://github.com/magicblock-labs/magicblock-dev-skill

The private payments section tells the agent: if the user asks for a private transfer, call the MagicBlock API, take the returned transaction, and pass it into LobsterCash.

The LobsterCash side is the signing step:

lobstercash crypto tx create \
	--type serialized \
	--serialized-transaction "$TRANSACTION_BASE64"


LobsterCash creates the transaction request and gives you an approval step. Once approved, it signs with the agent wallet and submits the transaction.

This is the part I like: the model is not holding your private key, or manually building the transaction, or trying to be a wallet. It is only gluing together two systems with clear responsibilities.

Do It Yourself


First, set up LobsterCash:

npm install -g @crossmint/lobster-cli 

lobstercash agents register \
  --name "Solana Payments Agent" \
  --description "Signs Solana private payment transactions" \
  --network solana 
    
lobstercash setup
lobstercash status


If you already have a LobsterCash agent registered on Solana, use that one instead. The network matters here because the private payment transaction is a Solana transaction.

Then install the MagicBlock skill into your agent:

npx add-skill https://github.com/magicblock-labs/magicblock-dev-skill


Now you can give the agent a prompt like:

Send 1 USDC privately to <recipient> using MagicBlock private payments and LobsterCash.


The agent should:

1. Check the LobsterCash wallet address.

2. Build a private transfer with `POST /v1/spl/transfer`.

3. Pass `transactionBase64` into `lobstercash crypto tx create`.

4. Ask you to approve the transaction.

5. Return the explorer link after confirmation.


If you are wiring it manually, keep these details in mind:

- Use base units for amounts.

- Set `visibility` to `private`.

- For the simplest transfer flow, set the init flags to `true`.

- Fund the Solana LobsterCash wallet with USDC and enough SOL for fees, unless you are using a sponsored route.

- Respect `sendTo` if you build your own submitter.

Why It Matters

A simple transfer is intentionally small. "Send 1 USDC privately" is not a world-changing function.


But the pattern is the useful part.


Agents are going to pay for things: API calls, cloud jobs, domains, subscriptions, data, hotel bookings, whatever. Some of that is just replacing commerce a human would have done manually. Some of it is probably new behavior, like tiny one-off payments for tools an agent discovers in the middle of a task (we’re seeing this emerge with x402 and MPP).


For that to work, payments need to be easy for agents, in control of the users, and private by default.


This flow gets pretty close:

- LobsterCash gives the agent a wallet and human-controlled signing.

- MagicBlock builds the private payment transaction.

- The agent coordinates the workflow without becoming the wallet.


That's the pattern I want more agent payments to move toward. Give the model tools with narrow interfaces. Keep signing explicit. Keep your payments the way they should be: private.