New: AI Agent SDK is live — integrate Claude-powered wallet actions into your app. Read the docs
Agent Integration

Agent Integration

Veil includes an AI agent powered by Claude that can check balances, fetch live prices, build swaps/payments, and request user approval — all through natural language. The agent uses x402 micropayments for paid data feeds (Oracle, Wraith).

There are two ways to integrate:

  1. SDK (createVeilAgent) — import and use directly in your Node.js backend
  2. WebSocket server — self-host the agent backend, connect from any frontend

Install the agent package:

npm install @veil/agent

Create an agent and start chatting:

import { createVeilAgent } from '@veil/agent'
 
const agent = createVeilAgent({
  anthropicApiKey: 'sk-ant-...',       // Your Claude API key
  agentKeypairSecret: 'S...',          // Stellar keypair for x402 payments
  oracleUrl: 'https://oracle.example.com',
  wraithUrl: 'https://wraith.example.com',
  // Optional:
  horizonUrl: 'https://horizon-testnet.stellar.org',
  network: 'testnet',
  model: 'claude-sonnet-4-6',
  maxHistoryTurns: 20,
})
 
// Send a message
const result = await agent.chat('What is my balance?', {
  walletAddress: 'CABC...',
  feePayerAddress: 'GABC...',
  profile: {
    name: 'Alice',
    role: 'trader',      // trader | investor | saver | explorer
    language: 'English',
    persona: 'concise and direct',
  },
})
 
console.log(result.response)
// "Your balance is 1,500 XLM and 47.3 USDC."
 
// If the agent built a transaction, it returns the unsigned XDR
if (result.pendingTxXdr) {
  console.log('Transaction needs approval:', result.pendingTxSummary)
  // → Sign with passkey and submit to Horizon
}
 
// Clear history for a wallet
agent.clearHistory('CABC...')
 
// The agent's Stellar public key (for x402 funding)
console.log('Fund this address for x402:', agent.publicKey)

AgentConfig

FieldRequiredDescription
anthropicApiKeyNoClaude API key. Falls back to ANTHROPIC_API_KEY env var
agentKeypairSecretYesStellar secret key for x402 micropayments
oracleUrlYesPrice oracle endpoint (x402-enabled)
wraithUrlYesTransfer indexer endpoint (x402-enabled)
horizonUrlNoDefault: https://horizon-testnet.stellar.org
sorobanRpcUrlNoDefault: https://soroban-testnet.stellar.org
networkNo"testnet" or "mainnet". Default: "testnet"
modelNoClaude model ID. Default: "claude-sonnet-4-6"
maxHistoryTurnsNoConversation turns to keep per wallet. Default: 20

AgentResult

FieldTypeDescription
responsestringThe agent’s text response
pendingTxXdrstring?Unsigned transaction XDR if the agent built a tx
pendingTxSummarystring?Human-readable summary of the pending tx

Architecture

Your App (React)           Agent Backend (Node.js)         Stellar
──────────────────         ─────────────────────────       ────────────
WebSocket client           Express + WebSocket server       Horizon API
 │                          │                               Soroban RPC
 │  { type: 'chat',        │                               │
 │    walletAddress,        │  Claude API (tool use)        │
 │    feePayerAddress,      │   ├─ get_price → Oracle ──── x402
 │    message,              │   ├─ get_transfer_history     │
 │    profile }             │   ├─ get_wallet_balance       │
 │ ─────────────────────▶   │   ├─ build_swap ──────────── Horizon
 │                          │   ├─ build_payment            │
 │  { type: 'response',    │   └─ request_user_approval    │
 │    message,              │                               │
 │    pendingTxXdr? }       │                               │
 │ ◀─────────────────────   │                               │
 │                          │                               │
 │  User approves with      │                               │
 │  passkey (biometric)     │                               │
 │  Signs + submits tx ─────┼───────────────────────────▶  Horizon

Self-Hosting the Agent Backend

The agent backend is a standalone Node.js server at packages/agent/.

1. Install dependencies

cd packages/agent
npm install

2. Configure environment

# .env
ANTHROPIC_API_KEY=sk-ant-...       # Your Claude API key
AGENT_KEYPAIR_SECRET=S...          # Stellar keypair for x402 micropayments
ORACLE_URL=https://your-oracle.com # Price feed API (x402-enabled)
WRAITH_URL=https://your-wraith.com # Transfer indexer API (x402-enabled)
HORIZON_URL=https://horizon-testnet.stellar.org
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org
STELLAR_NETWORK=testnet            # or "mainnet"
CLAUDE_MODEL=claude-sonnet-4-6   # optional, defaults to claude-sonnet-4-6
AGENT_PORT=3001                    # optional
ALLOWED_ORIGIN=*                   # CORS origin

