How to Build an SMS Slack Bot in Python

Slack powered SMS bots.

Bots can be a super useful bridge between Slack channels and external applications. Let’s code a simple Slack bot as a Python application that combines the Slack API with the Twilio SMS API so a user can send and receive Slack messages via SMS.

Tools We Need

Our bot, which we’ll call “twiliobot”, requires Python, Slack and Twilio APIs and libraries. To write and run our Python code we need:

Here’s a handy step-by-step guide to setting up Python, pip, virtualenv and Flask.

The Slack dependencies are:

Our Twilio requirements include:

Make sure Python version 2 or 3 is installed now. We will configure everything else throughout the remainder of this tutorial.
You can follow along by writing the code in this post or skip ahead to the finished project by cloning the companion GitHub repository.

Setting Our Environment

Now that we know what tools we need to use, go to the terminal (or Command Prompt on Windows) and change into a directory where you want to store this project. Within that directory, create a new virtualenv to isolate our application dependencies from other Python projects you’re working on.

Activate the virtualenv:

Depending on how your virtualenv and shell are set up, your prompt should look like this.

twiliobot-activate.png

We’ll use the official slackclient API helper library built by Slack to access their API to send and receive messages from a Slack channel. Install the slackclient and Twilio helper libraries along with Flask into your virtualenv with the pip command:

We next need to obtain an access token for our Slack team and our Twilio API credentials.

Slack Web API

Slack provides programmatic access to their chat application through a web API. Open up the landing page for the Slack Web API and sign up to create a Slack team or sign into your existing account.  You can create a new team for free if you don’t have admin privileges on an existing team.
slack-api-sign-in.png

After you have signed in scroll down on the web API page to where you see a button to generate test tokens.
generate-test-tokens.png

Generate a test token for a Slack team on which you have administrative privileges.

We need that test token so our Python code is authorized to call the Slack API. A common practice for Python developers is to export secret tokens like our Slack token as environment variables. Export the token with the name SLACK_TOKEN:

Switch into our Python environment set up so we can try out the API. With your virtualenv still active, fire up the Python REPL with the python command:

Let’s ensure our API token is working with a test – type the following code at the REPL prompt.

The REPL should return back something like the following dictionary if your API test with the token was successful:

If you get back {u'ok': False, u'error': u'invalid_auth'} then double check that you copied the Slack token correctly into the second line entered on the REPL.

Enter one more quick test for our authentication with another line of code in the REPL:

You should see another dictionary like this one:

Awesome, we’re authorized to start using the Slack API through our account. We just need a Twilio account and credentials to create our bot!

Sending SMS Messages to Slack

We need access to the Twilio API to send and receive SMS messages. Sign up for a free Twilio account or log into your existing account if you already have one. When you sign up for a new account you’ll be given a Twilio phone number. If you already have an account you can use your existing Twilio phone number or upgrade your account to buy a new number. Click the phone number you want to use for the bot to configure it.

slack-sms-bot.png

Twilio needs a reachable URL to send an HTTP POST request to when an SMS is sent to our Twilio phone number. During development our application is typically running on our local server which cannot be reached from anywhere except our local machine.

To expose my local web server via an externally-accessible domain I typically use ngrok since it’s easy, free and awesome.

Download ngrok and run it with this command:

You will get a subdomain that forwards requests to that subdomain to your localhost server.

ngrok.png

Copy and paste the https version of the Forwarding URL plus “/twilio” into our phone number configuration under “A messages comes in” as shown here:

configure-number.png

Keep a note of your Forwarding URL, in this case https://9e6d3d38.ngrok.io as we’ll also need that for our Slack outgoing webhook in a future step.

Next, go to the Console Dashboard screen and look for your Account SID and Auth Token:

console-account-sid.png

Copy and paste the Account SID and Auth Token to export them as environment variables.

If you’re still in the Python REPL exit it with a quick CTRL-d or use the exit() command. Back on the command line, export Twilio credentials as an environment variables:

As we did earlier with the SLACK_TOKEN, we will use the newly-exported environment variables in our Python script.

Coding Our Python-Powered Bot

Dive into your favorite text editor such as Vim, Emacs or Sublime Text so we can cut some new Python code. Create a new file named twiliobot.py and start it with the following import statements.

The os module will be used to pull the SLACK_TOKEN, TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN environment variables we exported on the command line. From the Flask framework we import the standard Flask class to instantiate our app, along with the request and Response objects to obtain HTTP input and return appropriate HTTP responses.

The SlackClient import should look familiar as the same line we wrote earlier on the REPL. We’ve also got a couple of new Twilio helper library imports so we can generate TwiML and send outgoing text messages.

With our dependencies imported we can use them to grab those environment variable values and instantiate the Flask app along with Slack and Twilio clients.

Instantiating TwilioRestClient automatically pulls the TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN from environment variables with those exact names.

