Discord
The Discord bot is a transport for the operator Chat and Intake. It does not run a second agent: a mention, or any human message in a conversation channel, becomes a normal Chat turn on this agent, with the same memory, retrieve, tools, and work intents.
What it does
Section titled “What it does”- @mention → Chat. Mention the bot in a channel or thread. It answers in the same channel, as a reply to the mention.
- Conversation channels → Chat when addressed. List a channel in
discord_conversation_channelsand the bot joins the conversation. Clef decides whether each human message is addressed to it or continues its last reply; human-to-human messages, announcements, and unrelated chatter are ignored. The session persists, so follow-ups keep their context. A direct Discord reply to one of the bot’s messages counts as addressed and bypasses the classifier. This needs the privileged Message Content intent and acloudflare_aicredential. - 📥 → Intake. A reply that proposes work (a bug, feature, backlog item, or a suggested issue) carries 📥. An operator who reacts with 📥 files the original message and the assistant reply as an Intake item. The item keeps the Discord message link, the author, and the reply as provenance. Plain answers, status checks, greetings, and Decision drafts do not carry 📥.
- One Chat session per channel or thread. A thread is a separate session from its parent channel, so use a thread for a side conversation.
The bot ignores its own messages, other bots, reactions from bots, and
messages that neither mention it nor arrive in a conversation channel (except
DMs when discord_allow_dms=1).
- Create a Discord application and bot in the Developer Portal.
- Invite the bot with View Channel, Send Messages, Read Message History, Add Reactions, and Send Messages in Threads.
- Store the bot token as the
discord_botcredential (Credentials → Discord bot). - Optionally set
discord_allowed_channelsanddiscord_allowed_usersto comma-separated IDs. Empty means every channel/user the bot can see.
Mention-only operation needs no privileged intents: Discord delivers the
content of messages that mention the bot. For conversation mode, enable
Message Content under Bot → Privileged Gateway Intents, configure
cloudflare_ai (or CLOUDFLARE_ACCOUNT_ID/CLOUDFLARE_API_TOKEN), then set
discord_conversation_channels to the channel IDs. Without the classifier,
conversation mode ignores non-mention messages rather than replying to
everything.
The agent starts the gateway when a token is present and
discord_bot_enabled is not 0. No public URL or interactions endpoint is
needed; the bot uses Discord’s outbound gateway connection.
One bot per agent
Section titled “One bot per agent”Each agent runs its own project. Use a separate Discord application and token
for each one, and scope it to that project’s channels with
discord_allowed_channels:
| Agent | Bot | Channels |
|---|---|---|
| Steelframe dogfood | Steelframe | #steelframe, #dogfood |
| Steelframe makolate | Steelframe Makolate | #makolate, #86, #makolate-steelframe |
The dogfood and makolate agents have separate databases and credentials, so a
mention in #dogfood never reaches the makolate agent. The bot name and avatar
are set in Discord; they are not agent config.
Configuration
Section titled “Configuration”| Key | Default | Purpose |
|---|---|---|
discord_bot_enabled | 1 | 0 turns the bot off even with a token. |
discord_allowed_channels | empty | Comma-separated channel or thread IDs the bot answers in. |
discord_allowed_users | empty | Comma-separated Discord user IDs allowed to use the bot. |
discord_conversation_channels | empty | Channel IDs where Clef decides whether each human message is for the bot. Requires Message Content and cloudflare_ai. |
discord_intake_reaction | 📥 | Emoji that files an Intake. |
discord_allow_dms | 0 | 1 also answers direct messages (no mention required). |
STEELFRAME_DISCORD_BOT_TOKEN is a local-testing fallback when the credential
is not stored.
Empty allowlists are an open posture: any member who can mention the bot
can drive operator Chat. Conversation mode is stronger still: a message Clef
judges addressed to the bot runs a Chat turn, so a misclassification can spend
a worker. Set at least discord_allowed_channels and
discord_allowed_users for an operator agent. The agent logs a warning at
startup when either allowlist is empty or conversation mode is on.
Behavior notes
Section titled “Behavior notes”- Discord shows Steelframe is typing… while the Chat turn runs; the indicator is refreshed every ~8 seconds and cleared when the reply is sent.
- In a mention-only channel, each reply ends with a one-line reminder to mention the bot. In a conversation channel, replies have no reminder: the next addressed message continues the session.
- Conversation mode is not reply-to-everything. Clef scores whether a message is addressed to the bot or continues its last reply; below the threshold the message is ignored. If the classifier is unavailable, non-mention messages are ignored; mention the bot to force an answer.
- Chat first. While a Chat turn is running, the agent defers new background worker assignments. An incident burst can still slow the model, but it cannot take the remaining worker slots from the operator’s reply.
- A Chat turn can take as long as the coding runtime takes. The bot replies once the turn finishes; it does not stream tokens into a message.
- Discord replies are a chat answer, not a report: the prompt asks for at most ~900 characters and the bot trims a runaway answer at a sentence or word boundary at 1,500. The trailing ellipsis means there is more to ask for; the TUI/GUI Chat is not capped.
- The bot does not file an Intake automatically. The reaction is the operator’s confirmation, which keeps a chat question from becoming work by accident.
- Attachments are not read yet; the message text is. A mention with only an attachment gets a reply asking for words.