.env file handles startup configuration — credentials, provider selection, file paths, and optional integration keys. This file is read once when the bot launches and requires a restart to change. The runtime config layer handles tunable behavior values — polling intervals, timeouts, generation pacing — via /config commands that take effect immediately without a restart.
Environment Variables
Copy.env.sample to .env and fill in your values before launching the bot:
Required
These three variables must be set. The bot refuses to start if any of them is missing or still holds a placeholder value.| Variable | Description |
|---|---|
BOT_TOKEN | Your Discord bot token from the Developer Portal |
CHANNEL_ID | Numeric channel ID (Discord snowflake) where the bot posts its startup message |
AI_PROVIDER | Active AI provider: gemini, openai, ollama, nim, azure, groq, or openrouter |
AI Provider Keys
You only need to set the key for the provider you’ve selected inAI_PROVIDER. Leave the others blank.
| Provider | AI_PROVIDER value | Variable(s) to set | Notes |
|---|---|---|---|
| Google Gemini | gemini | GOOGLE_API_KEY | Default provider |
| OpenAI | openai | OPENAI_API_KEY | Also set OPENAI_BASE_URL (default: https://api.openai.com/v1/chat/completions) |
| Ollama | ollama | OLLAMA_BASE_URL | Defaults to http://localhost:11434/api/chat if not set |
| NVIDIA NIM | nim | NVIDIA_API_KEY | Also set NVIDIA_NIM_BASE_URL (default: https://integrate.api.nvidia.com/v1/chat/completions) |
| Azure AI Foundry | azure | AZURE_AI_KEY + AZURE_AI_BASE_URL | AZURE_AI_BASE_URL is your Azure AI Foundry endpoint |
| Groq | groq | GROQ_API_KEY | Base URL defaults to https://api.groq.com/openai/v1/chat/completions |
| OpenRouter | openrouter | OPENROUTER_API_KEY | Optionally set OPENROUTER_SITE_URL and OPENROUTER_SITE_NAME |
MODEL_NAME to override the default model for your chosen provider, or use AI_PROVIDER_MODEL to set a per-provider model override that persists across provider switches.
Optional Integrations
These variables unlock specific features. The bot starts and runs normally without them — the corresponding commands will simply be unavailable or fall back to a different method.| Variable | Description |
|---|---|
MVSEP_API_KEY | Required for audio stem separation via the ~separate command (MVSEP module) |
MVSEP_WEBHOOK_URL | Public URL for MVSEP task completion callbacks (e.g. https://your-host.example.com/webhooks/mvsep) |
MVSEP_WEBHOOK_SEND_MAIL_ON_ERROR | Set to true to have MVSEP send an email on task error (default: false) |
WOLFRAM_APPID_SHORT | Wolfram Short Answer API key used by the ~math command for direct computation |
WOLFRAM_APPID_LLM | Wolfram LLM API key used as a fallback if the short answer API doesn’t return a result |
LOGOKIT_TOKEN | LogoKit API token for fetching publication logos in RSS feed embeds |
GOOGLE_SEARCH_API_KEY + SEARCH_ENGINE_ID | Legacy fallback for the /search command when the primary search method is unavailable |
CHROMA_COLLECTION | ChromaDB collection name for the knowledge base (default: freesona) |
CHROMA_PERSIST_DIRECTORY | Local path for ChromaDB vector storage (default: ./.chroma) |
BOT_NAME | Display name used in startup messages and certain response contexts (default: Freesona) |
HTTP_PORT | Port for the built-in health check and webhook server (default: 10000) |
File Paths
Freesona stores several mutable files: a runtime config file, a user memory database, a warnings database, and persona files. The correct paths depend on where you’re hosting the bot.| Variable | Local default | Cloud (Railway / Render) |
|---|---|---|
CONFIG_FILE_PATH | config.json | /data/config.json |
MEMORY_FILE_PATH | memory.db | /data/memory.db |
WARNINGS_FILE_PATH | warnings.db | /data/warnings.db |
AI_PERSONA_FILE | persona.txt | /data/persona.txt |
AI_PERSONA_JSON_FILE | persona.json | /data/persona.json |
AI_PERSONAS_FILE | personas.json | /data/personas.json |
On cloud hosts without a persistent volume, file changes don’t survive a redeployment — the container resets to the image state. Mount a persistent volume at
/data and switch to the /data/ paths in your .env to keep your config, memory, warnings, and persona across deploys.Runtime Config
The/config command group lets the bot owner inspect and adjust tunable behavior values while the bot is running. Changes take effect immediately — no restart needed.
These commands require you to be the bot owner (the account that owns the Discord application in the Developer Portal).
Commands
/config list— Prints all configurable keys with their descriptions and current defaults./config show [key]— Shows the current value and default for one key, or all keys if you omit the argument./config set <key> <value>— Updates a key to a new value immediately. The bot converts the value to the correct type (int, float, bool, or string) based on the key’s default type./config reset <key>— Removes the override and restores the key to its compiled-in default.
Configurable Keys
These are the configurable keys and the defaults the bot ships with.| Key | Type | Default | Description |
|---|---|---|---|
mvsep_poll_interval | int | 10 | Seconds between MVSEP API polling checks while waiting for a stem separation task |
mvsep_poll_timeout | int | 600 | Maximum seconds to wait for an MVSEP task before giving up |
ytdlp_subprocess_timeout | int | 300 | Maximum seconds for a yt-dlp subprocess to complete before it is killed |
ytdlp_compress_target_mb | float | 9.5 | Target file size in MB when compressing video for Discord upload |
generation_split_min_length | int | 280 | Minimum character length before a long AI response is split into multiple messages |
generation_split_delay_base | float | 1.2 | Base delay in seconds between consecutive message segments |
generation_split_delay_per_char | float | 0.012 | Additional delay added per character in a segment (creates natural pacing for longer chunks) |
generation_split_delay_max | float | 3.5 | Maximum delay in seconds between any two segments, regardless of length |
generation_rate_limit | float | 5 | Minimum seconds between successive AI generation calls (per-bot rate limit) |
debounce_seconds | float | 1.2 | Seconds to wait after a user’s last message before generating a reply (collapses rapid-fire messages) |
autonomy_cooldown_seconds | int | 120 | Per-channel cooldown in seconds before the bot can autonomously respond in that channel again |
autonomy_user_cooldown | int | 60 | Per-user cooldown in seconds before the bot can autonomously respond to the same user again |
Example Usage
config.json
config.json is the bot’s runtime state file. Freesona reads it on startup and writes to it whenever you use commands that change persistent settings. You don’t need to edit this file manually — the Discord commands are the intended interface.
A fresh config.json starts from config.sample.json and contains only:
config.json
| Field | Set by | Description |
|---|---|---|
prefix | ~prefix <new_prefix> | The active prefix for all prefix commands (max 5 characters) |
chat_channel_id | /setchannel | Channel where the bot responds to general (non-mention) messages |
conversation_response_mode | /chatmode | How the bot decides to respond: all, mentions, or smart |
autonomy_* settings | /autonomy | Whether autonomy mode is on, and its frequency setting |
enabled_modules | /module enable / /module disable | Per-module on/off state persisted across restarts |
provider / provider_model | /provider set / /model set | Active AI provider and model overrides |
timezone | /settimezone | IANA timezone string for time-sensitive features |
rss_feeds | /rss add / /rss remove | Configured RSS/Atom feed subscriptions |
You don’t edit
config.json directly. Use the Discord commands — ~prefix, /setchannel, /autonomy, /module, /provider, /model, /settimezone, and /rss — to change these values. The bot writes the file automatically.