I’m a huge fan of automating working processes. I try to automate everything and save my coworkers time.
This article I will show you how to improve the community onboarding journey with a custom Slack bot using the Slack Events API, hosted on AWS Lambda.
Motivation
We used to have a bot greeting new members in the
Ory Community Slack. It messages new members with an
introduction to help get an overview of the Ory community and products.
Since this way of onboarding new members is impersonal and one-way so the
Ory DevRel team was looking for ways to improve it by making it personal and
two-way:
- Message each new member personally.
- Ask them what their biggest challenges or struggles are or what they want to achieve by joining the Ory community.
- Point them to the right place or people who can help with that challenge or help them achieve their goals.
To keep the workload manageable, the initial message is pre-composed. A bot would either notify the team when new members join or message new members from a "human" account. So the options are:
- Ping the Ory DevRel team and notify them to greet a user.
- Send a greeting message from a Slack user.
We landed on the second option and let the bot use a User OAuth Token to send messages as a user. In the next part of the blog post, I’ll tell you how to build this bot.
Using Slack API
Slack offers you a few examples of using APIs:
I built Slack bots before, and the following two chapters are about the difference between WebSockets integration and the Events API. Just for convenience, let’s say that the Events API and webhook integration works almost the same way.
Websockets
Websocket is an excellent protocol. It's easy to implement, developer friendly, and works on top of HTTP1/1. The protocol was first described in 2008, and in 2010 there was broad browser support. Websockets made the developer experience building realtime web applications much more enjoyable back in the day because you did't need to deal with BOSH and chunked encoding of HTTP1/1. Furthermore, new architectural patterns and paradigms such as Event-Driven Architecture and Event-Driven SOA were described.
Despite the benefits described above, WebSockets have drawbacks. One of the most significant drawbacks is that it's built on-top-of HTTP/1.1 and keeps the connection open. It leads to scaling problems when you have more users for your application. We have two ways to scale our application:
- Vertical scaling. You add more resources such as RAM/disk/CPU or buy a new server.
- Horizontal scaling. You add more servers. You can move a database, webserver, or something else to a different server. Sometimes you need to scale your application horizontally.
Horizontal scaling requires load balancing between the servers. Balancing HTTP traffic is easier than WebSocket traffic, and almost all load balancers such as Nginx, Envoy, or Istio balance traffic on L4 of the OSI model. It would be best to implement load balancing mechanisms on L7 when you work with WebSockets to have evenly loaded servers.
Furthermore, it would be best to keep in mind that networks are unreliable or third parties may close connections and your application needs to handle it gracefully. In addition, you need to have a persistent listener of incoming events, which leads to the situation when you need to have EC2/VPS or any other server to run your code, but this is a cost-ineffective solution.
Events API
The Slack Events API works differently. You need to have a web server that is be publicly accessible and an event handler implemented in your app. According to the documentation of the Slack Events API, you need to implement the following steps:
- Use their signing tokens for incoming requests.
- Handle the URL verification challenge by your app. The app needs to sign the incoming request and return the incoming challenge parameter.
The only thing we need to have is a web server with a simple REST API endpoint. It allows us to use various cloud features to run our bot and save money. For instance, we can use AWS Lambda, trigger it with API Gateway. The best part of this is that we can use the Free tier plan. That's why I'm a huge fan of the Events API from Slack.
Let's build our bot, huh?
Implementing the bot
We will use the Go programming language to build our bot. What we need:
- Configuration for the bot using 12factors.net. In that case we will use the envconfig package because of its simplicity.
net/http
package for local development and testing.- Ngrok to make our web app accessible from the internet.
- AWS Go SDK.
Implementing configuration
Let's create a config
package
It's always a good idea to have some tests.
We can check it by simply running go test ./…
Slack events API handler
We can start with the example taken from the Slack Go SDK because of its simplicity. We need to extend this example with the following parts:
- Make it configurable what message we want to send as welcome.
- Support of AWS Lambda since it has its SDK. To get support for Go we can use the algnhsa library. Check out the code below.
To start everything up we need cmd/mrrobot/main.go
:
Creating Slack bot
- Press Create New App button on Slack apps page.
- Click on From scratch and then input your bot name and choose a workspace to install the bot.
- Copy the
Signing Secret
and store it somewhere. You'll need it to configure AWS Lambda function. - Go to the
OAuth & Permissions
and generate access tokens underOauth Tokens for YOur Workspace
. You need theUser Oauth Token
when you want to send message from a user and theBot User Oauth Token
for the bot user. You'll need it to configure AWS Lambda. - Under the scopes add
chat:write
for both theBot Token
andUser token
scopes.
Deploying to AWS Lambda
- Sign in to AWS Console.
- Go to the Lambda section and press
Create function
button. - Choose
Author from scratch
input the name of the function. ChooseGo 1.x
for the runtime and architecturex86_64
and then create a function. - Open
Configuration
->Environment variables
. - Set your
Signing Token
toSLACK_SIGNING_SECRET
variable. - Set your welcome message to
WELCOME_MESSAGE
variable. - Set your bot token to
SLACK_BOT_TOKEN
variable. - Set
production
toENV
variable. - Go to the
Code
section and scroll down toRuntime settings
and changeHandler
fromhello
tomrrobot
.
Configuring AWS Gateway
- Create a new REST API.
- In the "Resources" section create a new
ANY
method to handle requests to/
(check "Use Lambda Proxy Integration"). - Add a catch-all
{proxy+}
resource to handle requests to every other path (check "Configure as proxy resource").
Final steps
You need to upload the zip archive with compiled binary to the AWS lambda. In
that case, make
can help us -
make
allows us to
automate operations since 1976. Also it always a great idea to have them
self-documented:
.PHONY: help
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
lint: ## Runs linter against the code
golangci-lint run ./...
test: ## Run tests locally
go test ./...
build_docker: ## Build docker image
docker build -t mrrobot .
build_linux: ## Build executable for linux system
GOOS=linux GOARCH=amd64 go build -o mrrobot cmd/mrrobot/main.go
zip: build_linux ## Build and create a zip archive for deploying to AWS lambda
zip main.zip mrrobot
- Run
make zip
. - Open your function on
AWS Lambda
. - Choose
Upload from
under the source code section. - Upload it and run.
- Choose your application on Apps page on Slack,
click on
Add features and functionality
and chooseEvent subscriptions
. - Insert URL of your API Gateway to the
Request URL
field, pass the verification step and clickSave
. - Open
Subscribe to bot events
and chooseteam_join
event and then pressSave
.
That's it. You can now invite a new member to your Slack and test the bot.
Conclusion and takeaways
As you can see the Slack Events API helps you to build bots and automate your routine. Also, if you just build a simple bot you don’t need to spend money on hosting.
Join the Ory Community Slack to see the bot in action and let us know what you think!