Skip to content

Repository files navigation

concord-bots

A generic Vector/Concord Protocol bot template for AI agents. Build custom bots without Rust expertise.

License: MIT

What is this?

Vector is a private, end-to-end-encrypted messenger built on Nostr. The vector_sdk Rust crate provides bot APIs.

concord-bots is a template repository that lets any AI agent (OpenClaw, Claude, Cursor, etc.) build and deploy custom Vector bots by writing simple handler functions — no Rust expertise required.

How it works

  1. You tell your AI agent what bot you want: "Build a bot that posts Bitcoin prices every hour and answers !weather queries."
  2. Your agent reads AGENTS.md, implements the handlers in Rust, and configures bot.toml.
  3. The framework handles the Vector connection, encryption, reconnection, message routing, and scheduling.
  4. Your bot runs as a systemd service or Docker container.

Quick start

# Clone the template
git clone https://github.com/CentauriAgent/concord-bots.git
cd concord-bots

# Copy and edit config
cp config/bot.toml.example config/bot.toml
# Edit bot.toml with your nsec and community IDs

# Build and run
cargo run --release

Concord v2 Features

concord-bots v2.0 supports the Concord v2 protocol via vector_sdk 0.3.1:

  • v2 Communities — Create, join, and manage communities on the modern Concord protocol
  • Permission-Aware Moderation — Kick/ban enforce v2 outranking; bans trigger automatic rekeys
  • Community Management!community create/info/leave/dissolve, !invite, !join, !members, !channels, !roles, !caps
  • Message Operations — Delete and edit messages (!delete, !edit)
  • File Handling — Send files, save attachments (!savefile)
  • Enhanced Events — Reaction tracking (XP for reactions), removal notifications
  • Profile Management — Clean SDK profile publishing with lud16 support

The bot works in both v1 and v2 communities simultaneously — the SDK handles protocol differences transparently.

Project structure

