You want to create a Discord bot that uses slash commands instead of traditional prefix-based commands. Slash commands appear in the user interface and provide autocomplete, required options, and permission controls. This article walks through building a basic bot with Python 3.8 or later using the discord.py 2.0 library. You will learn how to set up your bot token, write a command group, and deploy the bot to a server.
Key Takeaways: Building a Slash Command Bot with discord.py 2.0
- discord.py 2.0
app_commandsmodule: Replaces the deprecatedcommands.Botwithcommands.Botthat supports slash commands natively. @bot.tree.command()decorator: Registers a slash command that appears in the Discord UI with autocomplete and option validation.bot.tree.sync()method: Uploads your command definitions to Discord servers so they appear in the command list.
What Is discord.py 2.0 and How Slash Commands Work
discord.py 2.0 is a major update to the popular Python library for interacting with the Discord API. The library now supports Application Commands, which include slash commands, user context menu commands, and message context menu commands. Slash commands are commands that users type with a forward slash and are defined in code rather than parsed from a message prefix like ! or ..
When a user types a slash command, Discord sends an interaction event to your bot. Your bot receives the interaction, processes it, and responds within three seconds. For longer processing, you can defer the response and then send a follow-up. The discord.app_commands module handles parsing of options, autocomplete, and permission checks automatically.
Prerequisites for This Tutorial
Before you start, you need the following:
- Python 3.8 or later installed on your computer
- A Discord account and a server where you have the Manage Server permission
- A Discord application created at the Discord Developer Portal
- The bot token from the Developer Portal
- The bot invited to your server with the
applications.commandsscope
Steps to Create and Run a Slash Command Bot
Follow these steps to build a bot that responds to /hello with a greeting.
- Install discord.py 2.0
Open a terminal and runpip install -U discord.py. Verify the version withpip show discord.py. The version should be 2.0.0 or later. - Create a Python file for the bot
Create a file namedbot.pyand open it in a code editor. Write the import statements at the top:import discordandfrom discord.ext import commands. - Define the bot instance with intents
Write the following code to create a bot instance. Intents are required for the bot to receive events. For slash commands, you need at least the default intents.intents = discord.Intents.default()bot = commands.Bot(command_prefix='/', intents=intents) - Add an event for when the bot is ready
Write anon_readyevent that prints a message when the bot connects. This confirms the bot is online.@bot.eventasync def on_ready():print(f'Logged in as {bot.user}') - Create a slash command using the tree
Use the@bot.tree.commanddecorator to define a slash command namedhello. The function name becomes the command name unless you specify anameparameter.@bot.tree.command(name="hello", description="Says hello")async def hello(interaction: discord.Interaction):await interaction.response.send_message(f"Hello, {interaction.user.mention}!") - Sync the command tree
After defining commands, callbot.tree.sync()inside theon_readyevent or in a separate setup function. This uploads the command definitions to Discord servers. The bot must be in a server for the commands to appear.@bot.eventasync def on_ready():await bot.tree.sync()print(f'Logged in as {bot.user}') - Run the bot with your token
At the bottom of the file, addbot.run('YOUR_BOT_TOKEN'). ReplaceYOUR_BOT_TOKENwith the actual token from the Developer Portal. Do not share this token. - Start the bot
Runpython bot.pyin the terminal. You should see the logged-in message. Open Discord and type/helloin any channel where the bot has access. The bot should reply with a greeting.
Common Issues When Building Slash Command Bots
Commands Do Not Appear in Discord
The most common cause is that the command tree has not been synced. Make sure you call await bot.tree.sync() after all commands are defined. If you add or remove commands later, you must sync again. Also verify that the bot has the applications.commands scope when you invite it. Use the OAuth2 URL generator in the Developer Portal and select the bot and applications.commands scopes.
Bot Does Not Respond to Slash Commands
Check that your bot is online in the Discord server member list. If the bot is online but does not respond, the interaction may be timing out. Discord expects a response within three seconds. If your code takes longer, use await interaction.response.defer() first, then send a follow-up with await interaction.followup.send(). Also check that your bot has the necessary permissions in the channel.
Slash Command Options Not Working
When you add options to a slash command, use the @app_commands.describe() decorator or pass parameters directly. For example:@bot.tree.command(name="greet", description="Greets a user")@app_commands.describe(user="The user to greet")async def greet(interaction: discord.Interaction, user: discord.Member): await interaction.response.send_message(f"Hello, {user.mention}!")
Options must have type hints such as str, int, discord.Member, or discord.Role. If the type is wrong, the command will not register.
Commands Work Locally but Not After Hosting
If you move your bot to a cloud server, ensure the Python environment has discord.py 2.0 installed. Also check that the bot token is set as an environment variable rather than hardcoded. Use os.getenv('DISCORD_TOKEN') to read the token from the environment. This prevents accidental exposure.
Comparison: discord.py 2.0 Slash Commands vs Traditional Prefix Commands
| Feature | Slash Commands (discord.py 2.0) | Traditional Prefix Commands |
|---|---|---|
| User interface | Shows in command list with autocomplete and descriptions | No UI, users must remember the prefix and command name |
| Permission control | Can require specific permissions per command, enforced by Discord | Must check permissions manually in code |
| Input validation | Options are typed and validated by Discord before sending to bot | Bot must parse and validate arguments from message text |
| Latency | Interaction must be acknowledged within 3 seconds, then follow-up allowed | Bot can take as long as needed to process and reply |
| Global availability | Commands sync globally but may take up to an hour to appear in all servers | Commands are available immediately after bot starts |
You now have a working Discord bot that uses slash commands. The next step is to add more commands with options and autocomplete. You can also create groups of commands using @bot.tree.command(guild=discord.Object(id=GUILD_ID)) to test commands in a single server before making them global. Use the discord.app_commands documentation to explore advanced features like context menus and cooldowns.