Skip to content

Configuration Reference ​

All configuration is via environment variables. Copy .env.example to .env and fill in what you need.

Required ​

DISCORD_TOKEN ​

Your bot's token from the Discord Developer Portal.

DISCORD_APP_ID ​

Your bot's application ID (numeric), from the same page.

LLM Models ​

DEFAULT_MODEL ​

The model used when no $model directive is set on an entity. Format: provider:model for known providers, or a URL-based spec for OpenAI-compatible endpoints.

DEFAULT_MODEL=google:gemini-3-flash-preview

Known providers: See provider list below.

OpenAI-compatible endpoints: Use the base URL as the provider — unknown provider names are routed through @ai-sdk/openai-compatible:

DEFAULT_MODEL=http://localhost:11434:llama3          # Ollama (local)
DEFAULT_MODEL=https://my.proxy.io/v1:gpt-4          # Custom proxy
DEFAULT_MODEL=api.example.com:mistral-7b             # HTTPS assumed if no scheme

ALLOWED_MODELS ​

Comma-separated allowlist of models entities can select via $model. Supports * wildcards.

ALLOWED_MODELS=google:*,anthropic:*

When unset, all models are allowed.

MAX_RESPONSE_CHAIN ​

Default maximum number of consecutive self-triggered responses (an entity responding to itself). Prevents infinite loops. Default: 3. Set to 0 for unlimited.

MAX_RESPONSE_CHAIN=3

This is the global default. Per-channel and per-server overrides can be set with /config-chain or /admin config chain (requires Manage Webhooks). The override takes precedence over this env var.

Rate Limiting ​

Hologram includes a three-scope sliding-window rate limiter to prevent cascade incidents. Limits are checked before each entity response; entities that exceed a limit have their response dropped and the owner receives a deduplicated DM warning.

Scopes (checked in order, all must pass) ​

  1. Per-entity — configured via /edit <entity> type:advanced (field: "Per-entity rate limit"). Limits how fast a single entity can respond anywhere.
  2. Per-owner — configured via /admin config rate scope:channel|server or web UI. Limits total responses per minute from all entities owned by the same user.
  3. Per-channel — configured via /admin config rate scope:channel|server or web UI. Limits total entity responses per minute in a channel regardless of owner.

All limits use a sliding 60-second window. NULL = no limit (inherit from narrower scope).

Mutes (kill switches) ​

/admin mute create / /admin disable channel|server write persistent mutes to the entity_mutes table. Mutes are checked before fact evaluation and apply even when rate limits are not configured.

Startup Catch-Up ​

When the bot restarts, it can backfill messages it missed while offline.

CATCHUP_ON_STARTUP ​

Controls when catch-up runs. Default: all.

ValueBehavior
allFetch all bound channels immediately on startup
lazyFetch each channel on first message received there
offDisable catch-up entirely

CATCHUP_RESPOND ​

Whether to evaluate and respond to missed messages during catch-up. Default: false.

When true, entities will respond to recent messages they missed, subject to CATCHUP_RESPOND_MAX_AGE_MS.

CATCHUP_RESPOND_MAX_AGE_MS ​

Maximum age (in milliseconds) of a missed message that the bot will respond to during catch-up. Default: 300000 (5 minutes).

Messages older than this are stored in history but not responded to.

Web Server ​

WEB ​

Set to false to disable the built-in web API server. The web server is on by default.

WEB=false

WEB_PORT ​

Port for the web API server. Default: 3000. PORT is also accepted as a fallback.

WEB_PORT=3000

Logging ​

LOG_LEVEL ​

Verbosity of structured logs. Default: info.

ValueOutput
debugEverything, including message processing internals
infoNormal operation
warnWarnings and errors only
errorErrors only

API Keys ​

Set the key for each LLM provider you want to use. At least one is required.

ProviderEnv varNotes
Google AIGOOGLE_GENERATIVE_AI_API_KEYRequired for default google:* models
AnthropicANTHROPIC_API_KEYFor anthropic:* models
OpenAIOPENAI_API_KEYFor openai:* models
GroqGROQ_API_KEY
MistralMISTRAL_API_KEY
xAIXAI_API_KEY
DeepSeekDEEPSEEK_API_KEY
CohereCOHERE_API_KEY
CerebrasCEREBRAS_API_KEY
PerplexityPERPLEXITY_API_KEY
Together AITOGETHER_AI_API_KEY
FireworksFIREWORKS_API_KEY
DeepInfraDEEPINFRA_API_KEY
HuggingFaceHUGGINGFACE_API_KEY
AzureAZURE_API_KEY
Google VertexGOOGLE_VERTEX_API_KEY
Amazon BedrockAMAZON_BEDROCK_ACCESS_KEY_ID + AMAZON_BEDROCK_SECRET_ACCESS_KEY

Image Generation ​

For entities that use image-generation models (e.g. google:gemini-2.0-flash-image-generation), generated images are returned as Discord attachments automatically — no extra configuration needed for that.

The following env vars control ComfyUI-based image generation (separate pipeline):

RunComfy ​

RUNCOMFY_API_KEY=

Or serverless:

RUNCOMFY_SERVERLESS_API_KEY=
RUNCOMFY_SERVERLESS_DEPLOYMENT_ID=
RUNCOMFY_SERVERLESS_OVERRIDE_MAPPING=   # JSON mapping of variable names to node paths

SaladCloud ​

SALADCLOUD_API_KEY=
SALADCLOUD_ORG_NAME=

RunPod ​

RUNPOD_API_KEY=
RUNPOD_COMFY_ENDPOINT_ID=

Self-Hosted ComfyUI ​

COMFYUI_ENDPOINT=http://localhost:8188

Image Storage ​

For persistent image URLs (instead of ephemeral Discord attachments):

S3_ENDPOINT=          # e.g. https://xxx.r2.cloudflarestorage.com
S3_BUCKET=
S3_REGION=auto
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_PUBLIC_URL=        # Public base URL for generated links

Compatible with Cloudflare R2, AWS S3, MinIO, and any S3-compatible storage.

Released under the MIT License.