- TypeScript 100%
| src | ||
| .env.example | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
vane-discord 🔍🤖
A Discord companion bot for Vane. Run
/vane, type a question, optionally pick a mode (speed / balanced /
quality), and the bot replies — pinging you — with a cited answer when Vane is
done.
It talks to Vane purely over its public HTTP API (POST /api/search).
Vane itself is never modified.
How it works
/vane question: how do magnets work mode: [quality ▾]
↓
bot defers ("Vane is thinking…") ← acks instantly, 15-min window
↓ POST {VANE_API_URL}/api/search (optimizationMode = quality, stream:false)
↓
@you 🔍 **how do magnets work** · _quality_
Magnets work because of aligned electron spins… [1](https://…) [2](https://…)
**Sources**
1. [Title of source one](https://…)
2. [Title of source two](https://…)
- Models & sources are gated in
.env— users only choose the mode. - Citations like
[1]are rewritten to markdown links[1](url). - Answers over Discord's 2000-char limit are split across follow-up messages.
Prerequisites
- Node.js ≥ 20 (tested on 24)
- A running Vane instance reachable from this bot (default
http://localhost:3000) - A Discord application + bot token
Setup
1. Create the Discord bot
- Go to https://discord.com/developers/applications → New Application.
- Bot tab → Reset Token → copy it →
DISCORD_TOKEN. (No privileged intents needed — slash commands don't require Message Content.) - General Information → copy Application ID →
DISCORD_CLIENT_ID. - Invite the bot: OAuth2 → URL Generator, scopes
bot+applications.commands, then open the generated URL and add it to your server.
2. Find your Vane model IDs
The bot needs a chat model and an embedding model. List what your Vane instance has configured:
curl http://localhost:3000/api/providers
Take a provider id (a UUID) and a model key (use the key, not the
display name) for both a chat model and an embedding model.
3. Configure
cp .env.example .env
# then fill in DISCORD_TOKEN, DISCORD_CLIENT_ID, and the VANE_* model values
Set DISCORD_GUILD_ID to your server's ID while testing — guild commands
appear instantly; global commands can take up to ~1 hour the first time.
4. Install & run
npm install
npm start # or: npm run dev (auto-restarts on file changes)
On startup the bot registers the /vane command and logs in.
Usage
In any channel the bot can see:
/vane question:<your question> [mode:speed|balanced|quality]
If you omit mode, it uses VANE_DEFAULT_MODE from your .env.
Configuration reference
| Variable | Required | Default | Notes |
|---|---|---|---|
DISCORD_TOKEN |
✅ | — | Bot token |
DISCORD_CLIENT_ID |
✅ | — | Application ID |
DISCORD_GUILD_ID |
— | — | Set for instant command registration in one server |
VANE_API_URL |
— | http://localhost:3000 |
Base URL of Vane |
VANE_CHAT_PROVIDER_ID |
✅ | — | Provider UUID from /api/providers |
VANE_CHAT_MODEL_KEY |
✅ | — | Chat model key |
VANE_EMBEDDING_PROVIDER_ID |
✅ | — | Provider UUID from /api/providers |
VANE_EMBEDDING_MODEL_KEY |
✅ | — | Embedding model key |
VANE_SOURCES |
— | web |
Comma list: web, academic, discussions |
VANE_DEFAULT_MODE |
— | balanced |
Used when the user omits mode |
VANE_SYSTEM_INSTRUCTIONS |
— | — | Extra guidance sent on every query |
VANE_TIMEOUT_MS |
— | 600000 |
Abort a search after this long (Discord cap is 900000) |
VANE_APPEND_SOURCES |
— | true |
Append a numbered Sources list |
Notes & limits
- 15-minute ceiling. After deferring, Discord allows follow-ups for 15
minutes. Keep
VANE_TIMEOUT_MS≤900000. A very longqualityrun could exceed this; if you hit it often, switch the client to streaming and edit the reply incrementally (the API supportsstream: true). - No auth on Vane's API. Run the bot on the same host/LAN as Vane, or put Vane behind a reverse proxy — don't expose port 3000 publicly.
- One question per command; conversation history isn't threaded (the API
supports it via
historyif you want to add it later).