Skip to main content
Create a Discord integration from your project’s Integrations page to start agents from mentions and continue conversations in Discord threads.

Connect your bot

In the Discord Developer Portal:
  1. Create an application and choose its name in Discord. Copy the Application ID and Public Key from General Information.
  2. Under Bot, copy the bot token, or use Reset Token to create one.
  3. Enable Bot → Privileged Gateway Intents → Message Content Intent before connecting. This is required to read replies that do not mention the bot.
  4. Under Installation, enable Guild Install.
Omnara receives server messages through Gateway; this integration does not support DMs. The bot needs View Channels, Read Message History, Send Messages, Add Reactions, Create Public Threads and Send Messages in Threads in the channels it uses. Grant Attach Files if agents will upload files.

Dashboard

Choose Discord bot on your project’s Integrations page. Keep the suggested Omnara name discord-bot or enter your own, such as support. Enter the Application ID, public key and bot token, then choose Create and connect. Omnara saves the credential for you and retrieves the bot User ID and display name from the token. After connecting, save the displayed Interactions Endpoint URL under General Information in Discord. Add bot to server opens Discord with the permissions above already selected. Choose a server you manage, then select Profiles for mentions in Omnara and select Save changes. The dashboard requires the public key. It verifies interaction callbacks for profile menus, questions and approvals; it is different from the bot token used to read and send messages. Discord controls who can install the bot and access its conversations. Public bots are supported: people in accessible conversations can launch the offered profiles and answer agent questions and approvals without Omnara project membership, subject to the agent’s configured permissions. For internal use, turn off Public Bot under Bot in the Developer Portal when available, and restrict server/channel access in Discord. This setting limits new installations; review existing servers separately. See Discord’s bot authorization guidance.

API

Create the integration with POST /orgs/{orgID}/projects/{projectID}/integrations:
Save the token as a project-available generic secret, with material: {"kind":"generic","value":"your-bot-token"}. Configure the saved integration through POST /orgs/{orgID}/projects/{projectID}/integrations/{integrationID}/setup:
Use the integration’s current setup_revision. provider_tenant_id is the Application ID; neither it nor the bot User ID is the guild ID. Setup discovers and saves the bot User ID as provider_account_ref. If supplied explicitly, it must match the token. Reconnecting cannot change the saved application or bot. Omnara manages one Gateway connection per integration. This supports bots in fewer than 2,500 servers; larger bots require sharding, which is not currently supported. Omit provider_config during token rotation to keep the current settings. Supplying it replaces the settings, so include every field you intend to retain. The API permits omitting the public key for messaging with a single launch profile. Profile menus and Discord questions or approvals require it and a verified Interactions Endpoint URL. Install the bot through Discord with the permissions listed above. Each saved integration has an independent runtime. Integrations can use the same bot credentials, including in different projects, but duplicated sessions consume provider capacity. Overlapping launch behavior can create duplicate responses. Omnara does not merge these independently configured integrations. Unrelated messages without role mentions or a mention of this bot use inbox capacity but make no Discord REST requests. Omnara checks exact thread subscriptions and pending launches before looking up the channel. Role mentions require a guild-role lookup unless the bot user is also mentioned. Bot mentions require a channel lookup and share the bot’s REST quota with replies. Identity checks and attachment downloads happen only after routing finds a recipient.

Launch from mentions

Choose Profiles for mentions in the integration’s settings. Mentions work in every server where this bot is installed and permitted; manage server and channel access in Discord. All of those servers use this Omnara project’s profile choices. Mention either the bot user or its own Discord-managed role. Omnara verifies role ownership with Discord; matching names, other assigned roles and @everyone do not trigger a launch. Mentioning both the user and its role is one request. When starting an agent inside an existing thread or forum post, wait for the bot’s response before sending follow-ups. Messages sent while Omnara is identifying that thread can be missed, including while Discord lookups are retrying. Once the agent has been attached to the thread, this limitation no longer applies. For the API, put launcher inside settings and send it to PUT /orgs/{orgID}/projects/{projectID}/integrations/{integrationID}:
Profiles are ordered, distinct public IDs. Discord launchers do not accept server or channel filters. Updates replace settings; send {"settings":{}} to remove the mention launcher. A mention in a parent channel creates or reuses the public thread attached to that message. A mention already inside a thread uses that thread. One offered profile starts immediately; several profiles produce a menu and start only the selected profile. Anyone in the conversation can choose. The menu expires after an hour; send follow-ups after selecting, because earlier replies may be missed. The launcher derives the agent’s tools and interaction handler for the thread, preserving existing explicit entries in the profile config, and attaches a thread subscription. Human messages steer the agent and cancel open interactions. Bot and webhook messages are ignored. The bot adds an eyes reaction after a message is accepted for an agent. Enable Add Reactions on the bot’s role if you installed it before this permission was included in setup. A failed reaction does not prevent the agent from receiving the message. Change Profiles for mentions directly on the integration page and select Save changes to update future launches; existing agents keep their configs. Selecting profiles enables mention launches without a separate enable switch. An empty selection leaves schedules and existing conversations available. With no matching subscription or launcher, messages receive no response.

Scheduled threads

