discord-interactions is a Python library for the Discord Artificial Programming Interface. (API) A library in Python has to be installed through the pip file. Run this in your terminal/command line in order to install our library:

pip install -U discord-py-interactions

Minimal Bot

Bots can be a little confusing to create. That’s why we’ve decided to try and make the process as streamlined as humanly possible, in order for it to be friendlier to understand for our fellow bot developers. Please note that a Discord bot should not be your first project if you’re learning how to code. There are plenty of other projects to consider first before this, as a Discord bot is not exactly beginner-friendly.

This code block below shows a simple bot being created:

 1import interactions
 3bot = interactions.Client(token="...")
 6    name="test",
 7    description="this is just a test command.",
 8    scope=1234567890
10async def test(ctx):
11    await ctx.send("Hello world!")

There’s quite a lot of things that are going on here, so let’s break it down step-by-step:

  • import interactions – This is the import line. If this returns a ModuleNotFoundError, please look at our section on how to install here.

  • bot = interactions.Client(token="...") – This is the bot variable that defines our bot. This basically instantiates the application client, which requires a token keyword-argument to be passed. In order to get a token, please look at the image given below.

  • @bot.command() – This is something known as a decorator in Python. This decorator is in charge and responsible of making sure that the Discord API is told about the slash/sub command that you wish to create, and sends an HTTP request correspondingly. Any changes to the information contained in this decorator will be synchronously updated with the API automatically for you. The scope field shown here is optional, which represents a guild command if you wish to have a command appear in only specific servers that bot is in. This can be a guild object or the ID.

  • async def test(ctx): – This here is called our “command coroutine,” or what our library internally calls upon each time it recognizes an interaction event from the Discord API that affiliates with the data we’ve put into the decorator above it. Please note that ctx is an abbreviation for context.

  • bot.start() – Finally, this is what tells our library to turn your bot from offline to online.


Context menus

While, granted that application commands are way more intuitive and easier to work with as both a bot developer and user from a UX approach, some may not want to always type the same command over and over again to repeat a repetitive task. Introducing: context menus. Also known as “user” and “message” respectively, this simple switch in command structure allows you to quickly empower your bot with the ability to make right-click actions with menial efort.

In order to create a menu-based command, all you need to do is simply add this one line into your @command decorator:

2    type=interactions.ApplicationCommandType.USER,
3    name="User Command",
4    scope=1234567890
6async def test(ctx):
7    await ctx.send(f"You have applied a command onto user {ctx.target.user.username}!")

The structure of a menu command differs significantly from that of a regular one:

  • You cannot have any options or choices.

  • You cannot have a description.

  • The name filter follows a different regex pattern.


Being able to run your own commands is very useful for a lot of automation-related purposes as a bot developer, however, we also have something that we’re able to introduce for both the developer and a user to use that will be the “sprinkles” on top of a cupcake, so-to-speak: components.

Components are ways of being able to select pre-defined data, or define your own. They’re very simple but quite powerful when put into practice This code block below shows a simplified implementation of a component:

 1button = interactions.Button(
 2    style=interactions.ButtonStyle.PRIMARY,
 3    label="hello world!",
 4    custom_id="hello"
 8    name="test",
 9    description="this is just a test command.",
10    scope=1234567890
12async def test(ctx):
13    await ctx.send("testing", components=button)
16async def button_response(ctx):
17    print("someone clicked the button! :O")

This is a design that we ended up choosing to simplify responding to buttons when someone presses on one, and to allow bot developers to plug in which button they want a response to. No more wait_for_component and wait_for functions with huge if-else chains; this removes redundancy in your code and overall eases into the practice of modularity.

What kinds of components are there?

As a bot developer, this may be fairly important for you to want to know. Different components provide difference user experiences, interactions and results. Currently you can choose between two components that Discord provides: a Button and SelectMenu. You’re able to find these component types here.

How do I send components in a row?

You are also able to organize these components into rows, which are defined as ActionRow’s. It is worth noting that you can have only a maximum of 5 per message that you send. This code block below shows how:

 1button = interactions.Button(
 2    style=interactions.ButtonStyle.PRIMARY,
 3    label="hello world!",
 4    custom_id="hello"
 6menu = interactions.SelectMenu(
 7    options=[
 8        interactions.SelectOption(label="Option one", value="o-one"),
 9        interactions.SelectOption(label="Option two", value="o-two"),
10        interactions.SelectOption(label="Option three", value="o-three")
11    ]
13row = interactions.ActionRow(
14    components=[button, menu]
18async def test(ctx):
19    await ctx.send("rows!", components=row)

By default, the components keyword-argument field in the context sending method will always support ActionRow-less sending: you only need to declare rows whenever you need or want to. This field will also support raw arrays and tables, if you so wish to choose to not use our class objects instead.