Agent skill
discord-bot-architect
Specialized skill for building production-ready Discord bots. Covers Discord.js (JavaScript) and Pycord (Python), gateway intents, slash commands, interactive components, rate limiting, and sharding.
Install this agent skill to your Project
npx add-skill https://github.com/aiskillstore/marketplace/tree/main/skills/sickn33/discord-bot-architect
SKILL.md
Discord Bot Architect
Patterns
Discord.js v14 Foundation
Modern Discord bot setup with Discord.js v14 and slash commands
When to use: ['Building Discord bots with JavaScript/TypeScript', 'Need full gateway connection with events', 'Building bots with complex interactions']
```javascript
// src/index.js
const { Client, Collection, GatewayIntentBits, Events } = require('discord.js');
const fs = require('node:fs');
const path = require('node:path');
require('dotenv').config();
// Create client with minimal required intents
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
// Add only what you need:
// GatewayIntentBits.GuildMessages,
// GatewayIntentBits.MessageContent, // PRIVILEGED - avoid if possible
]
});
// Load commands
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(f => f.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
if ('data' in command && 'execute' in command) {
client.commands.set(command.data.name, command);
}
}
// Load events
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(f => f.endsWith('.js'));
for (const file of eventFiles) {
const filePath = path.join(eventsPath, file);
const event = require(filePath);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
client.login(process.env.DISCORD_TOKEN);
// src/commands/ping.js
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Replies with Pong!'),
async execute(interaction) {
const sent = await interaction.reply({
content: 'Pinging...',
fetchReply: true
});
const latency = sent.createdTimestamp - interaction.createdTimestamp;
await interaction.editReply(`Pong! Latency: ${latency}ms`);
}
};
// src/events/interactionCreate.js
const { Events } = require('discord.js');
module.exports = {
name: Event
Pycord Bot Foundation
Discord bot with Pycord (Python) and application commands
When to use: ['Building Discord bots with Python', 'Prefer async/await patterns', 'Need good slash command support']
```python
# main.py
import os
import discord
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
# Configure intents - only enable what you need
intents = discord.Intents.default()
# intents.message_content = True # PRIVILEGED - avoid if possible
# intents.members = True # PRIVILEGED
bot = commands.Bot(
command_prefix="!", # Legacy, prefer slash commands
intents=intents
)
@bot.event
async def on_ready():
print(f"Logged in as {bot.user}")
# Sync commands (do this carefully - see sharp edges)
# await bot.sync_commands()
# Slash command
@bot.slash_command(name="ping", description="Check bot latency")
async def ping(ctx: discord.ApplicationContext):
latency = round(bot.latency * 1000)
await ctx.respond(f"Pong! Latency: {latency}ms")
# Slash command with options
@bot.slash_command(name="greet", description="Greet a user")
async def greet(
ctx: discord.ApplicationContext,
user: discord.Option(discord.Member, "User to greet"),
message: discord.Option(str, "Custom message", required=False)
):
msg = message or "Hello!"
await ctx.respond(f"{user.mention}, {msg}")
# Load cogs
for filename in os.listdir("./cogs"):
if filename.endswith(".py"):
bot.load_extension(f"cogs.{filename[:-3]}")
bot.run(os.environ["DISCORD_TOKEN"])
# cogs/general.py
import discord
from discord.ext import commands
class General(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.slash_command(name="info", description="Bot information")
async def info(self, ctx: discord.ApplicationContext):
embed = discord.Embed(
title="Bot Info",
description="A helpful Discord bot",
color=discord.Color.blue()
)
embed.add_field(name="Servers", value=len(self.bot.guilds))
embed.add_field(name="Latency", value=f"{round(self.bot.latency * 1000)}ms")
await ctx.respond(embed=embed)
@commands.Cog.
Interactive Components Pattern
Using buttons, select menus, and modals for rich UX
When to use: ['Need interactive user interfaces', 'Collecting user input beyond slash command options', 'Building menus, confirmations, or forms']
```javascript
// Discord.js - Buttons and Select Menus
const {
SlashCommandBuilder,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
StringSelectMenuBuilder,
ModalBuilder,
TextInputBuilder,
TextInputStyle
} = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('menu')
.setDescription('Shows an interactive menu'),
async execute(interaction) {
// Button row
const buttonRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('confirm')
.setLabel('Confirm')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('cancel')
.setLabel('Cancel')
.setStyle(ButtonStyle.Danger),
new ButtonBuilder()
.setLabel('Documentation')
.setURL('https://discord.js.org')
.setStyle(ButtonStyle.Link) // Link buttons don't emit events
);
// Select menu row (one per row, takes all 5 slots)
const selectRow = new ActionRowBuilder()
.addComponents(
new StringSelectMenuBuilder()
.setCustomId('select-role')
.setPlaceholder('Select a role')
.setMinValues(1)
.setMaxValues(3)
.addOptions([
{ label: 'Developer', value: 'dev', emoji: '💻' },
{ label: 'Designer', value: 'design', emoji: '🎨' },
{ label: 'Community', value: 'community', emoji: '🎉' }
])
);
await interaction.reply({
content: 'Choose an option:',
components: [buttonRow, selectRow]
});
// Collect responses
const collector = interaction.channel.createMessageComponentCollector({
filter: i => i.user.id === interaction.user.id,
time: 60_000 // 60 seconds timeout
});
collector.on('collect', async i => {
if (i.customId === 'confirm') {
await i.update({ content: 'Confirmed!', components: [] });
collector.stop();
} else if (i.custo
Anti-Patterns
❌ Message Content for Commands
Why bad: Message Content Intent is privileged and deprecated for bot commands. Slash commands are the intended approach.
❌ Syncing Commands on Every Start
Why bad: Command registration is rate limited. Global commands take up to 1 hour to propagate. Syncing on every start wastes API calls and can hit limits.
❌ Blocking the Event Loop
Why bad: Discord gateway requires regular heartbeats. Blocking operations cause missed heartbeats and disconnections.
⚠️ Sharp Edges
| Issue | Severity | Solution |
|---|---|---|
| Issue | critical | ## Acknowledge immediately, process later |
| Issue | critical | ## Step 1: Enable in Developer Portal |
| Issue | high | ## Use a separate deploy script (not on startup) |
| Issue | critical | ## Never hardcode tokens |
| Issue | high | ## Generate correct invite URL |
| Issue | medium | ## Development: Use guild commands |
| Issue | medium | ## Never block the event loop |
| Issue | medium | ## Show modal immediately |
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
perigon-backend
Perigon ASP.NET Core + EF Core + Aspire conventions
perigon-agent
Pointers for Copilot/agents to apply Perigon conventions
perigon-angular
Angular 21+ standalone/Material/signal conventions for Perigon WebApp
fastapi-mastery
Comprehensive FastAPI development skill covering REST API creation, routing, request/response handling, validation, authentication, database integration, middleware, and deployment. Use when working with FastAPI projects, building APIs, implementing CRUD operations, setting up authentication/authorization, integrating databases (SQL/NoSQL), adding middleware, handling WebSockets, or deploying FastAPI applications. Triggered by requests involving .py files with FastAPI code, API endpoint creation, Pydantic models, or FastAPI-specific features.
context7-efficient
Token-efficient library documentation fetcher using Context7 MCP with 86.8% token savings through intelligent shell pipeline filtering. Fetches code examples, API references, and best practices for JavaScript, Python, Go, Rust, and other libraries. Use when users ask about library documentation, need code examples, want API usage patterns, are learning a new framework, need syntax reference, or troubleshooting with library-specific information. Triggers include questions like "Show me React hooks", "How do I use Prisma", "What's the Next.js routing syntax", or any request for library/framework documentation.
browser-use
Browser automation using Playwright MCP. Navigate websites, fill forms, click elements, take screenshots, and extract data. Use when tasks require web browsing, form submission, web scraping, UI testing, or any browser interaction.
Didn't find tool you were looking for?