You must enable javascript in order to use the Slack API Documentation. You can do this in your browser settings.
Go to Slack

Enabling interactions with bots

Enable conversations between users and apps in Slack by building bots.

A conversation between @celeste and @officebot


What are bots?

A bot is a type of Slack App designed to interact with users via conversation.

A bot is the same as a regular app: it can access the same range of APIs and do all of the magical things that a Slack App can do.

But when you build a bot for your Slack App, you're giving that app a face, a name, and a personality, and encouraging users to talk to it.

Your bot can send DMs, it can be mentioned by users, it can post messages or upload files, and it can be invited to channels - or kicked out.

Bots are not cybernetic infiltration units, and it is unlikely that they dream of electric sheep, though we can't rule it out. 🤖

Bots and workspace apps

You can create two types of Slack App - newer workspace apps and older traditional apps. Each type of app has a distinct process for creating a bot, so we have separate getting started guides:

If you don't have an app yet and are wondering which type to start with, check out our overview of workspace apps to read more about the differences between them and to learn how to create them.


Getting Started

Since your bot is capable of doing everything that a Slack App can do, we're going to limit our focus to a common use-case for bots. The following steps will get you to the point where you have a bot waiting for messages with trigger words and sending simple responses.

From there, you can start bolting on whatever kind of amazing app logic or nuclear-powered jet-packs you can imagine.

Before you start, you'll need a Slack App. If you don't already have one, click the following button to create it:

Create your Slack app

That done, you're all ready to arrange the architecture of this automaton.

1. Creating a bot user

To use your Slack App as a bot, first you'll need to create a Bot User for it.

Head to your app's settings page and click the Bot Users feature in the navigation menu.

You'll be presented with a button marked Add a Bot User, and when you click on it, you'll see a screen where you can configure your app's bot user with the following info:

  • Display name - the name that is displayed to other users when the bot posts messages, or the bot's profile is viewed, etc.
  • Default username - the string that is used when the bot is mentioned in a message. This username may be modified slightly from the default when it is installed to a workspace where that username is already reserved. This modification is an incrementing number appended to the username - so @username might become @username2.
  • Always Show My Bot as Online - we recommend you enable this feature, so that your bot always appears to be ready to receive input (which it probably will be). When disabled, you'll have to programmatically set its online presence.

Once you've completed these fields, click the Add Bot User button and then Save Changes.

Great, you've just created a bouncing baby bot! Don't leave the app settings yet though, there's just one more bit of configuration left to do.

2. Setting up the Events API

The Events API is a bot's equivalent of eyes and ears. It gives a bot a way to react to posted messages, changes to channels, and other activities that happen in Slack. When these events happen, a data payload will be sent to your bot, and it can use that data to form a useful response.

Giving your bot access to the Events API is pretty simple:

  • From your app's settings, click the Event Subscriptions feature in the navigation menu.
  • Switch the Enable Events toggle to on and you'll be presented with a new screen of options.
  • You'll need to configure the Request URL that the data payloads will be pushed to. This URL needs to be verified first, as outlined in the Events API docs.
  • Then you'll add some individual event subscriptions. For our bot, we're interested in the Bot Events, so click on the Add Bot User Event button.
  • There are lots of different event types you could add, but for the purposes of our tutorial let's add two event subscriptions - app_mention which sends events when someone mentions your bot, and message.channels which sends events when a new message is posted in a public channel.
  • Click the Save Changes buttons

Good news! Your bot is looking more and more life-like, and now it's ready to find a home.

3. Installing the bot to a workspace

A bot user is added to a workspace by installing the app that the bot is associated with. Once you do, you'll get a bot token that is imbued with the bot scope. This token can be used with a subset of Web API methods that we'll discuss later.

If you had already installed your app in the past, you'll need to reinstall to grant the additional bot scope. The process is the same either way:

  • On your app's settings page again, click the Install App settings item in the navigation menu.
  • On this page, click a button marked Install App to your Workspace. If you had already installed your app, the button to click will instead be marked Reinstall App.
  • You'll see a permissions authorization page, where you should click Authorize. Your app is now installed to that workspace, but you still need to invite it into individual channels.
  • You should also invite the bot to a public channel somewhere in your workspace.

