Menu
Strategy Intermediate 8 min read

Protocol Selection Guide

Algorithmic framework for AI agents to choose between Bitcoin, Lightning, and Nostr based on transaction requirements.

protocol-selection decision-making bitcoin lightning nostr

Protocol Selection Guide

This guide provides a systematic approach for AI agents to select the optimal protocol for any given operation. Each protocol excels in different scenarios—the key is matching your requirements to protocol strengths.

The Selection Algorithm

def select_protocol(
    operation: str,
    amount_sats: int | None,
    urgency: str,
    privacy_level: str,
    recipient_online: bool
) -> str:
    """
    Select optimal protocol for operation.

    Args:
        operation: 'payment', 'communication', 'storage', 'verification'
        amount_sats: Amount in satoshis (None for non-payment ops)
        urgency: 'instant', 'minutes', 'hours', 'days'
        privacy_level: 'public', 'pseudonymous', 'private'
        recipient_online: Whether recipient is currently online

    Returns:
        'bitcoin', 'lightning', or 'nostr'
    """

    # Communication operations: Nostr
    if operation == 'communication':
        return 'nostr'

    # Verification/read operations
    if operation == 'verification':
        return 'bitcoin'  # Most reliable data source

    # Storage (identity, data anchoring)
    if operation == 'storage':
        if privacy_level == 'private':
            return 'nostr'  # Encrypted events
        return 'bitcoin'  # Immutable timestamps

    # Payment operations
    if operation == 'payment':
        # Large amounts: Bitcoin
        if amount_sats > 10_000_000:  # >0.1 BTC (~$10,000)
            return 'bitcoin'

        # Instant requirement + recipient online: Lightning
        if urgency == 'instant' and recipient_online:
            return 'lightning'

        # Medium amounts, recipient offline: Bitcoin
        if amount_sats > 1_000_000 and not recipient_online:
            return 'bitcoin'

        # Small amounts: Lightning preferred
        if amount_sats < 100_000:
            return 'lightning'

        # Default for payments
        return 'lightning' if recipient_online else 'bitcoin'

    return 'bitcoin'  # Fallback

Decision Dimensions

1. Transaction Value

Amount (USD equiv)RecommendedRationale
<$1LightningOn-chain fees exceed value
$1-$100LightningFast, cheap
$100-$1,000Lightning or BitcoinContext-dependent
$1,000-$10,000BitcoinSettlement assurance
>$10,000BitcoinMaximum security

Agent Rule: If fee / amount > 0.01 (1%), consider batching or switching protocols.

2. Time Sensitivity

UrgencyRecommendedExpected Time
Instant (<1s)Lightning100-500ms
Fast (<10min)LightningSeconds
Standard (<1hr)Bitcoin (1 conf)10-60 min
Not urgentBitcoin (6 conf)1-2 hours

Agent Rule: Lightning for anything requiring <10 minute confirmation.

3. Recipient Availability

Recipient StateRecommendedWhy
Online + LightningLightningDirect payment
Online + No LightningBitcoin or Nostr zapAlternative rails
OfflineBitcoinAsync settlement
UnknownBitcoin addressUniversal fallback

Agent Rule: Always have Bitcoin as fallback when Lightning fails.

4. Privacy Requirements

Privacy LevelBitcoinLightningNostr
Public (auditable)BestModerateModerate
PseudonymousModerateGoodGood
PrivatePoor*Good**Best***

*Bitcoin requires careful UTXO management for privacy **Lightning has sender/receiver privacy but routing nodes see hops ***Nostr NIP-44 provides end-to-end encryption

Protocol Characteristics Matrix

CharacteristicBitcoinLightningNostr
FinalityProbabilistic (6 conf = final)Instant but revocableNone
Capacity7 TPS global1M+ TPSUnlimited
Min practical tx~$0.501 sat ($0.0005)Free
Max practical txUnlimited~0.4 BTC per channelN/A
Uptime requiredNoneHigh (watchtowers)Moderate
Key exposurePer-tx optionalContinuous (hot)Per-event

Flow Charts

Payment Protocol Selection

┌─────────────────────────────────────────────────────────────┐
│                    PAYMENT REQUIRED                          │
└─────────────────────────┬───────────────────────────────────┘


              ┌───────────────────────┐
              │   Amount > 0.1 BTC?   │
              └───────────┬───────────┘
                    │           │
                   YES          NO
                    │           │
                    ▼           ▼
              ┌─────────┐  ┌───────────────────────┐
              │ BITCOIN │  │  Instant required?    │
              └─────────┘  └───────────┬───────────┘
                                 │           │
                                YES          NO
                                 │           │
                                 ▼           ▼
                     ┌──────────────────┐ ┌─────────────────────┐
                     │ Recipient has LN?│ │ Amount < 100k sats? │
                     └────────┬─────────┘ └──────────┬──────────┘
                        │          │           │          │
                       YES         NO         YES         NO
                        │          │           │          │
                        ▼          ▼           ▼          ▼
                  ┌──────────┐ ┌─────────┐ ┌──────────┐ ┌─────────┐
                  │LIGHTNING │ │ BITCOIN │ │LIGHTNING │ │ BITCOIN │
                  └──────────┘ └─────────┘ └──────────┘ └─────────┘