Add a function named twilio_post to the Python file to handle an incoming HTTP POST request. This POST request will come from Twilio

Add a convenience function so we can test whether app works properly and a main function to start the Flask development server when we invoke the script with the python command.

Nice! Fire up the Flask app to test it out. Start the Flask app with the python twiliobot.py command. We’ll see debugging output that indicates the development server is running.

Time to give our app a try. Send a text message to your Twilio phone number. The SMS will go to Twilio, Twilio will send an HTTP POST request to the ngrok URL you configured in the phone number configuration screen. Then ngrok will forward the POST request to your local machine, which will hit your running twiliobot.py Flask development server. Our Flask web app then uses slackclient to post a message to our Flask channel as twiliobot, just like we see here:

twiliobot.png

Cool, we can send messages to Slack! Next let’s get important messages out of Slack and sent to our phone via SMS.

Receiving Slack Messages via SMS

Our bot can take SMS messages coming to our Twilio phone number and post them as messages to a Slack channel. However, what if we want to see when someone “@” mentions “twiliobot” in a channel? We can set up an outgoing Slack webhook that’ll alert our Python application via an HTTP POST request.

Stop the Flask development server with “Ctrl-C” and modify the existing twiliobot.py file. Add the new highlighted line and the highlighted function shown below.

Go to the Slack Outgoing Webhooks page then click the “outgoing webhook integration” link as shown below.

Scroll down to the Integration Settings section. Select “#general” as the channel to listen on. Enter “@twiliobot” within the “Trigger Word(s)” value. Copy your ngrok Forwarding URL plus “/slack” into the URL(s) text box.

slack-webhook-secret.png

Copy the generated Token in the field below the URL(s) section. Scroll down and press the “Save Settings” button. In case you are wondering, yes, I regenerated my own token after this screenshot. So, no, you can’t use it.

Export the Slack token as a new environment variable:

Restart your Flask server because it’s time to test out receiving messages via SMS!

Go to your Slack #general channel. You should see that the outgoing webhook integration has been added to the channel.

outgoing-to-twilio.png

Send a message mentioning twiliobot like “@twiliobot hola!” and hit enter. Check your phone:

hola.png

Sweet! That’s pretty simple output but we have a basic way to receive messages from one or more channels and can add whatever Python code we want to handle the input. This is a great hook for expanding our bot or sending messages to another service for processing.

Wrapping it up

Woohoo, all done! Well actually, there’s a whole lot more you can do with the Slack and Twilio APIs. Here are several more ideas to try out now that you’ve got the basics down:

  1. Add natural language processing (NLP) to the Python Flask web app
  2. Try a different Slack client or ditch the helper library entirely and use the Requests library to implement retry logic
  3. Write and customize a more complicated Slack bot

If you want to learn even more about the Slack API and bots, come out to SIGNAL in San Francisco on May 24th and 25th where I’ll be giving a talk called “R2-D2 or Skynet? Combining Slack Bots with the Twilio API” with one of Slack’s developers, Don Goodman-Wilson. You can use the promo code makai20 when you register for 20% off the ticket price.

Questions? Drop a comment below or contact me on these channels:

Twitter: @mattmakai
GitHub: mattmakai
Email: makai@twilio.com
Twitch (live coding along with other Twilio Developer Evangelists): Team Twilio

  • Vassili

    you should incorporate Botpages Inspector to track analytics for the bot: https://inspector.botpages.com/signup

  • converge0

    Hi,

    I got successfully until the last step before “Receiving Slack Messages via SMS.” It seems like my Slack authentication doesn’t seem to be working properly. When attempting to run the twiliobot.py the error Message was something like “failed to import SlackClient.” (I will get an exact text copy of error message soon). I did a printenv to see the currently exported variables and they appeared to be okay.

    As this article was posted in 2016 I am thinking that maybe the slack and twilio authentication methods have changed. Slack doesn’t have an option for test tokens as displayed in your printscreen. Only the ability to register the app or request legacy tokens. FYI I attempted this using the legacy tokens as I assumed that may be correct.

    I got flask and ngrok running and they are receiving 404 and at times 502 errors when text message is sent to the phone number set up in twilio. I couldn’t get twiliobot.py to run so I ran the __init__.py file but still didn’t work.

    Are there any additional tests or troubleshooting tips you can give for debugging? I can provide additional information upon request.

    Would you be able to offer any input on whether the authentication method demonstrated above in this article for building an sms slack bot with python is still applicable given the possibly updated authentication methods for slack and twilio?

    • hey converge, looks like we already have an email thread going, but posting here in case others have trouble with this post from last year. gist is, make sure your virtualenv is activated and includes the appropriate installed dependencies from the requirements.txt file. also use the 5.7.0 version of the Twilio Python helper library or use version 6.0.0+ and change the import to “from twilio.rest import Client” instead of TwilioRestClient