BoltHub logoBoltHub
Guides

Agent Wallet Security

Best practices for securing Lightning wallet credentials in AI agent deployments.

Overview

AI agents that call paid APIs need access to a Lightning wallet for automatic L402 payments. This guide covers how to scope credentials, limit spending, and secure wallet access in production deployments.

Threat model

When an agent has wallet access, the following risks apply:

ThreatImpactMitigation
Runaway spendingAgent pays large/many invoices unintentionallyBudget limits, per-request caps
Credential leakWallet secrets in env vars exposed via logs, error messages, or config filesScoped credentials, secret management
Malicious APIAn API charges more than expectedmax_cost_sats, invoice amount verification
Replay/reuseStolen L402 tokens used to access APIsL402 tokens are consumed on first use; session-based models issue a scoped session token after payment

Spending controls

Session budget

Set BUDGET_SATS to cap total spending per MCP session (session = lifetime of the MCP server process, typically one Cursor/Claude Desktop window):

{
  "mcpServers": {
    "bolthub": {
      "command": "npx",
      "args": ["@bolthub/mcp-registry"],
      "env": {
        "LND_REST_HOST": "https://your-lnd-node:8080",
        "LND_MACAROON": "<hex-pay-macaroon>",
        "BUDGET_SATS": "1000"
      }
    }
  }
}
BudgetUse case
100-500Testing and exploration
1,000-5,000Daily development
10,000+Production / heavy use

When the budget is exhausted, call_api returns an error instead of paying.

Per-request cap

Use max_cost_sats on individual call_api calls to refuse invoices above a threshold:

call_api({ slug: "expensive-api", path: "/v1/data", max_cost_sats: 50 })

The underlying L402Client also supports maxPerRequestSats as a constructor option for a global per-call limit.

Cost preview

Use preview_cost before calling to check pricing without paying:

preview_cost({ slug: "my-api", path: "/v1/endpoint" })

Wallet credential scoping

LND macaroons

If using LND (including a node from the bolthub Node Launcher), never use admin.macaroon in agent deployments. Bake a scoped macaroon with only the permissions the agent needs:

RolePermissionsUse case
Pay-onlySendPaymentSync, DecodePayReq, GetInfoAgent paying for L402 APIs
Invoice-onlyAddInvoice, LookupInvoice, GetInfoAPI provider generating invoices
Read-onlyGetInfo, balances, list operationsMonitoring / dashboards

Bake a pay-only macaroon:

lncli bakemacaroon uri:/lnrpc.Lightning/SendPaymentSync \
  uri:/lnrpc.Lightning/DecodePayReq \
  --save_to=pay-only.macaroon

This creates a macaroon that can only pay invoices and decode payment requests; it cannot create invoices, manage channels, or access funds.

For additional safety, add caveats to constrain spending:

lncli constrainmacaroon \
  --macaroon_path=pay-only.macaroon \
  --caveat="max_send_amount=1000"

For advanced setups (e.g. separating key management from payment routing), consider a watch-only + remote signer architecture where the agent machine holds no private keys. See the Lightning Agent Tools security docs for a detailed walkthrough of this pattern.

NWC (Nostr Wallet Connect)

NWC is the easiest wallet type to scope. Most NWC wallets let you create connection strings with limited permissions:

  • Alby Hub: Create a new app connection with a spending limit (e.g., 10,000 sats/day). The connection string only has pay_invoice permission.
  • CoinOS: Create an NWC connection with a daily/monthly budget cap.
  • Phoenix: NWC connections can be time-limited or budget-limited.

Recommendation: Create a dedicated NWC connection per agent/project with a daily budget that matches expected usage.

Phoenixd

Phoenixd uses a simple HTTP password. There is no credential scoping, so the password grants full access. Mitigate this by:

  1. Running a dedicated Phoenixd instance for agent payments with limited funds
  2. Setting BUDGET_SATS in the MCP config
  3. Monitoring spending via the Phoenixd HTTP API

Prefer LND with a pay-only macaroon when you are choosing a new setup.

LNbits

LNbits supports multiple wallets per instance. Create a dedicated wallet for the agent:

  1. Create a new wallet in LNbits
  2. Fund it with only the amount you're comfortable letting the agent spend
  3. Use that wallet's admin key as LNBITS_ADMIN_KEY

When the wallet runs dry, the agent can't pay. Top it up as needed.

Environment variable security

Do not commit secrets

Never commit wallet credentials to version control. Use .env files (added to .gitignore) or a secret manager.

# .gitignore
.env
.env.local
.env.*.local

Use project-scoped MCP config

For team projects, use .cursor/mcp.json with placeholder values and document the required env vars separately:

{
  "mcpServers": {
    "bolthub": {
      "command": "npx",
      "args": ["@bolthub/mcp-registry"],
      "env": {
        "NWC_URI": "${NWC_URI}",
        "BUDGET_SATS": "1000"
      }
    }
  }
}

Secret management in production

For production agent deployments:

  • Docker/K8s: Use Docker secrets or Kubernetes secrets, not env vars in compose files
  • Cloud: Use the platform's secret manager (AWS Secrets Manager, GCP Secret Manager, Fly.io secrets)
  • CI/CD: Use pipeline secrets, not hardcoded values

Monitoring

Track spending

The MCP tools report spending after each call:

Cost: 5 sats
Session spending: 45 sats | Remaining budget: 955 sats

Watch for anomalies

Set up alerts for:

  • Spending rate exceeding normal patterns
  • Budget exhaustion (the agent reports errors instead of paying)
  • Unusual API call patterns (many calls to expensive endpoints)

Wallet balance monitoring

Monitor your Lightning wallet balance. If using LND or Phoenixd, set up balance alerts:

# LND balance check
lncli walletbalance

# Phoenixd balance check (if you use Phoenixd for agent payments)
curl -u :<password> https://your-phoenixd/getbalance

Production checklist

  • Dedicated wallet/connection for agent use (not your primary wallet)
  • Scoped credentials (LND pay-only macaroon, NWC with budget, or LNbits sub-wallet)
  • BUDGET_SATS set to a reasonable session limit
  • Wallet secrets stored in a secret manager, not in code or config files
  • .env files in .gitignore
  • Monitoring for spending anomalies
  • Wallet funded with only the amount you're comfortable losing
  • Regular credential rotation (especially for long-running deployments)