Choose a server text or announcement channel. The opening-message template is limited to 2,000 characters. Use Add schedule on the integration page to post a template opening message and launch one profile in its new thread. Each schedule selects its own profile and destination channel, independently of mention settings. The tools, reply subscription and interaction handler are ready when the agent starts. Schedules can coexist with mention launches. See scheduled integration launches for setup, template variables and recovery behavior.

Thread tools and subscriptions

A mention or scheduled launch supplies read and post_message for its assigned thread. read supports before and limit; post_message takes content and an optional paths array of up to 10 files. Use exact /artifacts/<artifact_id> or /memory/<store>/<file> paths; directories and globs are not supported. For example, {"content":"Update","paths":["/memory/reports/weekly.pdf"]} posts the message and file directly to that thread. Omit paths for a text-only message. The model supplies neither channel nor thread IDs. Adding these tools to an agent without an assigned conversation is insufficient; calls fail before contacting Discord. post_message returns the message’s actual channel_id (the thread ID when posting in a thread), along with message_id and thread_id. The launcher subscribes the agent to replies. Posting does not change that subscription. To independently forward messages to an existing agent, send this body to the integration subscriptions API. This does not assign or change the conversation used by the integration’s tools.
Thread subscriptions need only thread_id; guild_id and the parent channel_id are optional. Supplied IDs are checked for valid format, but subscription creation does not verify them against Discord or retain them as routing restrictions. Create/list responses return only thread_id for a thread. For a channel subscription, supply channel_id and omit thread_id. Channel subscriptions receive mentioned thread starters, not ordinary replies in their threads. Removing the sending tool or changing config does not remove subscriptions. Use Stop forwarding on the integration page or DELETE the subscription to remove it, including while the integration is disconnected.

Questions, approvals and profile menus

Configure the integration’s public key, then set the Discord registration’s Interactions Endpoint URL to:
Use the numeric Discord Application ID, not Omnara’s itg_… ID. One public endpoint can verify callbacks for independently configured integrations. Each menu or agent interaction captures its owning integration, so its answer is routed only there. Require successful signed PING verification before offering profile menus or external approvals. For an agent assigned to the support integration’s thread, select interaction_handlers: {support: {}} in its config to expose the handler. For manual configs, also select list_interaction_handlers and set_interaction_handler under tools to let the model choose a destination. The Discord launcher adds the handler and both tools automatically, preserving explicit settings. The handler uses the thread assigned when the integration launches the agent. Select it with {"handler":"support","args":{}}; the model does not supply channel, thread or server IDs. The list tool shows the assigned destination. Adding a handler to a manual config does not create an assignment. With automatic selection enabled, the last eligible content input admitted into a new turn selects its handler. Inputs from the dashboard, API, or an integration without an eligible handler select dashboard-only delivery. Ordinary scheduled instructions and internal agent messages/reports without an integration origin preserve the selection. An explicit integration origin takes precedence, including a scheduled launch in a new thread. Waiting inputs do not change the current turn. Set auto_select: false with set_interaction_handler to pin a choice, or true to resume automatic selection; omission preserves the mode. The list tool reports the mode. Questions remain answerable in the dashboard if Discord presentation fails. There is no Gateway fallback for interaction answers or automatic slash-command registration. Discord interaction notifications run independently of the waiting agent. Delivery is best effort: overload can delay or drop notifications, and restarts can interrupt sending. Omnara retries only safe failures, with a bounded retry budget. If delivery may have succeeded, it does not automatically post another copy; a crash during sending can leave a prompt missing or unconfirmed. The interaction remains answerable in the dashboard and API regardless of delivery.

Restarts and deployments

An integration can retain its verified credentials while its Gateway connection is failing. The integration detail page shows the latest connection error and earliest retry time for the current setup and credential version. Refresh status rereads the recorded failure; it does not start a retry. The failure remains until a new attempt starts. After correcting the Discord settings, use Reconnect account to make the integration eligible for a new attempt without waiting for the old retry time. A missing error does not prove the Gateway is connected. The list and setup responses do not include this runtime status; API clients read the optional runtime_failure from Get integration. A worker saves its Discord session and last committed event sequence in Postgres. The event receipt and sequence are saved together. When another worker takes over, it resumes that session and Discord can replay missed events; repeated message receipts are deduplicated. A database lease prevents two workers from committing for the same saved integration. Normal shutdown releases that lease; after a crash, a replacement waits for it to expire, normally within 30 seconds. Keep replacement workers healthy during routine deployments, and allow the old workers to shut down gracefully. Postgres and Redis must remain available. Discord retains replay history for a limited time: a long outage or an invalidated session can still leave a gap. The worker records that it must start a fresh session; restarting is not a guarantee that Discord retains every missed message. HTTP interactions use the API service separately. Keep a healthy API instance receiving requests while another drains. Before a production rollout, use a dedicated test guild to check a mention, a plain reply in the resulting thread, and another reply after restarting the test worker. Confirm that they reach the same agent without duplicate inputs. Also verify a signed interaction callback if using approvals or profile menus. The automated suite uses local provider fixtures; it does not replace this live check of the bot’s intents and guild permissions.