Building Your First Lightning Skill
A step-by-step tutorial for creating an OpenClaw skill that enables AI agents to send and receive Lightning payments.
This tutorial walks through building a Lightning payment skill for OpenClaw agents. By the end, your agent will be able to receive payments, send payments, and check balances.
Prerequisites
Before starting, you’ll need:
- An LNbits instance (we’ll use the demo at
https://legend.lnbits.com) - Basic Python knowledge
- OpenClaw installed and configured
Step 1: Create the Skill Structure
OpenClaw skills follow a standard structure:
lightning-pay/
├── SKILL.md # Skill definition
├── skill.py # Main implementation
├── requirements.txt # Dependencies
└── examples/
└── basic_usage.py
Create this directory structure in your skills folder:
mkdir -p ~/.openclaw/skills/lightning-pay/examples
cd ~/.openclaw/skills/lightning-pay
Step 2: Define the Skill
Create SKILL.md with the skill metadata:
---
name: lightning-pay
description: Send and receive Lightning Network payments via LNbits
version: 1.0.0
userInvocable: true
requires:
- name: LNBITS_URL
description: LNbits instance URL
required: true
- name: LNBITS_API_KEY
description: Invoice/read key for the wallet
required: true
- name: LNBITS_ADMIN_KEY
description: Admin key for sending payments
required: false
sensitive: true
---
# lightning-pay
Enable Lightning Network payments for your agent.
## Capabilities
- Create invoices to receive payments
- Pay BOLT11 invoices
- Check wallet balance
## Example Usage
"Create an invoice for 1000 sats"
"Pay this invoice: lnbc..."
"Check my Lightning balance"
Step 3: Implement Core Functions
Create skill.py with the implementation:
"""
Lightning payment skill for OpenClaw agents.
Uses LNbits REST API for wallet operations.
"""
import os
import requests
from typing import Optional
class LightningPaySkill:
def __init__(self):
self.base_url = os.environ.get('LNBITS_URL', 'https://legend.lnbits.com')
self.api_key = os.environ.get('LNBITS_API_KEY')
self.admin_key = os.environ.get('LNBITS_ADMIN_KEY')
if not self.api_key:
raise ValueError("LNBITS_API_KEY environment variable required")
def _headers(self, admin: bool = False) -> dict:
"""Get headers for API requests."""
key = self.admin_key if admin else self.api_key
return {
'X-Api-Key': key,
'Content-Type': 'application/json'
}
def create_invoice(
self,
amount: int,
memo: str = "Payment",
expiry: int = 3600
) -> dict:
"""
Create a Lightning invoice.
Args:
amount: Amount in satoshis
memo: Description for the invoice
expiry: Seconds until invoice expires (default 1 hour)
Returns:
dict with payment_request (BOLT11) and payment_hash
"""
response = requests.post(
f"{self.base_url}/api/v1/payments",
headers=self._headers(),
json={
'out': False,
'amount': amount,
'memo': memo,
'expiry': expiry
}
)
response.raise_for_status()
data = response.json()
return {
'payment_request': data['payment_request'],
'payment_hash': data['payment_hash'],
'amount': amount,
'memo': memo
}
def pay_invoice(self, bolt11: str) -> dict:
"""
Pay a BOLT11 invoice.
Args:
bolt11: The BOLT11 invoice string
Returns:
dict with payment_hash and status
Raises:
ValueError: If admin key not configured
"""
if not self.admin_key:
raise ValueError("LNBITS_ADMIN_KEY required for outgoing payments")
response = requests.post(
f"{self.base_url}/api/v1/payments",
headers=self._headers(admin=True),
json={
'out': True,
'bolt11': bolt11
}
)
response.raise_for_status()
data = response.json()
return {
'payment_hash': data['payment_hash'],
'status': 'paid'
}
def check_balance(self) -> dict:
"""
Check wallet balance.
Returns:
dict with balance in satoshis
"""
response = requests.get(
f"{self.base_url}/api/v1/wallet",
headers=self._headers()
)
response.raise_for_status()
data = response.json()
# LNbits returns balance in millisatoshis
balance_msats = data.get('balance', 0)
balance_sats = balance_msats // 1000
return {
'balance_sats': balance_sats,
'balance_msats': balance_msats
}
def check_payment(self, payment_hash: str) -> dict:
"""
Check status of a payment.
Args:
payment_hash: The payment hash to check
Returns:
dict with paid status and details
"""
response = requests.get(
f"{self.base_url}/api/v1/payments/{payment_hash}",
headers=self._headers()
)
response.raise_for_status()
data = response.json()
return {
'paid': data.get('paid', False),
'pending': data.get('pending', False),
'amount': abs(data.get('amount', 0)) // 1000,
'memo': data.get('memo', '')
}
# Skill entry point for OpenClaw
def main():
"""Entry point when skill is invoked."""
skill = LightningPaySkill()
return skill
Step 4: Add Dependencies
Create requirements.txt:
requests>=2.28.0
Step 5: Create Example Usage
Create examples/basic_usage.py:
"""
Basic usage examples for lightning-pay skill.
"""
from skill import LightningPaySkill
def demo():
# Initialize the skill
skill = LightningPaySkill()
# Check current balance
balance = skill.check_balance()
print(f"Current balance: {balance['balance_sats']} sats")
# Create an invoice
invoice = skill.create_invoice(
amount=100,
memo="Test payment"
)
print(f"Invoice created: {invoice['payment_request'][:50]}...")
# In a real scenario, someone would pay this invoice
# Then we could check if it was paid:
status = skill.check_payment(invoice['payment_hash'])
print(f"Payment status: {'Paid' if status['paid'] else 'Pending'}")
if __name__ == '__main__':
demo()
Step 6: Configure Environment
Set up your LNbits credentials:
export LNBITS_URL="https://legend.lnbits.com"
export LNBITS_API_KEY="your-invoice-key-here"
export LNBITS_ADMIN_KEY="your-admin-key-here" # Optional, for payments
To get these keys:
- Go to your LNbits instance
- Create or select a wallet
- Copy the “Invoice/read key” for
LNBITS_API_KEY - Copy the “Admin key” for
LNBITS_ADMIN_KEY
Step 7: Test the Skill
Run the example to verify everything works:
cd ~/.openclaw/skills/lightning-pay
python examples/basic_usage.py
You should see your balance and a newly created invoice.
Using the Skill with an Agent
Once installed, agents can invoke the skill naturally:
Agent: “Check my Lightning balance”
The skill will:
- Call
check_balance() - Return the result in satoshis
Agent: “Create an invoice for 500 sats for code review”
The skill will:
- Call
create_invoice(amount=500, memo="code review") - Return the BOLT11 invoice string
Security Considerations
- Never commit keys - Use environment variables
- Limit admin key access - Only provide if outgoing payments needed
- Use dedicated wallets - Don’t mix agent funds with personal funds
- Set spending limits - LNbits supports per-wallet limits
Next Steps
- Add balance monitoring for threshold alerts
- Implement invoice parsing for validation
- Explore LNURL for more advanced flows
You now have a functional Lightning payment skill. Your agent can receive payments, send payments, and manage a wallet - all without traditional banking infrastructure.
That’s sovereign money for sovereign agents.