Skip to content

🚀 This new wiki is in beta! Please double-check for any issue and report them on the GitHub

Interactions Overview

Interactions are Discord’s modern way of letting users engage with your bot. They include buttons, dropdown menus, slash commands, and modals - all providing a seamless, integrated experience within Discord’s interface.

Interactions are special Discord events that require your bot to respond within 3 seconds. Unlike traditional message commands, interactions provide:

  • Better UX - Native Discord UI components
  • Auto-complete - Built-in validation and suggestions
  • Ephemeral responses - Only visible to the user who triggered them
  • Rich components - Buttons, menus, and forms

Buttons

Clickable buttons in messages with different styles and colors. Great for confirmations, actions, and navigation.

Learn more →

Dropdown Menus

Let users select from predefined options or Discord entities (users, roles, channels).

Learn more →

Slash Commands

Modern Discord commands with built-in argument validation and auto-complete.

Learn more →

Modals

Pop-up forms for collecting structured user input with text fields and dropdowns.

Learn more →

Interactions in messages are organized into Action Rows. Each row takes the full width of the message and can contain:

  • Up to 5 buttons, or
  • 1 dropdown menu

A single message can have up to 5 action rows.

# Example: 3 rows in one message
create a new message and store it in {_msg}:
# Row 1: 3 buttons
make new component row and store it in {_row1}:
add new primary button with id "btn1" named "Option 1" to components of the row builder
add new primary button with id "btn2" named "Option 2" to components of the row builder
add new primary button with id "btn3" named "Option 3" to components of the row builder
add {_row1} to rows of the message
# Row 2: 1 dropdown
set {_dropdown} to new dropdown with id "menu1"
add new option with value "a" named "Choice A" to options of {_dropdown}
add {_dropdown} to rows of the message
# Row 3: 2 more buttons
make new component row and store it in {_row2}:
add new success button with id "confirm" named "Confirm" to components of the row builder
add new danger button with id "cancel" named "Cancel" to components of the row builder
add {_row2} to rows of the message
reply with {_msg}

When a user interacts with your bot, you must respond quickly. There are several ways to acknowledge an interaction:

Send a visible response right away:

on button click:
if event-string is "my_button":
reply with "You clicked the button!"

Send a response only visible to the user:

on button click:
if event-string is "my_button":
reply with hidden "This message is only visible to you!"

Buy more time when you need to do complex processing:

on button click:
if event-string is "process":
defer the interaction
# Now you have more time (15 minutes) to process
# ... do complex operations ...
# Update later with the result
edit interaction with "Processing complete!"

Open a form for user input:

on button click:
if event-string is "feedback":
set {_modal} to new modal with id "feedback_form" named "Feedback"
# ... configure modal ...
show {_modal} to the user
command /delete:
trigger:
create a new message and store it in {_msg}:
set the content of the message to "⚠️ Are you sure you want to delete this?"
make new component row and store it in {_row}:
add new danger button with id "delete_yes" named "Yes, Delete" to components of the row builder
add new secondary button with id "delete_no" named "Cancel" to components of the row builder
add {_row} to rows of the message
reply with {_msg}
on button click:
if event-string is "delete_yes":
# Perform deletion
reply with "✅ Deleted successfully!"
else if event-string is "delete_no":
reply with "Cancelled."
on button click:
if event-string is "step1":
# Acknowledge and show next step
create a new message and store it in {_msg}:
set the content of the message to "Step 1 complete! Continue to step 2?"
add new primary button with id "step2" named "Next" to rows of the message
edit interaction with {_msg}
else if event-string is "step2":
reply with "Process complete!"
command /roles:
trigger:
create a new message and store it in {_msg}:
set the content of the message to "Select your roles:"
set {_dropdown} to new dropdown with id "role_select"
set placeholder of {_dropdown} to "Choose roles..."
set min range of {_dropdown} to 0
set max range of {_dropdown} to 3
add new option with value "developer" named "Developer" with reaction "💻" to options of {_dropdown}
add new option with value "designer" named "Designer" with reaction "🎨" to options of {_dropdown}
add new option with value "tester" named "Tester" with reaction "🧪" to options of {_dropdown}
add {_dropdown} to rows of the message
reply with {_msg}
on dropdown click:
if event-dropdown is "role_select":
set {_values::*} to selected values
reply with hidden "You selected: %join {_values::*} with "", ""%"

Each interaction event provides specific values you can use:

on button click:
# event-string = button ID
# event-user = user who clicked
# event-message = message containing the button
# event-channel = channel where it happened
if event-string is "my_button":
reply with "Button clicked by %mention tag of event-user%!"
on dropdown click:
# event-dropdown = dropdown ID
# selected values = array of selected values
# event-user = user who selected
if event-dropdown is "my_menu":
set {_choices::*} to selected values
reply with "You chose: %{_choices::*}%"
on entity dropdown click:
# event-dropdown = dropdown ID
# selected entities = array of users/roles/channels
if event-dropdown is "user_picker":
set {_users::*} to selected entities
reply with "Selected %size of {_users::*}% users"
on slash command:
# event-string = command name
# argument "name" = get command arguments
if event-string is "mycommand":
set {_value} to argument "option" as string
reply with "Received: %{_value}%"
on modal receive:
# event-string = modal ID
# value of text input with id "..." = get input values
# value of dropdown with id "..." = get dropdown selections
if event-string is "my_modal":
set {_input} to value of text input with id "field1"
reply with "You entered: %{_input}%"

Since DiSky v4.14.2, you can directly edit clicked components:

on button click:
if event-string is "toggle":
# Change the button when clicked
edit button to show new disabled success button with id "toggle" named "Activated" with reaction ""
on dropdown click:
if event-dropdown is "selector":
set {_choices::*} to selected values
# Update the dropdown to show selection
set {_newDropdown} to new dropdown with id "selector"
set placeholder of {_newDropdown} to "Selected: %join {_choices::*} with "", ""%"
# ... add options ...
edit dropdown to show {_newDropdown}
  1. Always Respond Within 3 Seconds

    Use reply, defer, or show modal to acknowledge interactions. If you need more time, defer first.

  2. Use Unique IDs

    Button and dropdown IDs must be unique within a message. Use descriptive names like delete_confirm instead of btn1.

  3. Provide Clear Feedback

    Let users know what happened. Use ephemeral messages for errors or confirmations.

  4. Handle Edge Cases

    Check for null values, validate user input, and handle errors gracefully.

  5. Consider User Permissions

    Verify users have permission before allowing actions through interactions.

  6. Disable After Use (When Appropriate)

    For one-time actions, disable buttons after they’re clicked to prevent duplicate actions.

Components can be enabled or disabled:

# Enabled button (default)
set {_btn} to new primary button with id "active" named "Click Me"
# Disabled button
set {_btn} to new disabled primary button with id "inactive" named "Cannot Click"

Disabled components:

  • Appear grayed out
  • Cannot be clicked
  • Still visible but non-interactive
  • You didn’t respond within 3 seconds
  • Use defer if you need more processing time
  • Check for errors in your event handler
  • Verify the component ID matches in your event handler
  • Ensure you’re using the correct event (on button click vs on dropdown click)
  • Check that the component wasn’t disabled
  • When editing, make sure you’re updating the correct component
  • Verify you’re using edit interaction or edit button/dropdown
  • Check that the interaction hasn’t already been acknowledged