Wampus is a context-aware Discord bot that answers questions where they are asked. Mention Wampus or reply to one of its messages and it analyzes the reply chain, selects only relevant channel context, optionally searches the web, and sends a concise answer.
It is designed around a simple principle: keep context selection and answer generation separate so the final response is grounded in the conversation instead of being fed an entire channel history.
- Answers mentions and replies to Wampus messages.
- Reads the surrounding reply chain and up to 50 recent channel messages when context is needed.
- Uses a dedicated relevance selector to remove unrelated conversation.
- Supports vision on the Router and Answer agents for image-based questions.
- Uses Tavily for focused, optional web searches.
- Includes an input guardrail that screens clear-cut injection, harmful, hate, NSFW, and spam content.
- Supports premium image generation through an OpenAI-compatible image endpoint.
- Allows administrators to enable or disable Wampus, restrict it to selected channels, and set a server persona.
- Tracks answer, image, and search usage in Postgres.
- Uses per-agent model and provider configuration through environment variables.
- Applies request and image-generation rate limits.
Every supported message follows the same pipeline:
Message trigger
-> Intake: reply-chain traversal and image collection
-> Guardrail: input safety screening
-> Router: intent, context, web-search, and image-generation decisions
-> Retrieval: reply chain plus recent channel candidates
-> Selector: relevant-message filtering
-> Tools: optional Tavily searches
-> Answer: grounded response under 2,000 characters
-> Send: one plain Discord reply
Image requests take a premium branch after routing. Wampus checks the user's premium status, creates an image prompt, calls the configured image provider, and posts the generated image as a Discord attachment.
The bot does not maintain a separate persistent conversation memory. Its conversational context comes from Discord reply chains and the current channel window.
- TypeScript and Node.js 20+
- Discord.js 14
- LangChain with
@langchain/openaiand LangGraph with@langchain/langgraph - Zod for agent input and output validation
- Neon Postgres and Drizzle ORM
- Tavily web search
- OpenAI-compatible image generation API
- Biome for formatting and linting
- Node.js 20 or newer
- A Discord application and bot token
- A Postgres-compatible database, such as Neon
- An OpenAI-compatible chat provider
- An OpenAI-compatible image provider
- A Tavily API key
-
Install dependencies:
npm install
-
Create the local environment file:
cp .env.example .env
On Windows PowerShell, use:
Copy-Item .env.example .env -
Set the required values in
.env. The application validates the environment at startup and exits when required values are missing or invalid. -
Apply the database migrations:
npm run db:migrate
-
Start the bot in development mode:
npm run dev
In the Discord Developer Portal:
- Create an application and add a bot user.
- Enable the Message Content Intent under privileged gateway intents.
- Set
DISCORD_TOKENin.env. - Set
DEV_GUILD_IDto a test server while developing. Commands are registered there immediately. - Invite the bot with the
botandapplications.commandsscopes and permissions appropriate for your server.
The bot uses the Guilds, GuildMessages, and MessageContent gateway intents. It ignores messages authored by bots, including itself.
For production, omit DEV_GUILD_ID and start with:
npm start -- --prodProduction commands are registered globally and may take time to propagate through Discord.
Copy .env.example and configure the following groups:
| Variable | Purpose |
|---|---|
DISCORD_TOKEN |
Discord bot token. Required. |
DEV_GUILD_ID |
Test guild for immediate slash-command registration. |
OWNER_IDS |
Comma-separated user IDs allowed to bypass administrator checks. |
LOG_LEVEL |
debug, info, warn, or error. |
RATE_LIMIT_MAX |
Requests allowed per user and guild within the rate-limit window. |
RATE_LIMIT_WINDOW_SEC |
Rate-limit window in seconds. |
IMAGE_RATE_LIMIT_MAX |
Image requests allowed per user and guild within the window. |
LLM_BASE_URL |
Global OpenAI-compatible chat endpoint. Required. |
LLM_API_KEY |
Global chat provider key. Required. |
LLM_MODEL |
Global fallback chat model. Required. |
GUARDRAIL_*, ROUTER_*, SELECTOR_*, ANSWER_*, IMGPROMPT_* |
Optional per-agent model, endpoint, and key overrides. Unset values fall back to the global LLM_* values. |
IMAGE_BASE_URL |
OpenAI-compatible /images endpoint. Required. |
IMAGE_API_KEY |
Image provider key. Required. |
IMAGE_MODEL |
Image model, defaulting to gpt-image-1. |
DATABASE_URL |
Postgres connection string. Required. |
TAVILY_API_KEY |
Tavily API key. Required. |
LOG_WEBHOOK_URL |
Optional webhook for operational info, warning, and error logs. |
GUILD_JOIN_WEBHOOK_URL |
Optional webhook for server-join notifications. |
Structured-output agents such as the Guardrail, Router, Selector, and Image-Prompt agents require a provider with reliable structured-output support. The Answer agent uses plain text generation and can be configured independently. Router and Answer models must support vision when image inputs are expected.
| Command | Access | Description |
|---|---|---|
/help |
Everyone | Browse available commands and usage examples. |
/about |
Everyone | View bot information and runtime statistics. |
/premium status |
Everyone | View user and server premium status. |
/premium set user:<user> enabled:<true|false> |
Developer | Enable or disable premium access for a user. |
/config show |
Administrator | Show server configuration. |
/config enable |
Administrator | Enable Wampus in the server. |
/config disable |
Administrator | Disable Wampus in the server. |
/config channel-add channel:<channel> |
Administrator | Restrict Wampus to an allowed text channel. |
/config channel-remove channel:<channel> |
Administrator | Remove a channel from the allowlist. An empty allowlist permits all channels. |
/config persona-set text:<text> |
Administrator | Add server-specific answer instructions. |
/config persona-clear |
Administrator | Remove the server persona. |
| Command | Description |
|---|---|
npm run dev |
Run the bot with tsx watch mode. |
npm start |
Run the bot directly with Node. |
npm run build |
Compile TypeScript. |
npm run typecheck |
Run TypeScript checks without emitting files. |
npm run lint |
Check the repository with Biome. |
npm run lint:fix |
Apply Biome fixes. |
npm run format |
Format the repository with Biome. |
npm run db:generate |
Generate Drizzle migrations from the schema. |
npm run db:migrate |
Apply pending Drizzle migrations. |
npm run db:studio |
Open Drizzle Studio. |
Before opening a pull request, run:
npm run typecheck
npm run lintsrc/
index.ts # Discord client bootstrap and event wiring
config/ # Environment, bot, model, and logging configuration
discord/
events/messageCreate.ts # Trigger detection and request handling
intake.ts # Reply-chain traversal and image collection
format.ts # Plain replies and length fallback
commands/ # Slash commands
agent/
graph.ts # LangGraph pipeline execution
guardrail.ts # Input safety screening
router.ts # Intent and request classification
contextRetrieval.ts # Candidate context retrieval
selector.ts # Relevant-context selection
answer.ts # Grounded response generation
image.ts # Premium image generation
imagePrompt.ts # Image prompt generation
tools/ # Tavily and image-provider integrations
db/ # Drizzle schema, client, and repositories
types/ # Zod schemas for agent contracts
drizzle/ # Database migrations
config.yml # Bot branding and command metadata
- Never commit
.env, provider keys, database credentials, or bot tokens. - Keep
discord-bot-oracle.keyand other private credentials outside version control. - Treat
OWNER_IDSas a high-trust setting because it can bypass normal administrator checks. - Use separate Discord applications, provider keys, and databases for development and production.
- The guardrail is intentionally fail-open to avoid taking the bot offline during a provider outage; downstream prompts still enforce grounded behavior.
- Optional webhook delivery failures do not stop normal bot operation.
- Usage events are recorded asynchronously for answers, image generation, and web searches.
This project is proprietary and is released under an All Rights Reserved license. See LICENSE for the full terms.