t1385.7: Discord bot integration subagent doc#2765
Conversation
Create .agents/services/communications/discord.md covering: - Bot setup (Developer Portal, intents, OAuth2) - DM/guild/thread/forum messaging patterns - Slash commands with registration and handling - Interactive components v2 (buttons, selects, modals) - Role-based routing and channel-based routing - Access control (guild/channel/user/role allowlists) - Privacy/security assessment (no E2E, AI training warning) - aidevops runner dispatch integration - Matterbridge bridging notes - Voice channel integration - Deployment (PM2, systemd, Docker) Update subagent-index.toon and AGENTS.md domain index. Closes #2754
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces extensive documentation for integrating Discord bots, providing a detailed guide for developers on setting up, configuring, and deploying bots using discord.js. It also thoroughly addresses critical privacy and security considerations inherent to the Discord platform, offering recommendations for responsible usage, and integrates this new resource into the existing documentation structure. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Tue Mar 3 04:44:42 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
|
Accept worker versions for discord.md and msteams.md (already reviewed/merged). Keep our urbit.md (more detailed). Keep our AGENTS.md and subagent-index.toon (superset of all platforms).
There was a problem hiding this comment.
Code Review
This pull request introduces comprehensive documentation for Discord bot integration, a valuable addition to the subagent documentation. The new document is well-structured and covers a wide range of topics from setup to deployment and security. My review focuses on improving the code snippets within the documentation for correctness, security, and robustness, ensuring they are safe and runnable. I've identified a critical command injection vulnerability in one of the examples and provided a secure alternative, explicitly referencing the project's rule on avoiding command injection. Other comments address missing imports, unsafe use of non-null assertions, and minor inconsistencies, all of which align with best practices or are not contradicted by existing rules.
Note: Security Review is unavailable for this PR.
| import { execSync } from "node:child_process"; | ||
|
|
||
| async function dispatchToRunner( | ||
| runner: string, | ||
| prompt: string | ||
| ): Promise<string> { | ||
| // Sanitize prompt (remove potential injection) | ||
| const sanitized = prompt.replace(/[`$\\]/g, ""); | ||
|
|
||
| const result = execSync( | ||
| `runner-helper.sh dispatch "${runner}" "${sanitized}"`, | ||
| { | ||
| encoding: "utf-8", | ||
| timeout: 600_000, // 10 minutes | ||
| env: { ...process.env, RUNNER_TIMEOUT: "600" }, | ||
| } | ||
| ); | ||
|
|
||
| return result.trim(); | ||
| } |
There was a problem hiding this comment.
The current implementation is vulnerable to command injection. The sanitization on line 662 is insufficient and can be easily bypassed. Using execSync with interpolated strings is dangerous. A much safer approach is to use spawnSync and pass arguments in an array, which prevents the shell from interpreting special characters in the arguments.
import { spawnSync } from "node:child_process";
async function dispatchToRunner(
runner: string,
prompt: string
): Promise<string> {
const child = spawnSync(
"runner-helper.sh",
["dispatch", runner, prompt],
{
encoding: "utf-8",
timeout: 600_000, // 10 minutes
env: { ...process.env, RUNNER_TIMEOUT: "600" },
}
);
if (child.error) {
throw child.error;
}
if (child.status !== 0) {
// Note: stderr might contain sensitive info, handle with care in production
throw new Error(`Runner failed with exit code ${child.status}:\n${child.stderr}`);
}
return child.stdout.trim();
}References
- To avoid command injection vulnerabilities when constructing shell commands dynamically, do not use
eval. Instead, use a bash array to build the command and its arguments safely.
| const rest = new REST().setToken(process.env.DISCORD_BOT_TOKEN!); | ||
|
|
||
| // Register globally (takes up to 1 hour to propagate) | ||
| await rest.put(Routes.applicationCommands(process.env.DISCORD_APP_ID!), { | ||
| body: commands, | ||
| }); | ||
|
|
||
| // Or register per-guild (instant, good for development) | ||
| await rest.put( | ||
| Routes.applicationGuildCommands( | ||
| process.env.DISCORD_APP_ID!, | ||
| "GUILD_ID" | ||
| ), | ||
| { body: commands } | ||
| ); |
There was a problem hiding this comment.
Using non-null assertion operators (!) for environment variables can lead to runtime errors if they are not set. It's safer to check for their existence and throw an error, similar to the "Minimal Bot" example. Additionally, hardcoded values like "GUILD_ID" should be sourced from variables to make the example more practical.
Here is a safer implementation pattern:
const token = process.env.DISCORD_BOT_TOKEN;
const appId = process.env.DISCORD_APP_ID;
const guildId = process.env.DISCORD_GUILD_ID; // For guild-specific commands
if (!token || !appId) {
throw new Error("DISCORD_BOT_TOKEN and/or DISCORD_APP_ID must be set.");
}
const rest = new REST().setToken(token);
// Example for global registration
await rest.put(Routes.applicationCommands(appId), {
body: commands,
});
// Example for guild-specific registration
if (guildId) {
await rest.put(
Routes.applicationGuildCommands(appId, guildId),
{ body: commands }
);
}| ```typescript | ||
| // Post to a forum channel | ||
| const forum = await client.channels.fetch("FORUM_CHANNEL_ID"); | ||
| if (forum?.type === ChannelType.GuildForum) { |
| function resolveRunner( | ||
| interaction: ChatInputCommandInteraction, | ||
| config: BotConfig | ||
| ): string { | ||
| // 1. Explicit runner choice from command option | ||
| const explicit = interaction.options.getString("runner"); | ||
| if (explicit) return explicit; | ||
|
|
||
| // 2. Channel-based routing | ||
| const channelName = (interaction.channel as TextChannel)?.name; | ||
| if (channelName && config.channelRouting[channelName]) { | ||
| return config.channelRouting[channelName]; | ||
| } | ||
|
|
||
| // 3. Role-based routing (highest role wins) | ||
| const member = interaction.member as GuildMember; | ||
| for (const [roleName, runner] of Object.entries(config.roleRouting)) { | ||
| if (member.roles.cache.some((r) => r.name === roleName)) { | ||
| return runner; | ||
| } | ||
| } | ||
|
|
||
| // 4. Default | ||
| return config.defaultRunner; | ||
| } |
There was a problem hiding this comment.
This code snippet is missing several imports and type definitions which would prevent it from running. ChatInputCommandInteraction, TextChannel, and GuildMember should be imported from discord.js. The BotConfig type also needs to be defined for this example to be complete.
Here's an example of what's missing:
import { ChatInputCommandInteraction, GuildMember, TextChannel } from "discord.js";
// Assuming BotConfig is defined similar to the JSON example above
interface BotConfig {
channelRouting: { [key: string]: string };
roleRouting: { [key: string]: string };
defaultRunner: string;
// ... other properties
}| function checkAccess( | ||
| interaction: ChatInputCommandInteraction, | ||
| config: BotConfig | ||
| ): boolean { | ||
| const member = interaction.member as GuildMember; | ||
|
|
||
| // Guild allowlist (if configured) | ||
| if (config.allowedGuilds?.length) { | ||
| if (!config.allowedGuilds.includes(interaction.guildId!)) return false; | ||
| } | ||
|
|
||
| // Channel allowlist (if configured) | ||
| if (config.allowedChannels?.length) { | ||
| if (!config.allowedChannels.includes(interaction.channelId)) return false; | ||
| } | ||
|
|
||
| // User allowlist (if configured) | ||
| if (config.allowedUsers?.length) { | ||
| if (!config.allowedUsers.includes(interaction.user.id)) return false; | ||
| } | ||
|
|
||
| // Role allowlist (user must have at least one allowed role) | ||
| if (config.allowedRoles?.length) { | ||
| const hasRole = config.allowedRoles.some((roleName) => | ||
| member.roles.cache.some((r) => r.name === roleName) | ||
| ); | ||
| if (!hasRole) return false; | ||
| } | ||
|
|
||
| return true; | ||
| } |
There was a problem hiding this comment.
This code snippet is also missing necessary imports and type definitions. ChatInputCommandInteraction and GuildMember need to be imported from discord.js, and the BotConfig type needs to be defined for the example to be complete and understandable.
Here's an example of what's missing:
import { ChatInputCommandInteraction, GuildMember } from "discord.js";
// Assuming BotConfig is defined similar to the JSON example
interface BotConfig {
allowedGuilds?: string[];
allowedChannels?: string[];
allowedUsers?: string[];
allowedRoles?: string[];
}| | SEO | `seo/dataforseo.md`, `seo/google-search-console.md` | | ||
| | WordPress | `tools/wordpress/wp-dev.md`, `tools/wordpress/mainwp.md` | | ||
| | Communications | `services/communications/matterbridge.md`, `services/communications/simplex.md`, `services/communications/matrix-bot.md`, `services/communications/bitchat.md`, `services/communications/xmtp.md` | | ||
| | Communications | `services/communications/matterbridge.md`, `services/communications/discord.md`, `services/communications/simplex.md`, `services/communications/matrix-bot.md`, `services/communications/bitchat.md`, `services/communications/xmtp.md` | |
There was a problem hiding this comment.
For better readability and long-term maintainability, it's a good practice to keep lists of files sorted alphabetically.
| | Communications | `services/communications/matterbridge.md`, `services/communications/discord.md`, `services/communications/simplex.md`, `services/communications/matrix-bot.md`, `services/communications/bitchat.md`, `services/communications/xmtp.md` | | |
| | Communications | `services/communications/bitchat.md`, `services/communications/discord.md`, `services/communications/matrix-bot.md`, `services/communications/matterbridge.md`, `services/communications/simplex.md`, `services/communications/xmtp.md` | |
| │ Browser) │ │ │ │ │ | ||
| │ │────▶│ Events: │────▶│ 1. Parse event │ | ||
| │ User sends: │ │ - messageCreate │ │ 2. Check perms │ | ||
| │ /ask Review auth │ │ - interactionCr. │ │ 3. Route command │ |
There was a problem hiding this comment.
| Type=simple | ||
| User=discord-bot | ||
| WorkingDirectory=/opt/discord-bot | ||
| ExecStart=/usr/bin/node --import tsx src/bot.ts |
There was a problem hiding this comment.
While using node --import tsx is valid, a simpler and more direct approach is to use tsx as the executable. This would also be more consistent with the pm2 example which uses tsx as an interpreter. It's also more robust to use a relative path to the tsx executable within node_modules to ensure the correct one is used.
| ExecStart=/usr/bin/node --import tsx src/bot.ts | |
| ExecStart=/opt/discord-bot/node_modules/.bin/tsx src/bot.ts |
| COPY package*.json ./ | ||
| RUN npm ci --omit=dev | ||
| COPY . . | ||
| CMD ["node", "--import", "tsx", "src/bot.ts"] |
There was a problem hiding this comment.
Similar to the systemd example, it's simpler and more direct to use tsx as the executable instead of node --import tsx. Using a relative path to the executable in node_modules is also more robust.
| CMD ["node", "--import", "tsx", "src/bot.ts"] | |
| CMD ["./node_modules/.bin/tsx", "src/bot.ts"] |
| services/networking/,Networking - mesh VPN and secure device connectivity,tailscale|netbird | ||
| services/email/,Email services - transactional email deliverability testing and autonomous mission communication,ses|email-agent|email-health-check|email-testing|email-delivery-test|email-design-test|email-delivery-testing|email-design-testing | ||
| services/communications/,Communications - SMS voice Matrix bot multi-platform chat bridging Bluetooth mesh and Web3 messaging,twilio|telfon|matrix-bot|matterbridge|simplex|bitchat|xmtp | ||
| services/communications/,Communications - SMS voice Matrix bot Discord bot multi-platform chat bridging Bluetooth mesh and Web3 messaging,twilio|telfon|matrix-bot|discord|matterbridge|simplex|bitchat|xmtp |
There was a problem hiding this comment.
For better readability and maintainability, it's good practice to keep the keywords sorted alphabetically. The description could also be slightly improved by ordering the bot types consistently.
services/communications/,Communications - SMS voice, Discord bot, Matrix bot, multi-platform chat bridging, Bluetooth mesh and Web3 messaging,bitchat|discord|matrix-bot|matterbridge|simplex|telfon|twilio|xmtp



Summary
.agents/services/communications/discord.md— comprehensive subagent doc for Discord bot integration using discord.jssubagent-index.toonandAGENTS.mddomain index to include the new discord entryWhat's Covered
Privacy Assessment
The doc includes an explicit warning that Discord stores all messages server-side with no E2E encryption, Discord's privacy policy permits AI/ML usage of data, and recommends using Matrix or SimpleX for sensitive communications.
Closes #2754