# discord The `discord` extension gives a session its own Discord bot. Messages the bot may see reach the session through the daemon's event inbox (the same durable `mail` table and dispatcher webhooks use), and the session answers through the `discord` binding in its kernel. The extension is installed but **disabled by default**; enable it globally in `/extensions` to run bots and mount its HTTP service. A bot whose extension is off globally does not connect and reports state `disabled`. The table initialiser only creates storage. Its `StartupPlugin` starts the bot manager after the extension schema transaction commits, before runtime readiness. ## Setup 1. In the Discord developer portal, create an application, open **Bot**, press **Reset Token** and copy the token. On the same page enable the **Message Content** intent; without it the gateway closes with 4014 and the bot fails with that reason. 2. Open the Discord page (`/discord`), press `ctrl+o`, and give the bot a name (1–64 characters), the session it belongs to (one bot per session), the token, and your own Discord user ID. To copy your ID, turn on Settings → Advanced → Developer Mode, then right-click yourself → Copy User ID. You, the owner, can always DM the bot. 3. Invite the bot with the page's invite URL (`ctrl+l` copies it): `https://discord.com/oauth2/authorize?client_id=&scope=bot&permissions=274878024768`, which grants View Channel, Send Messages, Embed Links, Attach Files, Read Message History, Add Reactions and Send Messages in Threads. Before the bot's first READY, the application id is read from the token's first segment. 4. On the bot's Channels pane, choose what each channel delivers. Channels start **off**. The token never leaves the daemon except into the bot process's environment. Listings and the kernel never include it. ## Channels and delivery A `discord_channels` row means the bot sees that channel; no row means off. Each row sets a delivery: - `turn` (end of turn): a message waits for a running turn to end, then everything that waited starts the next turn together. An idle session starts a turn at once. - `tool` (after tool call): a message steers a running turn after its current tool call, or starts a turn when idle. `mentions_only` delivers only messages that mention the bot user (`@everyone` does not count). Threads follow their parent channel's row. DMs are always delivered after the current tool call. Other bots' messages are delivered like anyone's: other people's albedos live in these channels. There are no cooldowns. The bot's own messages are never delivered. ## DM whitelist The owner and the people on the bot's allowed list may DM it. A DM from anyone else stores no letter; it creates or updates a **request** (username, a 200-character preview, last time, count; at most 50 per bot, oldest dropped). The DMs pane lists the owner, the allowed people, and the requests; allowing a request (`PUT .../dms/{user_id}`) removes it, and when no name is given and the bot is online the daemon looks the person's display name up. The owner cannot be removed. ## Ingest rules For every message the bot process reports, in one store transaction: 1. The channel's cursor (newest message id seen, compared as integers) moves forward, for configured guild channels and their threads and for whitelisted DM channels. 2. A message from the bot user is ignored. 3. A DM from the owner or an allowed person becomes an `Event(AfterTool)` letter; any other DM becomes a request. 4. A guild message uses the row for its channel, else for its parent channel. Without one it is ignored. With `mentions_only` and no mention of the bot it is ignored. Otherwise it becomes `Event(AfterTool)` for `tool` and `Event(AfterTurn)` for `turn`. 5. The channel and the message are numbered (below). The letter id is `discord--`; a message whose letter exists already (a catch-up replay) stores nothing. Sender name is `discord`. The letter body, which mail wraps as ``: ``` [discord # in · c] @ (, bot) · message [ · reply to ] ·