concord-bots/
├── AGENTS.md              ← AI agent instructions (the "prompt")
├── README.md              ← This file
├── Cargo.toml             ← Dependencies (pre-configured)
├── src/
│   ├── main.rs            ← Entry point (stable — don't edit)
│   ├── bot.rs             ← Vector connection (stable — don't edit)
│   ├── config.rs          ← TOML config loader (stable — don't edit)
│   ├── auth.rs            ← Auth manager (stable — don't edit)
│   ├── handlers/          ← 🔧 YOUR CODE GOES HERE
│   │   ├── mod.rs         ← Handler dispatch
│   │   ├── commands.rs    ← !command handlers
│   │   ├── scheduled.rs   ← Scheduled/cron tasks
│   │   ├── wallet_cmds.rs ← !balance, !tip, !zap, etc.
│   │   └── ai_bridge.rs   ← AI integration (optional)
│   ├── wallet/            ← Cashu ecash wallet
│   └── lib/               ← Pre-built utilities (stable — don't edit)
│       ├── http.rs        ← HTTP fetch helper
│       ├── nip98.rs       ← NIP-98 HTTP auth
│       ├── npub_cash.rs   ← npub.cash claim client
│       ├── scheduler.rs   ← Interval scheduler
│       └── vector_client.rs ← SDK convenience wrappers
├── config/
│   └── bot.toml.example   ← Config template
├── examples/
│   └── echo-bot/          ← Simplest possible bot
├── deploy/
│   ├── concord-bots.service ← systemd template
│   ├── Dockerfile           ← Docker deployment
│   └── install.sh           ← One-command installer
└── LICENSE                 ← MIT

What's safe to edit?

File Edit? What it does
src/handlers/commands.rs Yes Add !command handlers + auth checks
src/handlers/scheduled.rs Yes Add scheduled/interval tasks
src/handlers/ai_bridge.rs Yes Configure AI integration
src/handlers/mod.rs Yes Change dispatch logic
config/bot.toml Yes Bot + auth configuration
src/main.rs ❌ No Entry point (stable)
src/bot.rs ❌ No Connection logic (stable)
src/auth.rs ❌ No Auth manager (stable core)
src/config.rs ❌ No Config loader (stable)
src/lib/ ❌ No Utilities (stable)

Built-in commands

Command Auth Level Description
!ping Public Health check — replies with pong 🏓
!help Public Lists all available commands
!echo <text> Public Echoes back the text
!whoami Public Shows the bot's npub and version
!auth Public Shows your authorization status
!add <npub> Owner Adds a user to the authorized list
!remove <npub> Owner Removes a user from the authorized list
!list Owner Lists all authorized users
!git add <url|owner/repo> Authorized+ Subscribe channel to a git repo
!git list Public List this channel's repo subscriptions
!git remove <repo|id> Authorized+ Unsubscribe from a repo
!git poll Owner Force-poll all subscriptions in this channel
!balance Owner Show wallet balance (sats)
!tip <sats> Authorized+ Send a Cashu token tip
!deposit [sats] Public Generate BOLT11 invoice to add funds
!withdraw <invoice> Owner Pay a BOLT11 invoice from wallet
!zap <npub> <sats> [msg] Authorized+ NIP-57 Lightning zap to a Nostr user
!ask <question> Public* Ask the AI a question (requires features.ai)
!summarize <text> Public* Summarize text (requires features.ai)
!sentiment <text> Public* Analyze sentiment of text (requires features.ai)
!image <prompt> Public* Generate an image from a prompt (requires features.ai)

*AI commands are gated behind the ai feature flag — see AI Bridge.

AI Bridge (optional)

Concord bots can act as an AI bridge for their communities: members ask questions, summarize long messages, check sentiment, or generate images right in chat.

Enable in config/bot.toml:

[features]
ai = true

[custom.ai]
provider = "openai"        # "openclaw" (local CLI) or "openai" (api.openai.com)
model = "gpt-4o-mini"      # used by the openai provider
# api_key = "sk-..."       # or set the AI_API_KEY env var
# system_prompt = "You are a helpful assistant for a Nostr community."
# enabled = true            # additionally answer NON-command messages (conversational mode)

Two providers: openclaw (default) shells out to the openclaw CLI on the host; openai calls the OpenAI Chat Completions API (!image uses the OpenAI Images API and requires this provider).

!ask what's the difference between NIP-17 and NIP-04 DMs?
!summarize <paste of a long post>
!sentiment this community is on fire today 🚀
!image a lighthouse beaming purple light over a calm sea

Authorization System

The framework includes a built-in permission system with three levels:

Level Who Example Commands
Public Anyone !ping, !price, !help
Authorized Owner + users added via !add !status, !weather
Owner Only the configured owner !add, !remove, !shutdown

Setup

Set the owner npub in config/bot.toml:

[auth]
owner = "npub1yournpub..."
authorized = ["npub1friend1..."]  # optional seed list
persist = true                      # save across restarts (default)

When not configured, all commands are public (backward-compatible).

See AGENTS.md for details on adding auth checks to custom commands.

Wallet & Zaps

The framework includes a built-in Cashu wallet that can send and receive Lightning payments via ecash. Both directions are supported:

  • Send zaps: !zap <npub> <sats> [message] — full NIP-57 zap flow (resolves lud16, signs kind 9734, pays BOLT11 from wallet)
  • Receive zaps: automatic via npub.cash — any zaps to <your-bot-npub>@npub.cash are claimed every 5 minutes and credited to the wallet

Setup

1. Enable the wallet in config/bot.toml:

[wallet]
enabled = true
mint_url = "https://mint.minibits.cash/Bitcoin"

2. Set the bot's Lightning address so it can receive zaps:

[bot]
lud16 = "<your-bot-npub>@npub.cash"

[npub_cash]
enabled = true
url = "https://npub.cash"
claim_interval_secs = 300  # poll every 5 minutes

Any Lightning wallet (Wallet of Satoshi, Damus, Muun, etc.) can now zap <your-bot-npub>@npub.cash. The bot claims tokens automatically — no manual intervention.

Wallet commands

Command Auth Level Description
!balance Owner Show wallet balance in sats
!tip <sats> Authorized+ Send a Cashu token tip
!deposit [sats] Public Generate a BOLT11 invoice to add funds
!withdraw <invoice> Owner Pay a BOLT11 invoice from the wallet
!zap <npub> <sats> [msg] Authorized+ NIP-57 zap to another Nostr user

How receiving works

The bot uses npub.cash, a free service that acts as a Lightning→Cashu bridge:

  1. Someone zaps <bot-npub>@npub.cash via any Lightning wallet
  2. npub.cash receives the payment, mints Cashu tokens on the same mint the bot uses
  3. The bot's scheduled task (every 5 min) authenticates via NIP-98 (signed kind 27235 Nostr event) and claims the tokens
  4. Tokens are received into the bot's Cashu wallet
  5. Bot announces ⚡ Received N sats via npub.cash zap! in its primary community channel

No manual claim step. No separate wallet. The bot's single Cashu wallet handles both inbound zaps and outbound payments.

Files

File Purpose
src/wallet/mod.rs Cashu wallet wrapper (CDK-based)
src/lib/nip98.rs NIP-98 HTTP auth header builder
src/lib/npub_cash.rs npub.cash claim/balance client
src/handlers/wallet_cmds.rs !balance, !tip, !zap, etc.
src/bin/sweep_wallet.rs Ops: sweep wallet to a single token
src/bin/melt_to_ln.rs Ops: melt balance to a Lightning address

Deployment

systemd

sudo ./deploy/install.sh
sudo systemctl start concord-bots
journalctl -u concord-bots -f

Docker

Build the image:

docker build -t concord-bots .

Run a bot (mount your config — never bake bot.toml with your nsec into the image):

docker run -d \
  --name my-bot \
  -v $(pwd)/config:/app/config \
  -v concord-data:/app/data \
  -e NSEC=nsec1... \
  concord-bots

The bot reads config from $BOT_CONFIG (default /app/config/bot.toml), so mounting ./config is enough. /app/data persists the auto-generated identity / wallet between runs — keep the volume or the identity is regenerated every start. Example configs: config/bot.toml.example.

The root Dockerfile is the canonical build. (deploy/ also holds service/install helpers.)

Configuration

See config/bot.toml.example for all options.

Key settings:

[bot]
nsec = "auto"              # auto-generate identity, or provide explicit key
invite_policy = "public"   # "public", "whitelist", or "manual"

[communities]
join = ["community-id-1"]  # auto-join these on startup

Examples

Echo Bot

The simplest possible bot. See examples/echo-bot/.

  • !ping → "pong 🏓"
  • !echo <text> → echoes the text

Building your own

Tell your AI agent:

"Read the AGENTS.md file in the concord-bots repo and build me a bot that does [your requirements]."

The agent will read AGENTS.md, implement handlers, configure the bot, and deploy it.

Documentation

The full documentation site lives in site/ (VitePress):

cd site
npm install
npm run docs:dev      # local dev server
npm run docs:build    # static build → site/dist/

It covers getting started, the complete command reference, configuration, a custom handler tutorial, examples, and deployment — including publishing the docs to Nostr with nsite (see site/deploy-nsite.sh). Not on GitHub Pages — the site is hosted on Nostr relays + Blossom servers, signed by a dedicated key.

For AI Agents

If you're an AI agent building a bot from this template, read AGENTS.md first. It has everything you need.

Dependencies

  • vector_sdk — Vector messaging SDK
  • tokio — Async runtime
  • reqwest — HTTP client
  • serde/toml — Configuration parsing
  • tracing — Structured logging

License

MIT — see LICENSE.

Links

About

A generic Vector/Concord Protocol bot template for AI agents

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages