kiro-discord-bot

Environment Reference #

The bot does not load .env by itself. Inject these variables through your shell, launchd, systemd, Docker, or another process manager.

Use /doctor after startup to inspect effective values. Secrets are redacted in diagnostics.

How to Use This Page #

Environment variables fall into four groups:

Required variables must be set before startup. Optional variables can usually stay empty because the bot applies conservative defaults. After changing any process-level environment variable, restart the service and run /doctor in Discord to confirm the effective runtime. /doctor redacts secrets, so it is the safest way to validate production configuration.

Existing Kiro-only deployments do not need new OMP variables. Add OMP variables only when the host has omp installed, authenticated, and intentionally enabled.

kiro-cli and omp are installed and updated outside this repository. See Installation for basic CLI setup and update commands, and use the upstream docs for platform-specific details.

Common Configuration Shapes #

Kiro-Only Default #

This is the default upgrade path for existing deployments. OMP is not required.

AGENT_ENGINE=kiro
AGENT_ENGINES_ENABLED=

Dual-Engine Bot #

Use this when the same bot should allow channel admins to switch between Kiro and OMP with /engine.

AGENT_ENGINE=kiro
AGENT_ENGINES_ENABLED=kiro,omp
OMP_PATH=omp

Only enable OMP after omp is installed and authenticated for the service user.

OMP With a Production Profile #

Use a named profile when you want bot-managed OMP auth, settings, sessions, and caches to stay isolated from your interactive OMP profile.

OMP_PROFILE=kiro-discord-bot omp setup
OMP_PROFILE=kiro-discord-bot

Leave OMP_PROFILE empty if you intentionally want the service to use OMP's default profile for backward compatibility.

Pure OMP Bot #

Use this only when Kiro should not be available to the bot.

AGENT_ENGINE=omp
AGENT_ENGINES_ENABLED=omp
OMP_PATH=omp

Multi-Bot Deployment #

When running multiple department bots, give each bot its own Discord token and persistent data directory.

DISCORD_TOKEN=...
DATA_DIR=/var/lib/kiro-discord-bot/marketing
BOT_PEERS=...

Do not share DATA_DIR between bot identities. Audit DBs, the usage SQLite DB and migrated JSONL archives, channel settings, MCP policy, and agent runtime files are bot-owned state.

WebShare Bot and Relay #

Enable WebShare only after a self-host relay is reachable over HTTPS/WSS and the bot can authenticate as the relay host.

WEBSHARE_ENABLED=true
WEBSHARE_RELAY_URL=wss://relay.example
WEBSHARE_PUBLIC_BASE_URL=https://relay.example
WEBSHARE_HOST_TOKEN_FILE=/etc/kdb-webshare/host-token

Use the matching relay-side RELAY_HOST_TOKEN_FILE or RELAY_HOST_TOKEN. The public base URL is what users open in the browser; the relay URL is the relay origin or route prefix the bot uses before appending /r/<room>.

Variable Relationships #

Upgrade Notes #

Required #

VariableDefaultPurpose
DISCORD_TOKENrequiredDiscord bot token.

Core Runtime #

VariableDefaultPurpose
DISCORD_GUILD_IDemptyGuild used for slash command registration. Empty uses Discord's global command scope.
KIRO_CLI_PATHkiro-cliExecutable path for Kiro CLI.
OMP_PATHompExecutable path for the omp engine (only needed when omp is enabled).
OMP_PROFILEemptyOptional OMP profile used by bot-managed OMP agents. OMP profiles isolate auth, settings, sessions, and caches. New production deployments should set kiro-discord-bot and authenticate that profile before enabling OMP. Empty keeps OMP's default profile for backward compatibility.
OMP_SESSION_DIRDATA_DIR/omp-agent-runtime/sessionsBot-managed OMP session directory passed to omp --session-dir. Leave empty to use the data-dir default, or set an absolute path when the service needs a shared session directory.
AGENT_ENGINEkiroDefault agent engine for new channels: kiro or omp.
AGENT_ENGINES_ENABLED(AGENT_ENGINE only)Comma list of engines /engine may switch to (e.g. kiro,omp). Empty disables switching.
KIRO_API_KEYemptyHeadless Kiro authentication key when kiro-cli login is not used.
DEFAULT_CWD/projectsRoot shown by /cwd setup.
ALLOWED_CWD_ROOTSemptyOptional comma-separated root allowlist for channel working directories.
DATA_DIR./dataPersistent bot data, channel metadata, sessions, audit DB, usage SQLite DB and migration archives, MCP policy, and bot-managed engine runtime directories.
BOT_LOCALEenBot response locale. Supported project locales are English and Traditional Chinese.
BOT_GM_USER_IDSemptyOptional comma-separated Discord user IDs with full bot-manager access across channels, A2A management, and usage-limit bypasses.

Agent Execution #

VariableDefaultPurpose
ASK_TIMEOUT_SEC3600Maximum wait for a single agent request.
QUEUE_BUFFER_SIZE20Per-target job queue buffer.
STREAM_UPDATE_SEC3Minimum streaming update interval.
MAX_SCANNER_BUFFER_MB64Scanner buffer for long Kiro CLI output.
DOWNLOAD_TIMEOUT_SEC120Attachment download timeout.
AGENT_CAPACITY_MODEautoDynamic host resource gate for starting ACP child agents. auto checks CPU/load and memory, reclaims idle agents first, then refuses starts under pressure. off disables this dynamic gate; explicit legacy caps such as THREAD_AGENT_MAX>0 still apply.
KIRO_MODELemptyInitial model override.
KIRO_AGENTemptyInitial Kiro agent profile or mode.
TRUST_ALL_TOOLStrueIf exactly true, ACP server permission requests are approved by default. Any other value denies by default unless covered by TRUST_TOOLS.
TRUST_TOOLSemptyOptional comma-separated allowlist for trusted tool approvals.
KIRO_MCP_CONFIGemptyOptional MCP catalog source. Runtime agents receive isolated settings under DATA_DIR/kiro-agent-runtime/.

Thread and Listen Behavior #

VariableDefaultPurpose
THREAD_AUTO_ARCHIVE1440Auto-archive duration for task threads, in minutes.
THREAD_AGENT_MAX0Legacy thread-agent hard cap. 0 means no fixed count; the bot uses dynamic CPU/memory agent capacity instead. When this cap is set and full, the bot closes inactive thread agents automatically before refusing; if only working agents remain, the error lists those threads to wait for.
THREAD_AGENT_IDLE_SEC900Idle timeout for thread agents.
CHANNEL_AGENT_IDLE_SEC0Idle timeout for channel agents. 0 disables channel-agent idle shutdown.
BOT_PEERSemptyComma-separated bot peer hints for multi-bot mention and handoff behavior.

Time, Usage, and Maintenance #

VariableDefaultPurpose
HEARTBEAT_SEC60Background maintenance tick.
DISCORD_GATEWAY_WATCHDOG_ENABLEDtrueEnables Discord Gateway heartbeat health checks. When stale, the bot closes and reopens the gateway session; repeated failures exit so the process manager can restart it.
DISCORD_GATEWAY_STALE_AFTER_SEC180Seconds without a Discord Gateway heartbeat ACK before the watchdog treats the session as stale.
DISCORD_GATEWAY_RECONNECT_TIMEOUT_SEC45Timeout for one watchdog reconnect attempt.
DISCORD_GATEWAY_MAX_RECONNECT_ATTEMPTS3Consecutive failed watchdog reconnect attempts before the bot exits with failure for systemd/launchd/Docker restart policy.
CRON_TIMEZONEemptyTime zone for scheduled jobs.
CRON_TIMEOUT_MIN5Cron job agent execution timeout, in minutes. Values below 1 fall back to 5.
USAGE_TIMEZONECRON_TIMEZONE, then local defaultTime zone for /usage day, week, and month windows.
USAGE_RETENTION_MONTHS0Online SQLite usage retention in months. 0 keeps all rows; archived legacy JSONL migration backups are unaffected.
USAGE_CREDIT_USD_RATE0USD value of one Kiro credit for effective USD limits. Required to be finite and greater than 0 when any USD usage limit is enabled.
USAGE_LIMIT_DAILY_USD0Per-user daily effective USD ceiling. 0 disables the daily gate.
USAGE_LIMIT_WEEKLY_USD0Per-user weekly effective USD ceiling. 0 disables the weekly gate.
USAGE_LIMIT_MONTHLY_USD0Per-user monthly effective USD ceiling. 0 disables the monthly gate.
ATTACHMENT_RETAIN_DAYS7Retention for downloaded Discord attachments.
ATTACHMENT_MAX_MB25Maximum attachment size accepted by the bot.
PREFLIGHT_MODEwarnACP compatibility preflight mode. strict exits on failure, skip disables the check, and unknown values fall back to warn.
SKIP_PREFLIGHTemptyAny non-empty value skips ACP preflight. Prefer PREFLIGHT_MODE=skip for explicit configuration.

WebShare Bot #