3. Run

npm run dev    # Development with hot-reload
npm run build  # Compile TypeScript
npm start      # Production

The server exposes:

  • GET /health — returns { ok: true, agentAddress: "G..." }
  • WebSocket / — chat endpoint

WebSocket Protocol

Client → Server

Chat message:

{
  "type": "chat",
  "walletAddress": "C...",
  "feePayerAddress": "G...",
  "message": "Swap 100 XLM to USDC",
  "profile": {
    "name": "Alice",
    "language": "English",
    "role": "trader",
    "persona": "concise and direct"
  }
}

Clear history:

{
  "type": "clear_history",
  "walletAddress": "C..."
}

Server → Client

Thinking indicator:

{ "type": "thinking" }

Response (text only):

{
  "type": "response",
  "message": "Your balance is 1,500 XLM."
}

Response with pending transaction:

{
  "type": "response",
  "message": "I've built a swap of 100 XLM → USDC. Please review and approve.",
  "pendingTxXdr": "AAAAAB...",
  "pendingTxSummary": "Swap 100 XLM for ~12.5 USDC via SDEX"
}

Error:

{
  "type": "error",
  "message": "walletAddress and message required"
}

User Profile & Personalization

The agent adapts its behavior based on the profile object sent with each message.

Roles

RoleAgent behavior
traderSuggests trades on incoming funds, mentions spread/slippage, action-oriented
investorSuggests yield/diversification, emphasizes market context, analytical
saverFocuses on balance updates and payments, avoids jargon, reassuring
explorerExplains concepts, encourages learning, suggests simple actions

Language

Set profile.language to any supported language (e.g. "Spanish", "Yoruba", "Japanese"). The agent will respond in that language.

Persona

ValueTone
"" (empty)Friendly and professional (default)
"concise and direct"Short answers, no fluff
"friendly and casual"Relaxed, conversational
"detailed and educational"Explains concepts along the way
"witty and fun"Light-hearted with personality

Agent Tools

The agent has access to these tools via Claude’s tool-use API:

ToolDescriptionCost
get_priceLive SDEX + AMM prices and swap routesx402 micropayment
get_transfer_historyRecent Soroban + classic transfersx402 micropayment
get_wallet_balanceXLM + token balances (fee-payer + contract)Free
build_swapBuild a path payment (unsigned XDR)Free
build_paymentBuild a payment transaction (unsigned XDR)Free
request_user_approvalSend transaction to frontend for passkey approvalFree
⚠️

The agent never executes transactions directly. It always calls request_user_approval which sends the unsigned XDR to the frontend. The user must approve with their biometric (passkey) before the transaction is signed and submitted.


Proactive Notifications

The Veil wallet frontend detects new incoming transfers and generates role-aware agent notifications:

  • Trader: “You received 500 XLM — want to check rates and trade?”
  • Investor: “500 XLM landed — explore yield opportunities?”
  • Saver: “You received 500 XLM — want to see your balance?”
  • Explorer: “You got 500 XLM — want me to explain what you can do?”

These are stored in localStorage as veil_agent_notification and displayed as the first agent message when the user opens the chat. A notification badge appears on the Agent button in the dashboard.


Connecting from Your Own Frontend

If you’re building a custom frontend, connect to the agent WebSocket:

const ws = new WebSocket('wss://your-agent-backend.com')
 
ws.onopen = () => {
  ws.send(JSON.stringify({
    type: 'chat',
    walletAddress: 'C...',
    feePayerAddress: 'G...',
    message: "What's my balance?",
    profile: { name: 'Alice', role: 'trader', language: 'English' },
  }))
}
 
ws.onmessage = (event) => {
  const data = JSON.parse(event.data)
 
  if (data.type === 'thinking') {
    // Show loading indicator
  }
 
  if (data.type === 'response') {
    console.log('Agent:', data.message)
 
    if (data.pendingTxXdr) {
      // Transaction needs user approval
      // Sign with passkey and submit to Horizon
    }
  }
}

Environment Variables Reference

VariableRequiredDescription
ANTHROPIC_API_KEYYesClaude API key
AGENT_KEYPAIR_SECRETYesStellar secret for x402 payments
ORACLE_URLYesPrice oracle endpoint
WRAITH_URLYesTransfer indexer endpoint
HORIZON_URLNoHorizon endpoint (default: testnet)
SOROBAN_RPC_URLNoSoroban RPC (default: testnet)
STELLAR_NETWORKNo"testnet" or "mainnet"
CLAUDE_MODELNoModel ID (default: claude-sonnet-4-6)
AGENT_PORTNoHTTP/WS port (default: 3001)
ALLOWED_ORIGINNoCORS origin (default: *)