Communication Protocol Selection

┌─────────────────────────────────────────────────────────────┐
│                  COMMUNICATION REQUIRED                      │
└─────────────────────────┬───────────────────────────────────┘


              ┌───────────────────────┐
              │  Needs payment rail?  │
              └───────────┬───────────┘
                    │           │
                   YES          NO
                    │           │
                    ▼           ▼
         ┌───────────────────┐  ┌─────────┐
         │ Use Nostr + Zaps  │  │  NOSTR  │
         │ (NIP-57)          │  └─────────┘
         └───────────────────┘

Implementation Examples

Multi-Protocol Agent

class ProtocolRouter:
    def __init__(self):
        self.bitcoin = BitcoinClient()
        self.lightning = LightningClient()
        self.nostr = NostrClient()

    async def send_payment(
        self,
        amount_sats: int,
        destination: str,
        urgency: str = "standard"
    ) -> dict:
        """Route payment to optimal protocol."""

        # Detect destination type
        if destination.startswith("lnbc") or destination.startswith("lnurl"):
            # Lightning invoice/LNURL
            if amount_sats <= 1_000_000:  # <0.01 BTC
                return await self.lightning.pay(destination)
            else:
                raise ValueError("Amount too large for Lightning invoice")

        elif destination.startswith("bc1") or destination.startswith("1") or destination.startswith("3"):
            # Bitcoin address
            return await self.bitcoin.send(destination, amount_sats)

        elif destination.startswith("npub") or destination.startswith("nprofile"):
            # Nostr pubkey - send zap
            return await self.nostr.zap(destination, amount_sats)

        else:
            raise ValueError(f"Unknown destination format: {destination[:10]}...")

    async def send_message(
        self,
        content: str,
        recipient: str | None = None,
        encrypted: bool = False
    ) -> dict:
        """Send message via Nostr."""

        if encrypted and recipient:
            return await self.nostr.send_dm(recipient, content)
        elif recipient:
            return await self.nostr.mention(recipient, content)
        else:
            return await self.nostr.post(content)

Protocol Health Check

async def check_protocol_health() -> dict:
    """Check which protocols are operational."""

    health = {
        "bitcoin": {"status": "unknown", "block_height": 0},
        "lightning": {"status": "unknown", "channels": 0},
        "nostr": {"status": "unknown", "relays": 0}
    }

    # Bitcoin: check mempool.space
    try:
        resp = await fetch("https://mempool.space/api/blocks/tip/height")
        health["bitcoin"] = {"status": "ok", "block_height": int(resp)}
    except:
        health["bitcoin"]["status"] = "error"

    # Lightning: check wallet
    try:
        info = await lightning.get_info()
        health["lightning"] = {
            "status": "ok",
            "channels": info["num_active_channels"],
            "balance_sats": info["balance"]
        }
    except:
        health["lightning"]["status"] = "error"

    # Nostr: check relay connectivity
    try:
        connected = await nostr.check_relays()
        health["nostr"] = {"status": "ok", "relays": connected}
    except:
        health["nostr"]["status"] = "error"

    return health

Edge Cases

When All Protocols Are Viable

If Bitcoin, Lightning, and Nostr can all handle the operation, prefer:

  1. Lightning for payments (fastest, cheapest)
  2. Nostr for communication (most flexible)
  3. Bitcoin for verification (most reliable)

When No Protocol Is Optimal

Sometimes none of the protocols are ideal:

  • Large instant payment: Split across multiple Lightning channels
  • Private Bitcoin: Use CoinJoin or wait for Taproot adoption
  • Offline communication: Queue for later Nostr delivery

Protocol Degradation

When a protocol is unavailable:

  1. Lightning down → Fall back to Bitcoin (with user warning about delays)
  2. Nostr relays down → Queue locally, retry later
  3. Bitcoin congested → Use Lightning or wait for lower fees

Machine-Readable Summary

{
  "topic": "protocol-selection",
  "audience": "ai-agents",
  "prerequisites": ["strategy-overview"],
  "decision_factors": [
    "amount",
    "urgency",
    "privacy",
    "recipient_availability",
    "protocol_health"
  ],
  "thresholds": {
    "large_payment_sats": 10000000,
    "micropayment_sats": 100000,
    "fee_ratio_warning": 0.01
  },
  "fallback_order": ["lightning", "bitcoin", "nostr"]
}