Once installed, you will have generated a bot token that you should store for use later on - you can find it in your app's settings under Install App > Bot User OAuth Access Token.

Bot tokens can also be generated using the OAuth install flow if you are distributing your app beyond your own workspace.

Your bot should now be happily dwelling in the channel picked during the install process. It will be listening out for users posting in that channel, and for posted messages that mention the bot. Now you need to tell it what to do when it hears something.

4. Handling events

In a previous step, we configured the event subscriptions for your app, but now we have to actually do something with the data that will be sent with each event.

Let's imagine a simple conversational bot that responds to being mentioned by sending a couple of follow up messages:

Example conversation between a user and a bot with the user asking the bot to tell a joke

There are 4 events triggered in this conversation: the first is an app_mention event from the first message that mentions the bot; the next three are message events for each of the messages posted by Johnny.

Our bot will need to be able to interpret each event and respond accordingly.

We've avoided showing you any specific code up until now, but in the following steps we're going to explain the process and then show very simplified Express/Node.js examples of what your app logic should look like. These examples translate readily into most modern programming languages.

Receiving events

The first thing we need to do is create some app code that will correctly receive the events.

Each event will trigger a request, containing a JSON payload, sent to your configured Request URL. The Events API docs contain a full description of the shape of this JSON, and the reference for app_mention and the message.channels contain any details specific to each event type.

Your app has to be able to receive and parse this JSON, and then send an immediate confirmation response to each event request, as described in the Events API docs.

Here's how we might build our code for receiving events:

