A Discord bot that answers questions about your Appwrite projects, such as why a deployment failed or how many users signed up this week. It runs on two Appwrite Functions, so there is no server to keep online. Each Discord user links their own Appwrite account with Sign in with Appwrite, and the bot reads only the projects that user approved.
The model is GPT-6 Luna through OpenRouter.
- Discord sends every command to the
discord-interactionsfunction over HTTP. - That function checks Discord's signature, queues the
stackbot-agentfunction, and answers Discord with "Stackbot is thinking..." inside the three-second limit. stackbot-agentruns the command and edits the reply when it is done.
/stackbot connect: links your Appwrite account with the device flow./stackbot ask question:<text>: answers a question with the model and read-only project tools./stackbot disconnect: revokes the grant and deletes the stored tokens.- Ask Stackbot (message menu): asks about the message you right-clicked, for example a pasted error.
Replies are ephemeral, so only the person who asked can see project data.
functions/discord-interactions: checks signatures, answers PING, queues the agent, defers the reply.functions/stackbot-agent/src/main.js: runs one queued command and edits the Discord reply.functions/stackbot-agent/src/commands/: one file per command (connect,ask,disconnect).functions/stackbot-agent/src/sign-in-with-appwrite.js: device flow, token refresh, revocation, granted project list.functions/stackbot-agent/src/connections.js: encrypted token storage in TablesDB and safe token refresh.functions/stackbot-agent/src/project-tools.js: the read-only tools the model can call.functions/stackbot-agent/src/agent.js: the OpenRouter tool loop.functions/stackbot-agent/src/discord.js: edits the deferred Discord reply.scripts/register-commands.js: registers the commands with Discord.appwrite.config.json: both functions forappwrite push functions.
- Create a Discord application in the Discord Developer Portal. Copy the application ID and public key, and reset the bot token on the Bot page.
- In the Appwrite Console, open your organization's Marketplace tab, select Create app, turn on Device flow on the OAuth client page, and create a secret on OAuth secrets.
- Create a TablesDB database with a
connectionstable. Add three required columns:accessToken(text, encrypted),refreshToken(text, encrypted), andexpiresAt(datetime). - Set
projectIdandendpointinappwrite.config.json, then runappwrite push functions. - Set these variables and redeploy both functions:
| Function | Variable | Value |
|---|---|---|
| discord-interactions | DISCORD_PUBLIC_KEY |
The public key from the Discord application |
| discord-interactions | AGENT_FUNCTION_ID |
stackbot-agent |
| stackbot-agent | DATABASE_ID |
The database ID |
| stackbot-agent | APPWRITE_CONSOLE_ENDPOINT |
https://cloud.appwrite.io/v1 |
| stackbot-agent | APPWRITE_CLIENT_ID |
The client ID of the Appwrite app |
| stackbot-agent | APPWRITE_CLIENT_SECRET |
The OAuth secret of the Appwrite app |
| stackbot-agent | OPENROUTER_API_KEY |
Your OpenRouter API key |
| stackbot-agent | OPENROUTER_MODEL |
Optional, default openai/gpt-6-luna |
-
Paste the
discord-interactionsfunction domain into Interactions Endpoint URL on the Discord application's General Information page. Discord checks the URL before it saves it, so redeploy after settingDISCORD_PUBLIC_KEY. -
Register the commands:
DISCORD_APPLICATION_ID=<id> DISCORD_BOT_TOKEN=<token> node scripts/register-commands.js
-
On the Installation page, add the
botscope next toapplications.commands, invite the bot with the install link, then run/stackbot connect.