WebShare is disabled while WEBSHARE_ENABLED=false or empty. When enabled, /webshare start creates a target-scoped delegated browser link. See WebShare for the deployment runbook and security model.

VariableDefaultPurpose
WEBSHARE_ENABLEDfalseEnables /webshare start, /webshare stop, /webshare status, and /webshare revoke.
WEBSHARE_RELAY_URLemptyRelay origin or route prefix the bot connects through as host, for example wss://relay.example. Required when WebShare is enabled.
WEBSHARE_PUBLIC_BASE_URLemptyBrowser-facing HTTPS base URL used to build control and view links, for example https://relay.example. Required when WebShare is enabled.
WEBSHARE_HOST_TOKEN_FILEemptyPath to the relay host bearer token. Preferred production setting.
WEBSHARE_HOST_TOKENemptyRelay host bearer token value. Use only for local development or secret-manager injection.
WEBSHARE_MAX_FRAME_BYTES4194304Maximum encrypted relay frame size accepted by the bot. Keep aligned with RELAY_MAX_FRAME_BYTES.
WEBSHARE_RECONNECT_INITIAL_MS1000Initial bot-to-relay reconnect backoff in milliseconds.
WEBSHARE_RECONNECT_MAX_MS30000Maximum bot-to-relay reconnect backoff in milliseconds.

WebShare Relay #

These variables configure the standalone webshare-relay process, not the main bot process unless both are launched from the same environment.

VariableDefaultPurpose
RELAY_ADDR:8080HTTP listen address for static assets, WebSocket rooms, health, and optional local reverse proxying.
RELAY_PUBLIC_BASE_URLemptyBrowser-facing HTTPS base URL used by relay healthcheck defaults and operator diagnostics.
RELAY_HOST_TOKEN_FILEemptyFile containing the bearer token required for bot host WebSocket connections. Preferred production setting.
RELAY_HOST_TOKENemptyBearer token value for host WebSocket authentication. The relay refuses to serve without either token source.
RELAY_TRUST_PROXYfalseTrust X-Forwarded-* headers from the reverse proxy. Enable only when requests arrive through a trusted proxy.
RELAY_MAX_ROOMS1000Maximum concurrent relay rooms.
RELAY_MAX_PEERS_PER_ROOM32Maximum connected guest peers per room.
RELAY_MAX_FRAME_BYTES4194304Maximum opaque encrypted frame size the relay routes.
RELAY_HOST_IDLE_TIMEOUT0Host idle timeout duration. 0 disables application-level idle expiry.
RELAY_GUEST_IDLE_TIMEOUT0Guest idle timeout duration. 0 disables application-level idle expiry.
RELAY_WRITE_TIMEOUT30sPer-write timeout for relay WebSocket writes. Must be greater than zero.
RELAY_LOG_LEVELinfoRelay log level: debug, info, warn, or error.
RELAY_METRICS_ADDRemptyOptional Prometheus metrics listen address, commonly 127.0.0.1:9090.

Audit #

VariableDefaultPurpose
AUDIT_LOG_ENABLEDtrueEnable audit recording.
AUDIT_LOG_DBDATA_DIR/audit/discord.sqliteSQLite audit database path.
AUDIT_LOG_RETENTION_DAYS0Audit retention. 0 keeps all rows.
AUDIT_LOG_QUEUE_SIZE1000Async audit queue size. If full, audit-only events may be dropped and logged.
AUDIT_LOG_RECORD_CONTENTtrueInclude message content in audit projections and raw event payloads.
AUDIT_LOG_RECORD_TYPINGfalseRecord Discord typing events.

A2A NATS Custom Binding #

A2A is disabled while NATS_URL is empty. Existing Discord behavior should remain unchanged in that state. If NATS_URL is set, startup requires a valid A2A_AGENT_ID; clear NATS_URL for rollback/no-op disable. For step-by-step setup, see Enable A2A with NATS. For identity, subject, policy, and task-state terminology, see A2A Protocol Model. For rollout gates, ACL templates, and smoke matrix, see A2A NATS Rollout.

