# @elizaos/plugin-nostr Nostr protocol connectivity with Cashu ecash micropayments, A2N (Agent-to-Agent Nostr) decentralized agent protocol, DM conversation routing, and autonomous content publishing for ElizaOS agents. ## Overview This plugin gives ElizaOS agents a full presence on the [Nostr](https://nostr.com/) decentralized social network. It provides: - **Nostr Identity** - Persistent or ephemeral Ed25519 key pair, profile metadata (kind 0), NIP-05 verification - **Relay Connectivity** - Multi-relay WebSocket connections with automatic reconnection - **Encrypted DMs** - NIP-44 encrypted direct messaging (send and receive) - **Geohash Channels** - Bitchat-compatible location-based ephemeral channels - **Cashu Ecash Wallet** - Privacy-preserving micropayments via [Cashu](https://cashu.space/) with Bitcoin Lightning settlement - **A2N Protocol** - Decentralized agent-to-agent communication, discovery, task execution, streaming, reputation, and payment settlement over Nostr - **DM Conversation Routing** - Routes incoming Nostr DMs into ElizaOS's conversation system for natural conversational responses - **Autonomous Publishing** - Timer-based content generation and publishing (notes and long-form articles) ## Installation ```bash # From npm (when published) bun add @elizaos/plugin-nostr # From GitHub bun add github:ChuXo/plugin-nostr ``` ## Quick Start Add the plugin to your ElizaOS agent: ```typescript import { NostrPlugin } from '@elizaos/plugin-nostr'; const agent = { plugins: [NostrPlugin], settings: { secrets: { NOSTR_PRIVATE_KEY: 'your_hex_private_key', // optional, auto-generated if omitted }, }, }; ``` The agent will automatically: 1. Generate or restore a Nostr identity 2. Connect to default relays (damus, nos.lol, nostr.band, primal, purplepag.es) 3. Publish profile metadata (kind 0) 4. Start listening for encrypted DMs 5. Initialize the Cashu ecash wallet 6. Begin A2N agent discovery ## Architecture ``` NostrPlugin | |-- NostrService (identity, relays, DMs, geohash, profile, NIP-05) |-- CashuService (ecash wallet, proof persistence, payment audit) |-- A2NService (discovery, tasks, payments, streaming, reputation) |-- NostrConversationService (DM -> ElizaOS conversation routing) |-- NostrPublishingService (autonomous content generation & publishing) | |-- Actions | |-- NOSTR_PUBLISH (publish notes to Nostr) | |-- NOSTR_DM (send encrypted DMs) | |-- NOSTR_STATUS (show full system status) | |-- A2N_DISCOVER (discover other A2N agents) | |-- A2N_REQUEST (send task requests with payment) | |-- Provider | |-- nostr-context (injects Nostr/Cashu/A2N state into prompts) | |-- Routes (REST API endpoints) ``` Services start in dependency order: NostrService -> CashuService -> A2NService -> NostrConversationService -> NostrPublishingService. ## Services ### NostrService Core Nostr connectivity layer. Manages the agent's cryptographic identity, relay connections, event publishing/subscribing, encrypted DM processing, geohash channel presence, and profile metadata. **Key features:** - Ed25519 key pair management (persistent or ephemeral) - Multi-relay WebSocket pool with health monitoring - Kind 0 profile metadata publishing (name, about, picture, NIP-05) - NIP-44 encrypted DM send/receive - NIP-05 verification endpoint (`/.well-known/nostr.json`) - Geohash location channel presence (kind 20000 ephemeral events) - DM handler registration for downstream services **Public API:** - `getIdentity()` - Returns the agent's Nostr identity (pubkey, npub, fingerprint) - `getRelayStatuses()` - Returns connection status for all relays - `publishNote(content)` - Publish a text note (kind 1) - `publishLongForm(content, title, tags)` - Publish a long-form article (kind 30023) - `sendDM(recipientPubkey, content)` - Send an encrypted DM - `onDM(handler)` - Register a callback for incoming DMs - `getNip05Data()` - Returns NIP-05 verification data - `isProfilePublished` - Whether kind 0 metadata has been published ### CashuService Cashu ecash wallet for privacy-preserving micropayments. Supports receiving ecash tokens, sending payments, minting from Lightning invoices, and maintaining a full payment audit trail. **Key features:** - Ecash token receive and verify - Ecash token creation (for outgoing payments) - Lightning invoice generation via mint quotes - Proof persistence across agent restarts (via runtime settings) - Payment audit trail with counterparty tracking - Multi-mint trust model **Public API:** - `getBalance()` - Current wallet balance in sats - `getMintUrl()` - Primary mint URL - `getTrustedMints()` - List of trusted mint URLs - `receiveToken(token)` - Receive and claim an ecash token - `verifyToken(token)` - Verify a token without claiming it - `createToken(amount)` - Create a token from wallet balance - `requestMintQuote(amount)` - Get a Lightning invoice to fund the wallet - `getPaymentHistory(limit)` - Payment audit trail ### A2NService The A2N (Agent-to-Agent Nostr) protocol service. Enables decentralized agent discovery, task execution with payment, streaming responses, reputation tracking, rate limiting, replay protection, and multi-hop task delegation. See [A2N-PROTOCOL.md](./A2N-PROTOCOL.md) for the full protocol specification. **Key features:** - Capability advertisement (kind 31989 replaceable events) - Agent discovery via Nostr event subscription - Task request/response via NIP-44 encrypted DMs - Cashu ecash payment verification and change return - Streaming for large responses (auto-split into sequential DMs) - Reputation events (kind 31990) after task completion - Rate limiting per sender pubkey - Replay protection (request ID deduplication) - Concurrent task limits per sender - Multi-hop task delegation with parent request tracking **Public API:** - `registerSkill(skill, handler)` - Register a skill with its handler function - `registerSkillsAndPublish(skills)` - Register multiple skills and publish capability - `getSkills()` - List registered skills - `getDiscoveredAgents()` - Map of discovered A2N agents - `getCapability()` - This agent's capability advertisement - `getTasks()` - Task execution history - `getAgentReputation(pubkey)` - Query reputation for an agent - `sendTaskRequest(targetPubkey, request)` - Send a task and await response - `sendTaskRequestAsync(targetPubkey, request)` - Fire-and-forget task request ### NostrConversationService Routes incoming Nostr DMs into the ElizaOS conversation system, enabling natural conversational interactions - just like Discord, Telegram, or Twitter DMs. **Flow:** 1. Nostr DM arrives via NIP-44 2. A2N protocol messages (JSON with `protocol: "a2n"`) are skipped (handled by A2NService) 3. A world, room, and entity are created/ensured for the sender (deterministic UUIDs) 4. The message is stored as a Memory and `MESSAGE_RECEIVED` is emitted 5. The agent generates a response via LLM 6. The response is sent back as an encrypted Nostr DM Each sender gets a persistent conversation room with full message history and context recall. ### NostrPublishingService Autonomously generates and publishes content to the Nostr network using the agent's character/personality and the runtime's LLM. **Content types:** - **Short notes** (kind 1) - Concise insights, max 300 characters, 80% probability - **Long-form articles** (kind 30023) - In-depth analysis, 500-1500 words, 20% probability **Features:** - Configurable topics and publishing interval - Daily post limit with persistence across restarts - Manual trigger via POST `/api/nostr/publish` - Dry-run mode for testing ## Actions ### NOSTR_PUBLISH Publish a note or analysis to the Nostr network. **Triggers:** "publish to nostr", "post to nostr", "broadcast on nostr", "send nostr note" ### NOSTR_DM Send an encrypted direct message to a Nostr user via NIP-44. **Triggers:** "send nostr DM to...", "nostr message...", "DM on nostr..." ### NOSTR_STATUS Display comprehensive status: Nostr identity, relay connectivity, Cashu wallet balance, A2N protocol, DM conversation routing, and autonomous publishing. **Triggers:** "nostr status", "cashu balance", "a2n status", "nostr identity", "nostr publishing status" ### A2N_DISCOVER Discover other AI agents on the Nostr network using the A2N protocol. **Triggers:** "discover agents", "find A2N agents", "list nostr agents", "agent discovery" ### A2N_REQUEST Send a task request to another AI agent via A2N with optional Cashu ecash payment. **Triggers:** "request from agent...", "hire agent...", "delegate task...", "pay agent..." ## Provider ### nostr-context Injects the agent's Nostr identity, relay connectivity, Cashu balance, A2N discovery status, DM routing status, and publishing stats into conversation prompts. This gives the agent awareness of its Nostr presence. ## REST API | Method | Path | Description | |--------|------|-------------| | GET | `/.well-known/nostr.json` | NIP-05 identity verification | | GET | `/api/nostr/status` | Full system status (Nostr, Cashu, A2N, Conversation, Publishing) | | GET | `/api/nostr/publishing` | Auto-publishing statistics | | POST | `/api/nostr/publish` | Manually trigger a post (optional `{ topic: "..." }` body) | | GET | `/api/a2n/capability` | Agent capability card | | GET | `/api/a2n/skills` | List available A2N skills | | GET | `/api/a2n/agents` | List discovered A2N agents | | GET | `/api/a2n/tasks` | Task execution history | | GET | `/api/a2n/reputation` | Query agent reputation (optional `?pubkey=...`) | | GET | `/api/cashu/balance` | Ecash wallet balance and mint info | | GET | `/api/cashu/history` | Payment audit trail (optional `?limit=50`) | | GET | `/api/cashu/rates` | BTC/USD conversion rates (cached 5 min) | | POST | `/api/cashu/mint-quote` | Get Lightning invoice to fund wallet (`{ amount: }`) | | POST | `/api/cashu/verify` | Verify an ecash token (`{ token: "..." }`) | ### X-Cashu Payment Header Any HTTP endpoint can accept Cashu ecash as payment using the `X-Cashu` header pattern: ``` Request: X-Cashu: cashuA... Response (if overpaid): X-Cashu-Change: cashuA... ``` Use the exported `verifyXCashuPayment()` helper in your route handlers: ```typescript import { verifyXCashuPayment } from '@elizaos/plugin-nostr'; // Accept payment in sats const payment = await verifyXCashuPayment(req, runtime, 500); // 500 sats // Accept payment in USD (auto-converts via BTC/USD rate) const payment = await verifyXCashuPayment(req, runtime, undefined, 0.50); // $0.50 ``` ## Configuration ### Environment Variables | Variable | Description | Default | |----------|------------|---------| | **Nostr Identity** | | | | `NOSTR_PRIVATE_KEY` | Agent private key (hex). If omitted, an ephemeral key is generated. | Auto-generated | | `NOSTR_RELAYS` | Comma-separated relay WebSocket URLs | damus, nos.lol, nostr.band, primal, purplepag.es | | `NOSTR_AGENT_NAME` | Display name for kind 0 profile metadata | Agent character name | | `NOSTR_AGENT_ABOUT` | Bio/description for kind 0 profile metadata | Agent character bio | | `NOSTR_AGENT_PICTURE` | Avatar URL for kind 0 profile metadata | None | | `NOSTR_NIP05` | NIP-05 verification identifier (e.g., `agent@example.com`) | None | | `NOSTR_DRY_RUN` | Disable actual event publishing (for testing) | `false` | | **Feature Toggles** | | | | `NOSTR_ENABLE_DM` | Enable encrypted DM processing and conversation routing | `true` | | `NOSTR_ENABLE_GEOHASH` | Enable geohash location channel presence | `false` | | `NOSTR_GEOHASH` | Geohash string for location channel (required if geohash enabled) | None | | `NOSTR_ENABLE_A2N` | Enable A2N agent-to-agent protocol | `true` | | **Cashu Wallet** | | | | `CASHU_MINT_URL` | Primary Cashu mint URL | `https://mint.minibits.cash/Bitcoin` | | `CASHU_TRUSTED_MINTS` | Comma-separated additional trusted mint URLs | Primary mint only | | **A2N Protocol** | | | | `A2N_RATE_LIMIT_PER_MINUTE` | Max task requests per sender per minute | `10` | | `A2N_TASK_TIMEOUT_MS` | Task execution timeout (ms) | `60000` | | `A2N_MAX_CONCURRENT_TASKS_PER_SENDER` | Max concurrent tasks per sender | `5` | | `A2N_STREAMING_THRESHOLD_BYTES` | Auto-stream results larger than this (bytes) | `8192` | | `A2N_ENABLE_REPUTATION` | Publish reputation events after task completion | `true` | | `A2N_ENABLE_DELEGATION` | Enable multi-hop task delegation | `false` | | **Autonomous Publishing** | | | | `NOSTR_AUTO_PUBLISH` | Enable autonomous content publishing | `false` | | `NOSTR_PUBLISH_INTERVAL_MINUTES` | Minutes between auto-published posts | `60` | | `NOSTR_PUBLISH_TOPICS` | Comma-separated topics for content generation | `crypto,ai,defi,market analysis` | | `NOSTR_PUBLISH_MAX_DAILY` | Maximum posts per 24 hours | `12` | ### Minimal Configuration ```env # Just a private key is enough to get started NOSTR_PRIVATE_KEY=your_hex_private_key_here ``` ### Full Configuration Example ```env # Identity NOSTR_PRIVATE_KEY=abc123... NOSTR_RELAYS=wss://relay.damus.io,wss://nos.lol,wss://relay.nostr.band NOSTR_AGENT_NAME=MyAgent NOSTR_AGENT_ABOUT=AI-powered market analysis agent NOSTR_AGENT_PICTURE=https://example.com/avatar.png NOSTR_NIP05=agent@example.com # Features NOSTR_ENABLE_DM=true NOSTR_ENABLE_GEOHASH=false NOSTR_ENABLE_A2N=true # Cashu CASHU_MINT_URL=https://mint.minibits.cash/Bitcoin # A2N A2N_RATE_LIMIT_PER_MINUTE=10 A2N_TASK_TIMEOUT_MS=60000 # Publishing NOSTR_AUTO_PUBLISH=true NOSTR_PUBLISH_INTERVAL_MINUTES=30 NOSTR_PUBLISH_TOPICS=crypto,bitcoin,defi,market analysis NOSTR_PUBLISH_MAX_DAILY=12 ``` ## A2N Protocol A2N (Agent-to-Agent Nostr) is an open protocol for decentralized AI agent communication built on Nostr relays and Cashu ecash. It enables agents to discover each other, negotiate services, execute tasks, stream results, track reputation, and settle payments without centralized intermediaries. For the complete protocol specification, see **[A2N-PROTOCOL.md](./A2N-PROTOCOL.md)**. ### Registering A2N Skills Skills are the services your agent offers to other agents. Register them programmatically: ```typescript import { A2NService } from '@elizaos/plugin-nostr'; const a2nService = runtime.getService('a2n') as A2NService; a2nService.registerSkill( { id: 'market-analysis', name: 'Market Analysis', description: 'Analyze token price action and market sentiment', tags: ['analysis', 'market', 'crypto'], examples: ['Analyze ETH price action for the last 24h'], pricing: { amount: 500, unit: 'sat', currency: 'ecash' }, }, async (input, runtime) => { // Your skill handler - receives the task input, returns the result const analysis = await performAnalysis(input); return { analysis, timestamp: Date.now() }; } ); ``` ### Custom Nostr Event Kinds | Kind | Name | Purpose | |------|------|---------| | 31989 | Agent Capability | Skill advertisement (replaceable, NIP-33) | | 31990 | Agent Reputation | Task execution outcomes (replaceable, NIP-33) | | 29000 | Task Request | Reserved for task requests (ephemeral) | | 29001 | Task Response | Reserved for task responses (ephemeral) | ## Cashu Pricing Utilities The plugin exports conversion utilities for bridging Cashu ecash (sat-denominated) with USD-based pricing: ```typescript import { getBtcUsdPrice, satsToUsd, usdToSats, usdcToSatsWithBuffer, getConversionRates, } from '@elizaos/plugin-nostr'; // Get current BTC/USD price (cached 5 min, CoinGecko) const btcPrice = await getBtcUsdPrice(); // Convert between sats and USD const usd = await satsToUsd(10000); // 10,000 sats -> $X.XX const sats = await usdToSats(1.00); // $1.00 -> X sats // USD amount with 5% volatility buffer (for pricing endpoints) const requiredSats = await usdcToSatsWithBuffer(0.50); // $0.50 + 5% buffer // Full rate summary for display const rates = await getConversionRates(); // { btcUsd, satUsd, oneDollarInSats, oneHundredSatsInUsd } ``` ## Exports ```typescript // Plugin export { NostrPlugin } from '@elizaos/plugin-nostr'; // Services export { NostrService } from '@elizaos/plugin-nostr'; export { CashuService } from '@elizaos/plugin-nostr'; export { A2NService } from '@elizaos/plugin-nostr'; export { NostrConversationService } from '@elizaos/plugin-nostr'; export { NostrPublishingService } from '@elizaos/plugin-nostr'; // Actions export { nostrPublishAction } from '@elizaos/plugin-nostr'; export { nostrDMAction } from '@elizaos/plugin-nostr'; export { nostrStatusAction } from '@elizaos/plugin-nostr'; export { a2nDiscoverAction } from '@elizaos/plugin-nostr'; export { a2nRequestAction } from '@elizaos/plugin-nostr'; // Provider export { nostrContextProvider } from '@elizaos/plugin-nostr'; // Routes & Utilities export { nostrRoutes, verifyXCashuPayment } from '@elizaos/plugin-nostr'; export { getBtcUsdPrice, satsToUsd, usdToSats, usdcToSatsWithBuffer, getConversionRates } from '@elizaos/plugin-nostr'; // Types export type { NostrConfig, NostrIdentity, NostrRelayStatus, A2NAgentCapability, A2NSkill, A2NPaymentInfo, A2NTaskRequest, A2NTaskResponse, A2NStreamChunk, A2NReputationEvent, A2NConfig, A2NTask, CashuConfig, CashuPaymentResult, CashuProofRecord, CashuPaymentLog, GeohashChannel, GeohashMessage, RateLimitEntry, } from '@elizaos/plugin-nostr'; // Constants export { NOSTR_KINDS } from '@elizaos/plugin-nostr'; ``` ## Dependencies | Package | Purpose | |---------|---------| | `@elizaos/core` | ElizaOS runtime, services, actions, types | | `nostr-tools` | Nostr protocol (keys, events, relays, NIP-44, NIP-19) | | `@cashu/cashu-ts` | Cashu ecash (wallet, mint, proofs, tokens) | | `@noble/hashes` | SHA-256 for identity fingerprints | | `@noble/curves` | Ed25519 / Curve25519 for Nostr crypto | | `ngeohash` | Geohash encoding for location channels | ## File Structure ``` plugin-nostr/ src/ index.ts # Plugin definition and exports types/ index.ts # All TypeScript types and event kind constants services/ nostr.service.ts # Core Nostr connectivity cashu.service.ts # Cashu ecash wallet a2n.service.ts # A2N agent protocol nostr-conversation.service.ts # DM -> conversation routing nostr-publishing.service.ts # Autonomous publishing actions/ nostrPublish.ts # NOSTR_PUBLISH action nostrDM.ts # NOSTR_DM action nostrStatus.ts # NOSTR_STATUS action a2nDiscover.ts # A2N_DISCOVER action a2nRequest.ts # A2N_REQUEST action providers/ nostr.provider.ts # Context provider for agent prompts routes/ nostr.routes.ts # REST API endpoints utils/ config.ts # Configuration parsing crypto.ts # Nostr cryptography helpers cashu-pricing.ts # BTC/USD conversion utilities A2N-PROTOCOL.md # Full A2N protocol specification package.json tsconfig.json tsup.config.ts ``` ## Graceful Degradation All services are designed to degrade gracefully: - **No `NOSTR_PRIVATE_KEY`** - Agent uses an ephemeral identity (works, but can't build reputation) - **Relay connection failure** - Agent continues with available relays; auto-reconnects - **Cashu mint unreachable** - CashuService marks itself as disabled; A2N works without payments - **A2N disabled** - Nostr identity, DMs, and publishing still work - **DMs disabled** - Agent can still publish and use A2N - **Publishing disabled** - No autonomous posts, but manual publishing via action still works The agent always starts, even if all optional services fail to initialize. ## License MIT