// Receive event payload to Request URL via HTTP POST
router.post("/", function(req, res, next) {
    // Get event payload
    let payload = req.body;
    // Respond to this event with HTTP 200 status
    res.sendStatus(200);
}

Now that you've written code to handle an event, you can think about how to respond in a 'bot-like' way.

Responding to mentions using the Web API

For a bot, being mentioned is usually the triggering event for a conversation, just as a human will respond when they hear their name.

Your app code should use the type field inside the event payload to spot these app_mention events, and differentiate them from any other events it might receive.

In addition, you don't want to respond to every mention, only the ones that are actually intended to trigger the "tell a joke" flow.

To do that, use the text field from the event payload, which contains the text of the message that the mention was contained in. When text mentions the bot and includes the words "tell me a joke", the bot will respond; otherwise it'll just stay quiet.

Here's what the example code might look like with this kind of logic:

router.post("/", function(req, res, next) {
    let payload = req.body;
    res.sendStatus(200);

    if (payload.event.type === "app_mention") {
        if (payload.event.text.includes("tell me a joke")) {
            // Make call to chat.postMessage using bot's token
        }
    }
}

With the call to chat.postMessage, the first line of the joke is sent:

Knock, knock.

To send this, your app should use that API method with the token you stored earlier. Here's an example request:

POST https://slack.com/api/chat.postMessage
Content-type: application/json
Authorization: Bearer YOUR_BOTS_TOKEN
{
    "text": "Hello <@UA8RXUPSP>! Knock, knock.",
    "channel": "CBR2V3XEX"
}

You can read the API method reference for more info on building this request. You can, of course, use all the special formatting, attachments, and interactive components available for messages, but for now keep it simple.

So, your bot has uttered those first magical words, and you can assume that the user will reply with the standard "Who's there?" response. Let's find out how to keep the joke going.

Responding to other messages

As we said before, the flow we're describing contains an app_mention event followed by three message events. In order to identify the differences between those three messages, the app logic must become a bit more complex.

The first thing you need to do is use the type field inside the event payload to look for these message events.

Next, use the text of the message in the event payload to decide which kind of response your bot should make.

Again, let's assume the pattern of 'knock, knock' jokes - the first user response is always "Who's there?", and the second user response is always "____ who?". So, you can check for messages that include these words, and use the right bot response for each. If you see any messages that don't include either of these phrases, ignore them.

Added to the code from previous steps you'll have something like this:

router.post("/", function(req, res, next) {
    let payload = req.body;
    res.sendStatus(200);

    if (payload.event.type === "app_mention") {
        if (payload.event.text.includes("tell me a joke")) {
            // Make call to chat.postMessage using bot's token
        }
    }
    if (payload.event.type === "message") {
        let response_text;
        if (payload.event.text.includes("Who's there?")) {
            response_text = "A bot user";
        }
        if (payload.event.text.includes("Bot user who?")) {
            response_text = "No, I'm a bot user. I don't understand jokes.";
        }
        if (response_text !== undefined) {
            // Make call to chat.postMessage sending response_text using bot's token
        }
    }
}

Congratulations, your first bot is now alive and talking! You should now be able to go to the channel you installed the bot into and strike up this conversation with it. Remember to laugh politely when it tells you the punchline.

Your next steps should involve adding some more complexity to your bot to make it useful. Jump to the section below for more on that.


Getting Started with bots in workspace apps

The setup process for a bot in a workspace app is somewhat different from that of a regular Slack App, even though the operating logic for either is pretty much the same.

Below we'll cover the steps needed to prepare a workspace app to be a bot, but to do that you'll need a workspace app! If you don't already have one, click the following button to create it:

Create a workspace app

Once you have created one, it's time to tinker with the tin-man.

1. Setting up the Events API

The Events API is a bot's equivalent of eyes and ears. It gives a bot a way to react to posted messages, changes to channels, and other activities that happen in Slack. When these events happen, a data payload will be sent to your bot, and it can use that data to form a useful response.

The process for enabling access to the Events API with a workspace app is very similar to what we've already explained for regular Slack Apps. But the difference is that workspace apps do not yet have support for the app_mention event type.

We'll explain more about how you can replicate the behavior of the app_mention event below.

For now, let's go ahead and give your bot access to the Events API:

  • From your app's settings, click the Event Subscriptions feature in the navigation menu.
  • Switch the Enable Events toggle to on and you'll be presented with a new screen of options.
  • You'll need to configure the Request URL that the data payloads will be pushed to. This URL needs to be verified first, as outlined in the Events API docs.
  • Once you've done that, click on the Add Workspace Event button.
  • There are lots of different event types you could add, but for the purposes of our tutorial let's add one event subscription - message.channels, which sends events when a new message is posted in a public channel.
  • Click the Save Changes buttons.

Good news! Your bot is looking more and more life-like, and now it's ready to find a home.

2. Getting a workspace token for a bot

Workspace apps don't have to create Bot Users like traditional Slack apps do, and there's a good reason for this.

With traditional apps, creating and using a user token for a bot would be fairly complicated as each bot and user interaction would have its own unique token. The bot token makes that simpler by giving each bot its own token to use to post messages and make other API calls.

For workspace apps, a special workspace token can be used for all the interactions with users in that workspace. This makes those Bot Users unnecessary - instead the workspace app is the bot, and the workspace token is used in place of a bot token. As a bonus, workspace tokens can access a fuller range of Web APIs compared to bot tokens.

With that in mind, you'll need to generate one of these tokens in order to build your bot, and you'll need to add the right permissions to that token to let your bot post messages:

  • On your app's settings page, click the OAuth & Permissions settings item in the navigation menu.
  • In the Scopes section, add the chat:write permission scope, then click Save Changes.
  • Now that you've changed the scopes for your app, you'll need to install it again - you should see a yellow banner near the top of the screen telling you to click here to reinstall your app. Click it, and follow through the permissions authorization page.
  • You'll be redirected back to the OAuth & Permissions page, where you can see your workspace token listed at the top of the page - store this for use later on.

If you want to distribute your app, you can also use the OAuth flow for installing workspace apps, and at the end of that process you'll receive the same workspace token as above.

Now we're ready to add some brains to this bot.

3. Handling events

At this point, you can essentially follow the regular Getting Started guide above from the Handling Events step, but there's just one little wrinkle to cover.

Because workspace apps do not currently support the app_mention event type, we need to build a way to recognise mentions manually.

Building off the code shown above for handling message events, we can redo it to add a check that the message text contains a mention of our bot:

router.post("/", function(req, res, next) {
    let payload = req.body;
    res.sendStatus(200);

    if (payload.event.type === "message") {
        let response_text;
        if (payload.event.text.includes("<@UBJTTTDRT>") && payload.event.text.includes("tell me a joke")) {
            response_text = `Hello <@${payload.event.username}>! Knock, knock.`
        }
        if (payload.event.text.includes("Who's there?")) {
            response_text = "A bot user";
        }
        if (payload.event.text.includes("Bot user who?")) {
            response_text = "No, I'm a bot user. I don't understand jokes.";
        }
        if (response_text !== undefined) {
            // Make call to chat.postMessage sending response_text using bot's token
        }
    }
}

The <@UBJTTTDRT> string is the escaped version of a mention of the app, so that identifies the mention within the rest of the event text. This essentially replicates the app_mention event functionality, although you will receive events for messages that aren't relevant to your app.

Your workspace app is now built to act as a bot, and respond to a simple conversation. You will want to take things further though: maybe you want to build a bot that could pass the Voight-Kampff test. Read on for tips on adding more complexity.


Making more complex bots

In the steps above, we made a lot of assumptions of simplicity. For example, we expected that users would respond with a very specific spelling, we assumed a test environment where there were no other conversations happening, and so on.

For a real bot in production, some of these assumptions would break the behavior of the bot. So let's cover some situations that you should address for your own bots - think of these as best practices rather than specific instructions to follow.

Tracking conversations

In our example bot, we've used a mention as the triggering point for a specific conversation, but you'll notice that your bot will still respond if you skip some of the steps - for example if you type Who's there?, your bot will respond to this message with A bot user, even if you didn't mention the bot or start at the beginning of the conversation.

A solution to this might involve tracking the beginning of a conversation, the participants involved, and the progress through the flow. For example, when the user first mentions the bot, a database entry is created that identifies that user and the open workflow with them.

As the user progresses through the flow, the database records this, and the user is unable to repeat earlier steps in the conversation (unless of course that is a desired behavior). Once the workflow is completed, the database entry is also marked as complete, and the bot waits for another mention before starting anew.

Threaded messages

Be aware that a user might choose to reply to your bot's messages in a thread rather than at the channel-level. Your bot will still receive message events for these threaded replies, but you will have to add some extra logic to ensure that your bot responds to the user in the relevant location.

Check out the Threading Messages docs for more information on how to spot the difference between messages and threaded messages.

Conversations in App Home

Workspace apps grant apps a dedicated space within Slack where members can interact directly — we call it your App Home. Apps can use this in many ways, but one great use is for bot conversations.

The message.app_home event is available for these workspace apps, and it'll subscribe you to any messages sent to that conversation.

Treat a message sent to this App Home in the same way as you would a message that mentions your bot - they're both intended for the attention of the bot, they just have different sources.

Your app can also initiate a conversation from scratch with users in their App Home by making use of the conversations.app_home:create scope.

Variations in phrasing

Because your bot will be interacting with humans, it's unlikely that you can expect consistent spelling and phrasing across messages from different people that might be trying to invoke the same thing. For example, our simple example bot used the phrase tell me a joke to trigger the start of the workflow, but at a very basic level a user might also try typing what's a good joke? or make me laugh.

Your bot can get more complex by broadening its understanding of natural language queries to capture a wider range of potential trigger phrases. Alternatively you can be more prescriptive about the exact phrasing to use, and provide user education to train correct usage.

Integrating with other services

The real magic of a bot comes when it is connected with external services, providing a seamless conversational interface for them from within Slack.

There's a huge range of possibilities for what your bot could do, so it might help to start with a great resource like the Botkit Community.


Limitations

Like other APIs and integrations, bot users are free. Unlike regular users, the actions they can perform are somewhat limited. For workspaces on the Free plan, each bot user counts as a separate integration.

API methods available to bots

Bot Users, and bot tokens, can be used with a slightly restricted set of Web API methods. These methods are shown below:

Method & Description Description
api.test
Checks API calling code.
Checks API calling code.
auth.test
Checks authentication & identity.
Checks authentication & identity.
bots.info
Gets information about a bot user.
Gets information about a bot user.
channels.info
Gets information about a channel.
Gets information about a channel.
channels.list
Lists all channels in a Slack team.
Lists all channels in a Slack team.
chat.meMessage
Share a me message into a channel.
Share a me message into a channel.
chat.postEphemeral
Sends an ephemeral message to a user in a channel.
Sends an ephemeral message to a user in a channel.
chat.postMessage
Sends a message to a channel.
Sends a message to a channel.
chat.update
Updates a message.
Updates a message.
conversations.close
Closes a direct message or multi-person direct message.
Closes a direct message or multi-person direct message.
conversations.history
Fetches a conversation's history of messages and events.
Fetches a conversation's history of messages and events.
conversations.info
Retrieve information about a conversation.
Retrieve information about a conversation.
conversations.list
Lists all channels in a Slack team.
Lists all channels in a Slack team.
conversations.members
Retrieve members of a conversation.
Retrieve members of a conversation.
conversations.open
Opens or resumes a direct message or multi-person direct message.
Opens or resumes a direct message or multi-person direct message.
conversations.replies
Retrieve a thread of messages posted to a conversation
Retrieve a thread of messages posted to a conversation
dialog.open
Open a dialog with a user
Open a dialog with a user
dnd.info
Retrieves a user's current Do Not Disturb status.
Retrieves a user's current Do Not Disturb status.
dnd.teamInfo
Retrieves the Do Not Disturb status for users on a team.
Retrieves the Do Not Disturb status for users on a team.
files.comments.add
Add a comment to an existing file.
Add a comment to an existing file.
files.comments.delete
Deletes an existing comment on a file.
Deletes an existing comment on a file.
files.comments.edit
Edit an existing file comment.
Edit an existing file comment.
files.delete
Deletes a file.
Deletes a file.
files.info
Gets information about a team file.
Gets information about a team file.
files.upload
Uploads or creates a file.
Uploads or creates a file.
groups.info
Gets information about a private channel.
Gets information about a private channel.
groups.list
Lists private channels that the calling user has access to.
Lists private channels that the calling user has access to.
im.close
Close a direct message channel.
Close a direct message channel.
im.history
Fetches history of messages and events from direct message channel.
Fetches history of messages and events from direct message channel.
im.list
Lists direct message channels for the calling user.
Lists direct message channels for the calling user.
im.mark
Sets the read cursor in a direct message channel.
Sets the read cursor in a direct message channel.
im.open
Opens a direct message channel.
Opens a direct message channel.
im.replies
Retrieve a thread of messages posted to a direct message conversation
Retrieve a thread of messages posted to a direct message conversation
mpim.close
Closes a multiparty direct message channel.
Closes a multiparty direct message channel.
mpim.history
Fetches history of messages and events from a multiparty direct message.
Fetches history of messages and events from a multiparty direct message.
mpim.list
Lists multiparty direct message channels for the calling user.
Lists multiparty direct message channels for the calling user.
mpim.mark
Sets the read cursor in a multiparty direct message channel.
Sets the read cursor in a multiparty direct message channel.
mpim.open
This method opens a multiparty direct message.
This method opens a multiparty direct message.
oauth.access
Exchanges a temporary OAuth verifier code for an access token.
Exchanges a temporary OAuth verifier code for an access token.
oauth.token
Exchanges a temporary OAuth verifier code for a workspace token.
Exchanges a temporary OAuth verifier code for a workspace token.
pins.add
Pins an item to a channel.
Pins an item to a channel.
pins.remove
Un-pins an item from a channel.
Un-pins an item from a channel.
reactions.add
Adds a reaction to an item.
Adds a reaction to an item.
reactions.get
Gets reactions for an item.
Gets reactions for an item.
reactions.list
Lists reactions made by a user.
Lists reactions made by a user.
reactions.remove
Removes a reaction from an item.
Removes a reaction from an item.
rtm.connect
Starts a Real Time Messaging session.
Starts a Real Time Messaging session.
rtm.start
Starts a Real Time Messaging session.
Starts a Real Time Messaging session.
stars.add
Adds a star to an item.
Adds a star to an item.
stars.remove
Removes a star from an item.
Removes a star from an item.
team.info
Gets information about the current team.
Gets information about the current team.
users.conversations
List conversations the calling user may access.
List conversations the calling user may access.
users.getPresence
Gets user presence information.
Gets user presence information.
users.info
Gets information about a user.
Gets information about a user.
users.list
Lists all users in a Slack team.
Lists all users in a Slack team.
users.lookupByEmail
Find a user with an email address.
Find a user with an email address.
users.setActive
Marked a user as active. Deprecated and non-functional.
Marked a user as active. Deprecated and non-functional.
users.setPresence
Manually sets user presence.
Manually sets user presence.