How to Add Phone Calling Bots to Slack with Python
Time to read: 6 minutes
Slack is awesome for text and emoji-based conversations with colleagues. However, sometimes it’s far easier to quickly answer a question over the phone. While Slack is just starting to add voice calling between users, there is no way to patch someone in by their good old telephone number. Let’s add phone calls to Slack by creating a bot with Python, Twilio and the Slack Real Time Messaging API.
Tools We Need
Our bot, which we’ll name callbot, requires a few libraries and APIs. To build our bot we need:
- Either Python 2 or 3
- pip and virtualenv to handle the Python application dependencies
- python-phonenumbers to ensure phone numbers are valid
Here’s a handy step-by-step guide to setting up Python, pip and virtualenv.
Our Twilio requirements are:
- A free Twilio account for testing your own phone number or an upgraded Twilio account to call any number
- One Twilio phone number with Voice calling capabilities
- A simple Twimlet to output TwiML for our phone calls
The Slack dependencies are:
- A free Slack account with a team on which you have API access or sign up for the Slack Developer Hangout team
- Official Python SlackClient code library built by the Slack team
- Slack API docs
- Slack Bot token
Ensure that Python version 2 or 3 is installed. We’ll 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.
Configuring Our Environment
Now that we know what tools we need, 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 something like this screenshot.
We’ll use the official slackclient API helper library to access their API to send and receive messages from a Slack channel. Install the slackclient and Twilio helper libraries along with phonenumbers into your virtualenv with the pip
command:
We next need to obtain an access token for the Slack Bot and our Twilio API credentials.
Slack Real Time Messaging 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.
After you have signed in go to the Bot Users page.
Give your bot the name “callbot” and click the “Add bot integration” button.
The page will reload and you’ll see a new generated access token. You can also change the logo to a custom design, like I did with this bot by giving it the Twilio logo.
Scroll down and click the “Save Integration” button. Your bot is now ready to access 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_BOT_TOKEN
:
Awesome. We’re authorized to use the Slack API as a bot. Now we just need a Twilio account and credentials to start handling phone calls.
Twilio Phone Numbers
We need access to the Twilio API to make phone calls from our application. Sign up for a free Twilio account or log into your existing account if you already have one. Our Slack bot will only dial outbound phone calls. Therefore, nothing needs to change on the number configuration screen.
With our phone number in hand, go to the Console Dashboard screen and look for your Twilio Account SID and Auth Token:
As we did earlier with the SLACK_BOT_TOKEN
, we will use the newly-exported environment variables in our Python script.
On the command line, export Twilio credentials as an environment variables:
There is one more bit of information we need: our bot’s ID in Slack. Next we’ll write a short script to snag that from the Slack API.
Obtaining Our Bot’s ID
Time to write some Python code! We’re going to get warmed up by writing a quick helper Python script to get callbot’s ID because it varies based on the Slack team. We need the callbot ID because it will allow our application code to determine if messages parsed from the Slack Real Time Messaging API are directed at our bot.
This script will also help test that our SLACK_BOT_TOKEN
environment variable is set properly. Create a new file named get_bot_id.py
with the following code.
The above code imports SlackClient and instantiates it with our SLACK_BOT_TOKEN
. When the script is executed by the python
command we hit the API for a list of Slack users and get the ID for the one that matches the name callbot.
We only need to run this script once to obtain our bot’s ID.
When we run the script, we’ll get a single line of output with our Bot’s ID.
Copy the ID and export it as an environment variable named BOT_ID
.
Again, the script only needs to be run once to make sure we have the appropriate bot ID for our Slack team. Now we’re ready to code up our Python application that’ll run our callbot.
Coding Our CallBot
We have all the appropriate environment variables set for our Python code to appropriately use the Twilio and Slack APIs. Create a new file named callbot.py
and add the following imports.
The os
and SlackClient
imports should look familiar because we used them earlier in the get_bot_id.py
script.
With our dependencies imported we can use them to grab those environment variable values and instantiate the Slack and Twilio clients.
Our code instantiates the SlackClient with our SLACK_BOT_TOKEN
from an environment variable. TwilioRestClient
automatically pulls the TWILIO_ACCOUNT_SID
and TWILIO_AUTH_TOKEN
from environment variables with those exact names during its declaration. Continue the Python script with the following lines of code that will handle starting the bot.
SlackClient connects to the Slack Real Time Messaging API WebSocket connection then continuously loops and parses messages from the Messaging firehose. If any of those messages are directed at our bot, a function named handle_command
will determine what to do with the command.
Above the Python code we just wrote, add two new functions to parse Slack output and handle commands.
The parse_slack_output
function takes messages from Slack and determines if they are directed at our Slack CallBot. If a message starts with a direct message to our bot ID, then we know our bot needs to handle a command. handle_command
function is currently a stub function that either passes back a generic help message or has a stub within a condition if the command starts with “call”.
With most of our code in place, let’s test our CallBot by using the python callbot.py
command.
Go into the Slack channel with CallBot and enter “@callbot: call 14045551234 14155550909” (or replace these two numbers with your own test phone numbers). CallBot will answer back but not really dial numbers.
Our CallBot can respond to commands but it doesn’t place calls yet. We can fix that by adding two new functions named call_command
and validate_phone_numbers
. handle_command
can then invoke call_command
instead of just serving as a stub. Change your code to match the entire callbot.py
application below. Code changes from our previous version are highlighted.
The above two new functions, call_command
and validate_phone_numbers
, do the bulk of the work for CallBot. validate_phone_numbers
uses the phonenumbers Python library to ensure each phone number is parsable and conforms to at least one phone number type from around the world. call_command
ensures that at least two phone numbers are specified and calls validate_phone_numbers
for some additional checks. If every phone number is valid then call_command
invokes the Twilio Voice API to place each outbound phone call.
Time to run our bot now that all of our code in place. On the command line, execute python callbot.py
.
In Slack, start giving CallBot commands. You can start testing it with invalid phone numbers. If we specify an invalid phone number format for one or more of the numbers, we’ll get back a helpful error message.
Now try with two legitimate phone numbers.
Wait a second for the incoming call…
Now we’re on a conference call with one or more people we’ve dialed through Slack. Time to hash out those questions over the phone so we can get back to coding.
Wrapping Up
Woohoo, our new callbot is all done! Actually, there so much more that can be done with the Slack and Twilio APIs. Here are several more ideas to try out now that you’ve got the basics down:
- Implement a persistent backend like PostgreSQL and use it to store a phone number for each username
- Add SMS capability to the bot
- Use Twilio Lookup to determine if a number is truly valid instead of just parseable
- Boost the parser with better parsing and natural language processing so it’s more natural for Slack users to interact with
Questions? Drop a comment below or contact me on these channels:
Twitter: @mattmakai
GitHub: mattmakai
Email: makai@twilio.com
Twitch (Python & Swift live coding): Team Twilio
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.