Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Nostr

Moltis can receive and send encrypted direct messages over Nostr, the decentralized social protocol. The integration uses NIP-04 encrypted DMs (kind:4) and connects to relays via nostr-sdk — no public URL or server infrastructure is required.

How It Works

┌──────────────────────────────────────────────────────┐
│              Nostr Relay Network                      │
│   (relay.damus.io, nos.lol, relay.nostr.band, ...)   │
└──────────────────┬───────────────────────────────────┘
                   │  WebSocket subscription (kind:4)
                   ▼
┌──────────────────────────────────────────────────────┐
│                moltis-nostr crate                     │
│  ┌────────────┐  ┌────────────┐  ┌────────────────┐  │
│  │    Bus     │  │  Outbound  │  │     Plugin     │  │
│  │ (inbound)  │  │ (replies)  │  │  (lifecycle)   │  │
│  └────────────┘  └────────────┘  └────────────────┘  │
└──────────────────┬───────────────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────────────┐
│                 Moltis Gateway                        │
│         (chat dispatch, tools, memory)                │
└──────────────────────────────────────────────────────┘

The bot connects outward to Nostr relays via WebSocket. No port forwarding, public domain, or TLS certificate is needed. Messages are end-to-end encrypted between the sender and the bot using NIP-04.

Prerequisites

Before configuring Moltis, you need a Nostr secret key:

  1. Generate a new key pair using any Nostr client (e.g. Damus, Amethyst, or a key generation tool)
  2. Copy the secret key — either the nsec1... bech32 format or the 64-character hex format
  3. Note the corresponding public key (npub1...) to share with users who want to message the bot

Warning

The secret key is highly sensitive — it controls the bot’s Nostr identity. Never commit it to version control. Moltis stores it with secrecy::Secret and redacts it from logs, but your moltis.toml file is plain text on disk. Consider using Vault for encryption at rest.

Configuration

Add a [channels.nostr.<account-id>] section to your moltis.toml:

[channels.nostr.my-bot]
secret_key = "nsec1..."
relays = ["wss://relay.damus.io", "wss://relay.nostr.band", "wss://nos.lol"]
dm_policy = "allowlist"
allowed_pubkeys = ["npub1abc...", "npub1def..."]

Make sure "nostr" is included in channels.offered (it is by default):

[channels]
offered = ["telegram", "discord", "slack", "matrix", "nostr"]

Configuration Fields

FieldRequiredDefaultDescription
secret_keyyesNostr secret key (nsec1... bech32 or 64-char hex)
relaysno["wss://relay.damus.io", "wss://relay.nostr.band", "wss://nos.lol"]Relay WebSocket URLs to connect to
dm_policyno"allowlist"Who can DM the bot: "open", "allowlist", or "disabled"
allowed_pubkeysno[]Public keys allowed to DM (npub1... or hex, when dm_policy = "allowlist")
enablednotrueWhether this account is active
modelnoOverride the default model for this channel
model_providernoProvider for the overridden model
otp_self_approvalnotrueAllow non-allowlisted senders to self-approve via OTP code
otp_cooldown_secsno300Cooldown after 3 failed OTP attempts
profile.namenoNIP-01 profile display name
profile.display_namenoNIP-01 longer display name
profile.aboutnoNIP-01 bio / about text
profile.picturenoNIP-01 avatar URL (HTTPS)
profile.nip05noNIP-05 identifier (e.g. bot@example.com)

Full Example

[channels.nostr.my-bot]
secret_key = "nsec1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqspcgef"
relays = [
  "wss://relay.damus.io",
  "wss://relay.nostr.band",
  "wss://nos.lol",
]
dm_policy = "allowlist"
allowed_pubkeys = [
  "npub1abc123...",
]
model = "anthropic/claude-sonnet-4-20250514"
model_provider = "anthropic"
otp_self_approval = true
otp_cooldown_secs = 300

[channels.nostr.my-bot.profile]
name = "Moltis Bot"
about = "AI assistant on Nostr"
nip05 = "bot@example.com"

Access Control

DM Policy

  • allowlist (default) — Only public keys in allowed_pubkeys can message the bot. Unknown senders receive an OTP challenge if otp_self_approval is enabled, or are silently ignored.
  • open — Anyone can DM the bot.
  • disabled — All inbound DMs are ignored.

OTP Self-Approval

When otp_self_approval is enabled and a non-allowlisted sender messages the bot, the sender appears in the Senders tab of the web UI where they can be approved or denied. This works the same as OTP for Telegram and Matrix.

NIP-04 Encryption

All messages between the bot and users are encrypted using NIP-04 (kind:4 events). The bot can also decrypt inbound NIP-04 messages from any client that supports this standard.

NIP-44 and NIP-17 (gift-wrapped DMs) are planned for future releases.

Relay Health

The bot maintains persistent WebSocket connections to all configured relays. The health probe reports the number of connected relays (e.g. “2/3 relays connected”). If all relays disconnect, the bot will automatically attempt to reconnect via nostr-sdk’s built-in reconnection logic.