2025, Oct 27 13:00
How to Enable Discord Bot Commands in DMs and Group DMs with Slash Commands and User Install
Fix DM commands that silently fail. Learn to use slash commands, User Install, and allowed_contexts to run a Discord bot in DMs and GDMs with discord.py 2.4
Building a Discord bot that works in DMs seems straightforward until you try to use it inside a private chat with another user. Classic prefix commands behave differently across contexts, and without the right setup your command will quietly do nothing in a two-person DM or a Group DM. Here is how to make it work correctly using the mechanisms Discord actually supports.
What breaks in the DM scenario
Consider a simple command that should only run in DMs. It logs who invoked it, picks a value, and replies. Everything looks fine, but it won’t trigger inside a DM thread with another user.
@core.command()
@commands.dm_only()
async def purr(ev: discord.ApplicationContext):
    audit.info(f"{ev.author} meows")
    max_count=len(catlines)
    idx=random.randint(1,max_count)
    msg=catlines[idx][0]
    audit.info(msg)
    await ev.send(msg)
Even though the command is restricted to DMs, invoking it in a private conversation with a friend will result in no visible action.
Why it happens
The behavior stems from how Discord exposes interactions in direct and group conversations. Using standard commands is not enough to make a bot usable inside user-to-user DMs or GDMs. This is only possible via slash commands combined with a feature that lets a user install the app to their profile so they can invoke it anywhere. In other words, the context and installation model matter as much as the command itself.
The correct approach
Starting with discord.py 2.4+, slash commands can be enabled for DMs and Group DMs when two things are in place. First, allow the command to be installed to a user profile. Second, explicitly permit execution in DM and GDM contexts. GDMs are referred to as private_channels. Below is the minimal setup:
@discord.app_commands.allowed_installs(guilds=False, users=True)
@discord.app_commands.allowed_contexts(guilds=False, dms=True, private_channels=True)
@app.tree.command()
async def purr(inter):
    ...
To complete the flow, enable “User Install” in the “Installation” tab of your application in the Developer Portal. That exposes the “Add to My Apps” option during authorization, which is required for user-level installs. Official references are available for @discord.app_commands.allowed_installs and @discord.app_commands.allowed_contexts.
Putting it all together
Switch the interaction style to slash commands, allow user installs, and open up the command contexts. Here is an adjusted version that mirrors the earlier logic while being invokable in DMs and GDMs once installed by the user:
@discord.app_commands.allowed_installs(guilds=False, users=True)
@discord.app_commands.allowed_contexts(guilds=False, dms=True, private_channels=True)
@app.tree.command()
async def purr(inter):
    audit.info(f"{inter.user} meows")
    max_count=len(catlines)
    idx=random.randint(1,max_count)
    msg=catlines[idx][0]
    audit.info(msg)
    await inter.response.send_message(msg)
After enabling “User Install” in the Developer Portal and reauthorizing the app with that scope, the slash command becomes available directly in a DM with another person or inside a GDM, depending on where the user invokes it.
Why this matters for your bot architecture
DM and GDM availability is not just a toggle; it is a capability tied to Discord’s slash command system and the user installation flow. If your product requires private interactions outside servers, design your commands as app commands and control where they are installable and executable. This approach keeps behavior predictable across contexts and avoids silent failures.
Takeaways
If a command works in a one-on-one DM with the bot but not in a DM with another person, move to slash commands and enable user installs. Configure @discord.app_commands.allowed_installs with user-level installs and set @discord.app_commands.allowed_contexts to permit DMs and private_channels. Turn on “User Install” in the Dev Portal. With these pieces aligned, your bot’s features become consistently available in private conversations where users expect them.
The article is based on a question from StackOverflow by Firemix and an answer by Lia Milenakos.