Agent Wallet SDK
Give your AI agent a self-custodial wallet with on-chain spend limits. The SDK handles x402 payments automatically.
Machine-readable version: /llms.txt
Overview
LumenBro Agents gives AI agents self-custodial wallets on Stellar. Your agent calls any x402-enabled API, the SDK detects the 402, signs a payment from the smart wallet, and retries. No API keys, no custodians, no seed phrases.
- Create a wallet at agents.lumenbro.com — deploys a Stellar smart account (C-address) secured by your passkey
- Register an agent signer — Ed25519 keypair or P-256 key, each gated by a daily spend policy
- Fund with USDC — send USDC to your wallet's C-address
- Use the SDK —
npm install lumenjoule-sdk, callclient.chat(), done
Agent keys only sign auth entries (not TX envelopes). The facilitator pays gas and submits the transaction. Agent keys never need XLM funding for x402 payments.
Smart Wallet Architecture
Each wallet is a Stellar smart account (C-address) that acts as a shared vault. Multiple agent signers draw from the same balance, each with independent daily limits.
C-address (Vault)
The smart account that holds all funds. Every transfer is gated by __check_auth which validates the signer's key + spend policy before allowing the transaction.
Agent Signers
Delegated signing keys registered on the wallet. Each signer has its own key type (Ed25519 or Secp256r1) and is bound to a spend policy contract. Like corporate cards — one funding account, multiple cards with individual limits.
Spend Policies
On-chain ExternalValidatorPolicy contracts that enforce daily USDC limits. Checked on every transfer() and approve(). Even if a key is compromised, damage is capped to one day's limit.
Smart account contract source: github.com/lumenbro/stellar-smart-account · Spend policy source: github.com/lumenbro/soroban-policies
Quick Start
1. Install
npm install lumenjoule-sdkCreate a wallet at agents.lumenbro.com if you haven't already.
2. Configure
import { SmartWalletClient } from "lumenjoule-sdk";
const client = new SmartWalletClient({
agentSecretKey: process.env.AGENT_SECRET, // S... key from portal
walletAddress: "CXXX...", // your wallet C-address
network: "mainnet",
});3. Use
const response = await client.chat({
model: "deepseek-ai/DeepSeek-V3",
messages: [{ role: "user", content: "Hello!" }],
});
console.log(response.choices[0].message.content);The SDK handles the x402 payment automatically: request → 402 → sign payment → retry → response.
Signer Types
Three signer implementations, same smart wallet. Pick based on your platform and security requirements.
| Signer | Platform | Key Storage | Best For |
|---|---|---|---|
Ed25519 | All | Secret key string (S...) | Simplest setup, any platform |
SoftP256Signer | All | Encrypted file (~/.lumenjoule/) | Linux VPS, cloud servers, dev |
KeypoSigner | macOS | Secure Enclave (hardware) | Maximum security, Mac Mini |
Ed25519 — Stellar Keypair (Any Platform)
The simplest option. Generate a Stellar keypair, register the public key (G-address) as an agent signer in the portal, and pass the secret key to the SDK.
import { SmartWalletClient } from "lumenjoule-sdk";
const client = new SmartWalletClient({
agentSecretKey: process.env.AGENT_SECRET, // S... secret key
walletAddress: "CXXX...", // wallet C-address
network: "mainnet",
});SoftP256Signer — Software P-256 (Any Platform)
Encrypted P-256 key stored on disk. Same signing format as Secure Enclave — production-ready on Linux VPS, Windows, macOS. AES-256-GCM encryption with PBKDF2-derived key.
import { SmartWalletClient, SoftP256Signer } from "lumenjoule-sdk";
// First time: generate and save encrypted key
const signer = await SoftP256Signer.generate("my-password");
// Saved to: ~/.lumenjoule/agent-key.enc
// Prints: public key (paste into portal when registering Secp256r1 signer)
// After: load existing key
const signer = await SoftP256Signer.load("my-password");
const client = new SmartWalletClient({
signer,
walletAddress: "CXXX...",
network: "mainnet",
});KeypoSigner — Secure Enclave (macOS)
Hardware-bound P-256 key via keypo-signer. The private key lives in the Secure Enclave and can never be extracted. Install: brew install keypo-signer.
import { SmartWalletClient, KeypoSigner } from "lumenjoule-sdk";
const signer = new KeypoSigner({
keyLabel: "my-agent-key",
publicKey: Buffer.from("BASE64_PUBLIC_KEY", "base64"),
});
const client = new SmartWalletClient({
signer,
walletAddress: "CXXX...",
network: "mainnet",
});Pay Any x402 Endpoint
The wallet isn't limited to one service. payAndFetch() works with any x402-compatible endpoint on any server. chat() is a convenience wrapper for OpenAI-compatible inference APIs.
// AI inference (OpenAI-compatible)
const response = await client.chat({
model: "deepseek-ai/DeepSeek-V3",
messages: [{ role: "user", content: "Analyze this data" }],
});
// Any x402 endpoint
const data = await client.payAndFetch("https://some-api.com/v1/data", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: "..." }),
});
// Direct USDC transfer (non-x402, agent pays gas)
const txHash = await client.transfer(
USDC_CONTRACT,
recipientAddress,
1_000_000n, // 0.1 USDC (7 decimals)
);Spend Policies
Every agent signer is gated by an on-chain ExternalValidatorPolicy contract. The policy is enforced during __check_auth on every transfer and approval. Even if a key is compromised, damage is capped.
CBRGH27ZFVFDIHYKC4K3CSLKXHQSR5CFG2PLPZ2M37NH4PYBOBTTQAECCCRIFGLMG3PT7R3V2IFSRNDNKR2Y2DLJAI5KXYBKNJPFCL2QC4MDIZNJCCSPAXNEVBNA5QAEU2YEUTU56O5KOZM4C2O7ONQ6GFPSHEWV5OJJS5H2Query Budget
// Requires policyAddress in constructor
const client = new SmartWalletClient({
agentSecretKey: process.env.AGENT_SECRET,
walletAddress: "CXXX...",
policyAddress: "CBRGH27Z...", // Starter tier
});
const budget = await client.budgetStatus();
// { dailyLimitUsdc: 50, spentTodayUsdc: 3.20, remainingUsdc: 46.80 }
// Individual queries
const limit = await client.dailyLimit(); // 500_000_000n (stroops)
const spent = await client.spentToday(); // 32_000_000n
const remaining = await client.remaining(); // 468_000_000nx402 Payment Protocol
The SDK implements the x402 payment protocol for Stellar. Compatible with both the LumenBro facilitator and the OpenZeppelin Stellar facilitator.
402 Payment Required with price, asset, and destinationPAYMENT-SIGNATURE header (v2) + X-Payment (v1 compat)The facilitator is a neutral relay — it doesn't need to understand smart wallets or signer types. It receives pre-signed auth entries, rebuilds the TX, and submits. The Soroban runtime calls __check_auth on your wallet contract transparently.
API Reference
SmartWalletClient Constructor
| Option | Type | Default | Description |
|---|---|---|---|
walletAddress | string | required | Smart wallet C-address |
agentSecretKey | string | — | Ed25519 secret key (S...) |
signer | AgentSigner | — | Pluggable signer (alternative to agentSecretKey) |
network | "testnet" | "mainnet" | "mainnet" | Stellar network |
computeUrl | string | compute.lumenbro.com | Default x402 endpoint for chat() |
rpcUrl | string | auto | Custom Soroban RPC URL |
policyAddress | string | — | Spend policy contract (for budget queries) |
preferredAsset | string | USDC | Payment asset contract |
Methods
| Method | Description |
|---|---|
chat(request) | OpenAI-compatible chat completion with automatic x402 payment |
payAndFetch(url, init?) | Pay any x402 endpoint and return the response |
transfer(token, to, amount) | Direct token transfer (Ed25519 only, agent pays gas) |
usdcBalance() | USDC balance of the wallet (7-decimal stroops) |
balance(token?) | Any token balance (defaults to LumenJoule) |
gasBalance() | XLM balance of the wallet |
budgetStatus() | Daily limit, spent today, remaining (requires policyAddress) |
dailyLimit() | Policy daily limit in stroops |
spentToday() | Amount spent today in stroops |
remaining() | Remaining daily budget in stroops |
x402 Protocol Helpers
import { parsePaymentRequirements, performX402Dance } from "lumenjoule-sdk";
// Parse 402 response headers
const requirements = parsePaymentRequirements(response);
// { scheme, payTo, amount, asset, network, maxTimeoutSeconds, ... }
// Full dance: request -> 402 -> build payment -> retry
const paidResponse = await performX402Dance(url, init, buildPaymentFn);Compute Server API
The default x402 endpoint for client.chat(). OpenAI-compatible, accepts USDC payments via x402.
POST /v1/chat/completionsOpenAI-compatible chat completion. Returns 402 with payment requirements on first request.
GET /api/modelsList available models and per-token pricing
Base URL: https://compute.lumenbro.com
You can point computeUrl to any x402-compatible inference server. The wallet is not locked to LumenBro compute.
Why Self-Custody Matters
Your agent's signing key lives on your device. The server never touches private keys — it only wraps transactions for gas sponsorship.
| Provider | Key Model | Self-Custodial? |
|---|---|---|
| lumenjoule-sdk | Device-local (SE, passkey, encrypted file) | Yes |
| Privy | MPC sharded (server holds share) | No |
| Crossmint | API key custodial | No |
| Turnkey | Infra-managed HSM | No |
| Coinbase AgentKit | CDP API key | No |
If your wallet provider goes down or changes terms, your agent's wallet should still work. With self-custody, it does. The server is only a gas sponsor — it fee-bumps pre-signed transactions but never has access to your keys.
FAQ
Does my agent key need XLM?
No. For x402 payments (the primary use case), the facilitator pays gas. Your agent key only signs auth entries, not TX envelopes. A freshly-created agent key can immediately start making x402 payments. Only direct transfer() calls require XLM on the agent's G-address.
What happens if my agent key is compromised?
Damage is capped by the on-chain spend policy. If your agent is on the Starter tier, an attacker can drain at most $50 in one day. You can revoke the signer from the dashboard at any time using your passkey.
Can I use this with my own inference server?
Yes. Set computeUrl to your server, or use payAndFetch() for any x402-compatible endpoint. The wallet is a general-purpose x402 payment wallet — it works with any service that speaks the protocol.
Which signer should I use on a Linux VPS?
Use SoftP256Signer with an encrypted key file, or Ed25519 if you prefer simplicity. Cloud VPS providers don't expose hardware security modules. The spend policy is your primary security layer — it caps damage regardless of key custody method.
Can multiple agents share one wallet?
Yes, that's the design. One wallet C-address holds pooled USDC. Each agent signer has its own key and independent daily limit. Like a corporate card program — one funding account, multiple cards.
What's the difference between Ed25519 and P-256?
Ed25519 is the native Stellar key format — simple and widely supported. P-256 (secp256r1) is the curve used by Secure Enclave, TPM, and WebAuthn passkeys — it enables hardware-bound keys that can never be extracted. Both produce the same auth format from the smart wallet's perspective.
How do I upgrade my spend policy tier?
Revoke the existing signer from the dashboard, then re-register the same key with a higher-tier policy contract. Tier upgrades will be automated in a future portal update.
Resources
- Agent Portal — Create wallets + register agent signers
- lumenjoule-sdk on npm
- SDK on GitHub
- x402 Protocol Specification
- LumenJoule Token
- LumenJoule on StellarExpert
- Stellar