VariableDefaultPurpose
NATS_URLemptyNATS server URL list. Empty disables A2A.
NATS_CREDS_FILEemptyNKey/JWT credentials file path. Preferred production credential.
NATS_TOKENemptyDevelopment token. Do not use as the only production credential.
NATS_TLS_CA_FILEemptyTLS CA file for server certificate validation. This is not client mTLS authentication by itself.
A2A_AGENT_IDemptyStable bot/process base identity. NATS credentials or ACLs must authorize the runtime IDs derived from this base identity.
A2A_RUNTIME_ID_MODElegacylegacy, dual, or runtime. Production target is runtime; dual is only for a bounded legacy drain.
A2A_CONFIRMATION_SECRETemptySigns A2A policy/delegation confirmation tokens and Discord confirmation buttons. Set a stable secret; otherwise it falls back to DISCORD_TOKEN or a process-random value that invalidates pending confirmations on restart.
A2A_AGENT_NAMEemptyPublic peer-card display name.
A2A_AGENT_DESCRIPTIONemptyPublic capability summary. Do not include secrets, private paths, hosts, or user data.
A2A_TASK_TIMEOUT_SEC3600Remote task timeout seconds.
A2A_MAX_DELEGATION_DEPTH1Maximum nested delegation depth.
A2A_AUTO_DELEGATE_ENABLEDfalseAllows automatic outbound delegation when channel policy also permits it.
A2A_REQUIRE_CONFIRMATION_FOR_REMOTEtrueRequires confirmation before remote task execution.
A2A_PRODUCTION_SECURITYfalseWhen true, requires NATS_CREDS_FILE and rejects token-only or unauthenticated production startup.
A2A_TASK_RETENTION_DAYS30Task/event retention. Set 0 only when permanent retention is intentional.
A2A_OBJECT_RETENTION_DAYS30Object/artifact retention. Set 0 only when permanent retention is intentional.
A2A_MAX_PENDING_TASKS100Global pending remote task limit. 0 means unlimited.
A2A_MAX_OUTBOUND_TASKS_PER_CHANNEL10Outbound remote task limit per channel. 0 means unlimited.
A2A_MAX_INBOUND_TASKS_PER_CHANNEL10Inbound remote task limit per channel. 0 means unlimited.
A2A_MAX_EVENT_RATE_PER_MIN120A2A event quota per minute. 0 means unlimited.

After changing any A2A variable, restart the bot and run /doctor. /doctor reports enabled/disabled state, auth mode, production guard state, retention, quotas, and redacted credential presence without raw tokens or credential paths.

Speech to Text #

VariableDefaultPurpose
STT_ENABLEDfalseEnable voice/audio transcription.
STT_PROVIDERgroqSTT provider.
STT_API_KEYemptyProvider API key.
STT_MODELemptyProvider model override.
STT_LANGUAGEemptyOptional language hint.
STT_MAX_DURATION_SEC300Maximum audio duration for transcription.

Discord MCP Server #

These variables configure direct mcp-discord-server file/member behavior. mcp-discord does not apply local guild/channel/read-only/write/destructive env caps; /mcp manage decides which discord_* tools are exposed, and Discord API permissions decide which resources the token can access.

VariableDefaultPurpose
MCP_DISCORD_DOWNLOAD_DIRemptyRequired root for discord_download_attachment save paths when set.
MCP_DISCORD_UPLOAD_DENY_PATHSemptyAdditional comma- or newline-separated wildcard patterns denied by discord_send_file; defaults still block bot/Kiro/OMP runtime roots.
MCP_DISCORD_UPLOAD_DENY_CASE_INSENSITIVEplatform defaultOverride upload denylist matching case sensitivity; default is case-insensitive on macOS/Windows and case-sensitive elsewhere.

Media MCP Server #

These variables configure mcp-media-server.

VariableDefaultPurpose
GEMINI_API_KEYemptyEnables Gemini image, video, music, and TTS providers.
OPENAI_API_KEYemptyEnables OpenAI image and TTS providers.
MEDIA_DEFAULT_IMAGE_MODELprovider defaultDefault image model override.
MEDIA_DEFAULT_VIDEO_MODELprovider defaultDefault video model override.
MEDIA_DEFAULT_MUSIC_MODELprovider defaultDefault music model override.
MEDIA_DEFAULT_TTS_MODELprovider defaultDefault TTS model override.
MEDIA_SYNC_WAIT_SEC20How long a legacy media tool waits for an immediate result before returning a job_id. Keep this below the MCP client's request timeout.
MEDIA_SYNC_TIMEOUT_SEC600Maximum runtime for a managed job started by a legacy media tool. Explicit async jobs use MEDIA_JOB_TIMEOUT_SEC instead.
MEDIA_JOB_TIMEOUT_SEC900Maximum runtime for an async media job.
MEDIA_JOB_RETENTION_SEC86400How long completed async job metadata remains listable.
MEDIA_JOB_MAX_ACTIVE4Maximum queued or running async media jobs in one mcp-media-server process. Set 0 to disable the limit.

If neither GEMINI_API_KEY nor OPENAI_API_KEY is set, mcp-media-server exits at startup.