Getting Started with Creating Slack Bots & Slack Apps
Six tips for building your first enterprise Slack app from a chatbot developer
August 4, 2021
My name is Anirudha Simha, and I’m a senior software engineer at Capital One working on an internal chatbot. Its capabilities include answering FAQs using machine learning and natural language processing (NLP) and supporting API-driven actionable integrations with various popular services like Confluence, JIRA, and Github. Our chatbot is primarily used as an app in Slack, where it supports over 150 different Slack channels and is used by thousands of employees across a wide range of internal teams within Capital One.
In my experience, these kinds of apps provide a great way to integrate various workflows and processes into Slack, allowing users to complete many tasks from a single environment. When implemented properly, Slack apps can provide a significant benefit, but there are some tricks involved. In this blog I will go over six considerations that you should keep in mind when building, owning, and maintaining a highly scalable enterprise Slack app.
A few words about Slack apps vs Slack bots. Though the terms are sometimes used interchangeably, they are different things; an app may contain a bot, or it may not, where the bot is just the piece of the app that interacts with the user. Most apps tend to have a bot component but it is not a required aspect of an app. The distinction is not significant here, so I'll use the term 'Slack app' throughout.
PLEASE NOTE - This article uses Amazon Web Services (AWS) as the example cloud service, however other cloud providers may work or have equivalent services.
Consideration #0: Why build a Slack app?
First and foremost, why are you making an app? What is its purpose and role?
The role of your app in your organization will affect considerations into how you design and build it; including, ultimately, the value and utility it drives for you. Some reasons and roles to build a Slack app include:
- Automating all of the things!
- Integrating processes that are tailored to your organization's needs and considerations.
- Enabling users to perform actions without having to leave Slack.
- Providing automated support.
- Creating a fun tool that helps enable culture within your company. 😎
Consideration #1: Getting events via Slack Events API vs Socket Mode
While the end goal for your Slack app is to communicate and interact with your users in an impactful and value-driving manner, that ultimately relies on also knowing what’s going on in Slack. That way is to use Slack’s events based system, through HTTP endpoints or WebSockets, to inform your application of the goings on of your workspace.
Slack Events API
Slack provides several APIs to consume. The web API is used to query Slack for information and perform actions. The next question is, how do you get information about events to your application? This is done via the events API. By exposing a public endpoint and providing this to your Slack app, Slack can forward events to your endpoint for you to process and handle, and only events that you choose to subscribe to will be sent. For example, you can choose to receive HTTP events about reactions being added in channels your app is part of, or you can sign up to get events for each time a new member joins a channel. You can see the full list of Slack events here.
Socket Mode is a feature from Slack that uses WebSockets to achieve the same functionality as the events API. Developers will not need to provide a public facing URL to Slack as the WebSocket connection will take the place of this. In my experience Socket Mode is the best way to work within the restrictions of corporate proxies. Additionally, because Socket Mode is a WebSocket connection, it tends to have less latency than traditional approaches that expose a static HTTP endpoint. However, this is at the cost of a persistent connection needing to be made (so no serverless approaches).
Consideration #2 - Using serverless vs containers for your Slack app infrastructure
When deploying your enterprise Slack app, you will want to strike the best balance between cost, availability, and performance. For that end, I personally recommend using a serverless approach like AWS Lambda (if you are using Socket Mode, then read on below) since it is very cost effective, scales out quite well, and is easy and simple to use.
PLEASE NOTE - as the intent of this article is not to walk through the minutiae of setting up infrastructure, I will instead leave links to articles that can help to set up the various infrastructure approaches I discuss below.
The serverless approach
Most implementations that take this serverless approach use an API gateway to expose a public URL that will then forward events to your lambda function. An example with AWS API gateway and a lambda function would look like the below:
Here is a tutorial on creating an AWS lambda function connected to API gateway
Here are articles with step-by-step approaches specifically for Slack Apps
This serverless approach allows for easy scaling out of events while still being quite performant and cost efficient, which makes it quite handy since, as your organization grows AWS lambda can scale to your needs.
The container-based approach
If you are running Socket Mode or using Bolt (SDK by Slack that makes it very easy to set up a server that listens for Slack events) without using the Serverless Framework, then the above serverless approach will not work for you. However, a container-based approach (e.g. ECS, Docker) will.
Here is an article on understanding Amazon Elastic Container Service (ECS)
Here is an article with step-by-step on deploying Docker containers in ECS
The advantages this container-based approach offers is that it is always running and will not suffer from cold starts or the 15 minute execution time limit that lambdas are limited to.
Consideration #3 - Understanding how Slack workspace organization impacts your app
The highest level of organization in Slack is the workspace, which contains all of the channels. If you are familiar with Discord, then it's analogous to Discord’s servers. An enterprise grid is a collection of workspaces that can communicate with each other. A small startup may have a single workspace that contains all of their channels. However, larger organizations are likely to have multiple workspaces each for different job functions (e.g. a workspace for the HR organization, and a workspace for tech, etc..).
We can see an example of an enterprise grid in the graphic below. There are various workspaces shown here like engineering or marketing, each with their own channels. However, there are some channels like #company-wide-announcements that are available across all workspaces in the company as well.
Slack apps are installed per workspace,so the app owner needs to make sure that the app is installed to each workspace that their intended users will be interacting from.
Single workspace - Organizations that are running across a single workspace will typically only have to worry about that single workspace (also referred to as team in the Slack API docs). This simplifies the process for the developer, as they only have to install to one workspace, and there is only a single app-token they need to worry about.
Multiple workspaces - Organizations across multiple workspaces will have to be aware that their app will need to be installed on each workspace. This means that the app will need to look at any incoming responses and use the “team” field to identify which workspace an event is coming from and then use the appropriate app token for that workspace.
Enterprise grid - If your organization is using an enterprise grid, then consider converting your app to an org-wide app and using its org-wide token. This lets you use a single app token that will work across all workspaces while providing simplified token management/usage.
Consideration #4 - Understanding the building “blocks” of Slack’s UI
When designing the UI/UX for your Slack app you will want to be consistent with your design and obey good design principles. Really, the rules for UI/UX in a Slack app are universal to many applications, so this shouldn’t be too hard.
You can read about Human Computer Interaction (HCI) Guidelines if you are interested in learning more.
Slack helps you stay consistent with HCI principles by using a templating UI framework called block-kit (more details here and here). The foundational building blocks of block-kit are aptly named blocks. Blocks are simply JSON formatted with specific fields and values that are given as inputs to certain Slack web API calls. The output of these web API calls, when provided with blocks, results in a stacked visual layout of elements (text boxes, buttons, dropdowns, text, etc) in messages, modals, and other surfaces in Slack. You can see an example of what block elements would look like in the image below.
While there are some options for the developer to change the colors of buttons, the placement and style of most elements is fixed, further reinforcing a consistent look and feel. However, since you have some leeway for how to position certain elements (e.g. have a button inline with a text section vs a text section with a button directly below it), you will want to stay consistent to make your app easy to use and visually on brand. This also includes usage of visuals like GIFs, images, and emojis. I personally like using visual elements like emojis in my blocks, since they help to break up text. However, the decision to use elements such as these will vary based on your use case, app, and preferences. Like all things though, it is a balancing act to find the right amount of text to interactive elements to visual elements to convey what you want while not being too overwhelming or too dense.
Please note that when designing your blocks, you can visualize how they will look using block-kit builder (please note that this link will require you to sign into a Slack workspace to view it). This is a great way to see how things will actually look like to users and allow for rapid prototyping. I highly, highly recommend using this, as it makes visualizing messages and modals that much easier, and the included templates are great sources of inspiration.
Consideration #5 - Simple guidelines for Slack app interactions
Slack apps have a multitude of ways they can communicate information and factors that should be taken into account when designing them. This includes what the Slack app does, the urgency/importance of the information it conveys, or how much traffic a channel gets. These all affect how you want your app to interact with users and is something to be mindful about.
tl;dr Don’t drag the user around from channel to channel, provide feedback when they do something, be aware of how and where you should display information, and don’t overwhelm them.
Do your work right there in the channel
If work can be done in the channel, then do it there. Don’t require the user to have to go to another specific channel or switch to a direct message (DM) with the app unless necessary. For example, if you have a Slack app that lets users make and send a poll to a channel it makes sense to be able to invoke the process in that channel, right there, as opposed to directing the user to a DM with the Slack app.
Offer informative feedback
Provide feedback to the user after actions are taken so it is obvious to the user that something is happening. This is especially important if there are long running processes that may require the user to wait for a moment. E.g. “Hey we just received your application, sit tight while the bot works on it! You’ll hear back from the bot in a few minutes once it finishes processing it.” I also like adding visual elements like emojis or images to my messages so they stand out a bit more. For the above message, an emoji with a spinning loading icon may be appropriate to help reinforce the idea that something is still being processed. Again, the idea is to keep the user from having to guess if something is happening or if their interactions did something; however, that doesn’t mean you need to drown them with feedback either--but more on that later.
Who, what, and where - context matters
When providing responses back to the user, consider who you are talking to, what you are talking about, and where you are. If you are in a busy channel and have responses that only a singular user needs to see, then it may not be appropriate to have your app publish messages for everyone to see. Instead, it may be better to have your app either publish responses in a thread, ephemerally (so only a specific user can see), directly to the user in the messages tab (aka DM), or to the home tab.
- Threaded replies - Work well when you want to follow up on something in the main channel or in an existing thread. A great example of this is if your Slack app is answering a question posted by a user in the main channel, the app should post its response as a threaded reply to the user’s message.
- Ephemeral messages - Are when a message (threaded or not) is only visible to a specific user. Ephemeral messages are not guaranteed to stick around and may “disappear” after a while, which should be taken into account when using them. A good use case for ephemeral messages would be if a user interacted with your app by clicking a thumbs up button to give feedback and you wanted the app to respond with “Thank you, your feedback has been recorded!” The entire channel does not need to see the app’s response, just the user.
- Direct messages/The Messages tab - Is a one-on-one channel between the user and your Slack app. This provides a great space for your app to send information to your user without it being lost in the clutter of a larger channel. I would consider using the messages tab if you need to convey to the user some important historical information that they may want to refer back to later. For example, let’s say a user is interacting with your app in your channel and you want to let them know that their operation was a success and give them some sort of confirmation number to be able to reference later. You could have your app respond back to the user in the channel (ephemerally) letting them know the operation was successful and that full details have been sent to them in a DM (at which point you will send the full details to them in a DM). This is a great use case since the user may not necessarily need the confirmation number, but if they do, then they can see the associated date, time, and information in their DMs instead of having to search through a channel for it.
- The Home tab - Is a “surface” that is part of the one-on-one experience an app has with a user. It is similar to the Messages tab/surface in that it’s a one-on-one experience. However, while direct messages tend to be more fluid and transient, changing as new information is added, the app Home only changes when specifically updated. Since the app Home is not dynamic in the same sense that the Messages tab is, it’s a great place to store blocks of information such as upcoming events or important info the app thinks the user should easily have on hand.
Home is where the app is
I want to draw special attention to the difference between the Home tab and Messages tab. While similar, there are some differences that need to be understood. The Home tab is a surface that contains “blocks,” and the app will need to update it for each user. However, it will stay the same until it is updated again by the app. Meanwhile, the Messages tab is more dynamic and will contain messages between the user and app, or just the app if you don’t want the user to respond back. Since the Messages tab is more dynamic, it has a sense of history and preserves older information that may be helpful to refer back to; similar to referring back to an older email in your inbox. Collectively, the Home tab, the Messages tab, and the About tab comprise the “app Home”. A good example of an app that utilizes the app home well is the Google Calendar app. It uses the Home tab to display the schedule for a specific day. However, it uses the Messages tab to send the user notifications about upcoming events and updates they may need to be aware of. The most important information is visible in the app Home, but other more dynamic and changing info is published in the DM/Messages tab for the user to see, with the advantage of this history being preserved in case the user needs to refer back to it for some reason.
Don’t be messy!
Another consideration when interacting with your user is to be careful not to overwhelm them with too much information or too many messages and notifications. Less is more sometimes. With that being said, keep in mind that if you have lots of options, buttons, text, etc to show, consider prioritizing the most important stuff first. You can use buttons or even modals to paginate through more information, depending on what you are showing. Buttons can work well if you are listing things, while modals can be good if you want to present a popup with more information or actionability.
Remember, context matters in busy channels. We don’t want everyone to see our app’s interactions with a specific user unless necessary. In such a scenario ephemeral messages can really help.
Consideration #6 - Selecting Slack libraries
Slack apps are powerful tools that can lend deep integrations and automations to your organization’s workflows, improving the efficiency of your teams. When building these apps, you need to consider infrastructure, receiving events, and of course the UI/UX.
How you receive events and how your application is hosted are closely related considerations and are dependent on your own skill set, as well as your organization’s cloud and infrastructure policies. Ultimately, whether you go with Lambda using the Events API via a public HTTP endpoint or an ECS container running Socket-mode, or even some hybrid model of the two, the above considerations should allow you to receive Slack events in your app.
In regards to the UI/UX, remember these main points. Take advantage of Slack’s block-kit framework to build visually pleasing and usable GUIs for your app’s various touchpoints with users. Be conscious of where and how your app is interacting. This plays a factor into how your app should be directing users to interact with it, as well as how it should respond back. Finally, find the balance on how you provide feedback, making it informative without being overwhelming.
I hope that this introductory guide on building Slack apps helped provide some help and deeper insight into what to consider when building a Slack app!
*Source: Blockit-builder example generated template (please note that this link requires you to sign into your Slack workspace to view)