Slack is a messaging app that has exploded in popularity among all sorts of teams. One of the things that makes Slack so compelling is that it integrates well with all kinds of other applications and services — a perfect fit within API space.

Slack comes with a slew of standard integrations, but it’s also really easy to build your own. Typical Slack integrations range from posting notifications to more sophisticated and interactive bots. In this article, we’ll use the Slack API Node.js library to build our own bot, and explore Wit.ai API and other tools that use natural language processing to analyze and respond to human-inputted text. We’ll also talk to some experts in the bot space for added insight. By the end, you’ll have an introductory toolset for building your own useful team bot with a dash of personality.

What is a Bot?

A bot is a “software robot.” There are bots for all kinds of applications, some of which accept inputs in a conversational format to help automate a variety of tasks for users. Some of the most prominent examples of bots are Apple’s Siri or Microsoft’s Cortana. Bots are not a new concept, but they’re starting to become mainstream.

Many bots are now being developed for Slack. Examples include Meekan for scheduling meetings, and Nestor for calling you an Uber or finding you a restaurant. There are even bots for playing poker, Jeopardy!, and oldschool adventure games. My experience has been from developing a bot for getting graphic design tasks done.

“Slack is an operating system for a whole new class of apps.”

Bots can enable new ways of working and entirely new classes of applications. They can make your application more useful, more usable, and more natural. Some users even feel more comfortable using a conversational bot than other kinds of interfaces. To operate and integrate with various systems, bots naturally rely on many APIs:

“Bots are creatures of almost pure API. It is the flesh and blood from which they are created. They speak and listen through messaging APIs, and carry out actions via other APIs.” —Ben Brown | XOXCO software design firm

Getting Started

For this tutorial, we’ll be using Node.js to build a bot that integrates with Slack. Make sure to download and install Node.js before continuing.

Slack has a variety of APIs that suit various purposes, but the one that is most useful for writing bots is the Slack RTM (Real Time Messaging) API.

To write our bot using the Slack RTM API, we’ll be using the official Slack client for Node.js, which can be installed using NPM. Learn more about NPM.

npm install --save slack-client

Setting up a Bot User

Before diving into code, you’ll need to create a new bot user integration in your Slack account. Give your bot a name and avatar — this is a good opportunity to start thinking about the kind of personality you want your bot to have. More on that later!

Copy the generated API token, and now let’s get started on our bot.

Basic Structure

The basic structure of our bot will resemble the following. Make sure to paste in your Slack bot’s API token.

var SlackClient = require('slack-client'); var slackClient = new SlackClient("PASTE YOUR BOT API TOKEN HERE"); var bot; // Track bot user .. for detecting messages by yourself slackClient.on('loggedIn', function(user, team) { bot = user; console.log("Logged in as " + user.name + " of " + team.name + ", but not yet connected"); }); slackClient.on('open', function() { console.log('Connected'); }); slackClient.on('message', function(message) { if (message.user == bot.id) return; // Ignore bot's own messages var channel = slackClient.getChannelGroupOrDMByID(message.channel); channel.send('Hello world!'); // More goes here later.. }); slackClient.login();

An important piece of housekeeping here is to detect the bot’s own messages to ensure it doesn’t reply to itself and get into a loop. This is a good start, but our bot isn’t very useful yet. All it does is reply to any message it sees with ‘Hello world!’.

Handling Simple Commands

One of the simplest things a bot can do is understand a set of basic commands. The benefits are that they’re simple to parse and will be familiar to users that have used a command line prompt.

This is pretty simple stuff, but there’s a few extra details that are worth paying attention to. For demonstration purposes we’re using the 99designs Tasks client for Node.js in this example.

if (message.text == 'create') { slackClient._send({ type: "typing", channel: message.channel }); api.create({ body: 'Please edit this image', urls: ['http://i.imgur.com/YryoTju.jpg']}, function(err, task) { if (err) { return channel.send('Something went wrong') } channel.send("Success! Created: " + task); }); } elseif (message.text == 'list' || message.text == 'status') { slackClient._send({ type: "typing", channel: message.channel }); api.myTasks(function(err, results) { if (err) { return channel.send('Something went wrong') } var list = results.items.join("

"); channel.send("Your Tasks:

" + list); }); } elseif (message.text == 'help') { channel.send("Possible commands are: create, status, help, ..."); } else { channel.send("Unknown command. Possible commands are: create, status, help, ..."); }

It’s a good idea to be forgiving — allow synonyms and aliases for commands. It’s also helpful to provide useful help text and guidance when users make mistakes. You could take this further and consider detecting and correcting typing mistakes.

Something extra is using Slack’s typing indicator for responses that take some time. The typing indicator is usually for when a human starts typing to let other human users know that they’re responding.

A bot is a computer program and doesn’t type messages like a human, so a typing indicator may seem pointless. However, giving users some instant feedback really helps reassure them when the bot is taking some time to respond, such as when making API calls or doing some processing that takes a few seconds. It makes the bot feel human in a subtle way.

It’s not currently officially implemented in the Slack node.js library, but it can be worked around by calling the private _send method as seen in the example above. In addition, depending on the type of bot you’re writing, it may also be useful to handle file uploads.

if (message.upload) { channel.send("This file was uploaded: " + message.file.url); }

Making Responses More Useful (and Better Looking!)

Plain text responses can go a long way, but there are many opportunities to respond in more informative and meaningful ways using Slack’s formatting options.

For example, Datadog, a cloud monitoring service, makes excellent use of chart images to show server monitoring statistics:

The poker bot mentioned earlier is able to show poker hands using emoji and clever use of image attachments.

Take a look at the Slack formatting and attachments documentation for more details on what’s possible.

Making Conversation

Part of what makes bots really interesting is that you can give them some personality.

Ideally, you want your bot to feel like a valuable part of your team and reflect your company’s culture. Making your bot sound like a real person can be easy or difficult depending on how realistic you want it to be.

Acting Natural

Natural language can open up many possibilities for new types of applications as well as enable users to combine data and services in interesting ways. One of the best examples is Wolfram Alpha, which combines a computation engine and a massive database of knowledge about the world with a natural language user interface.

When it’s done as well as this, it feels like magic.

It’s also something that can introduce significant complexities and is an open area of research. Thankfully, there are services to help take care of all the hard work. One of my favorites is Wit.

Wit is a semantic analysis tool designed specifically for developing “bots” and “smart agents”. You give Wit an example of a sentence you would like it to understand, and it has the capability to interpret meaning and intent, even if natural language is used.

Using the Wit API

Install the Wit Javascript library

npm install --save node-wit

var wit = require('node-wit'); var ACCESS_TOKEN = "YOUR WIT ACCESS TOKEN HERE"; wit.captureTextIntent(ACCESS_TOKEN, "What's the weather in Melbourne?", function (err, res) { console.log("Response from Wit for text input: "); if (err) console.log("Error: ", err); console.log(JSON.stringify(res, null, " ")); });

Here’s an example of what you get back from Wit:

{ "msg_id": "17c81127-5c02-4646-9d9d-ba72bccd03b2", "_text": "What's the weather in Melbourne?", "outcomes": [ { "_text": "What's the weather in Melbourne?", "intent": "weather", "entities": { "location": [ { "suggested": true, "value": "Melbourne", "type": "value" } ] }, "confidence": 1 } ] }

The idea is to specify the kinds of “intents” you want your bot to understand. For example, a weather intent is able to understand a variety of natural language expressions related to asking what the weather is like. A home automation “intent” would be able to understand expressions about switching your lights on and off or controlling your air conditioner.

Wit takes care of parsing sentences to work out the intent as well as any entities that were referred to. There are a variety of community contributed “intents” that are a great starting point and can be modified further to suit your needs.

Have a look at the Wit documentation for more details.

Avoiding the Uncanny Valley

One of the potential downsides of using this kind of sophisticated natural language understanding is falling into the “Uncanny Valley”. The uncanny valley is a term used to describe when an artificial resemblance — be it CGI or Cleverbot — looks, feels or moves almost — but not exactly— like a natural being. There’s just something slightly off.

Ironically, a bot that is programmed to act like a cartoon character can feel more natural than something that is smarter and “almost human”. There’s a strange effect where making a bot too smart can also make it feel unnatural and creepy. This can also lead to frustration when a bot is unable to understand or behaves unpredictably and it’s not clear to the user why.

A principle that many bot writers follow to avoid this is the idea of “being as smart as a puppy”.

“Making smart things that don’t try to be too smart and fail, and indeed, by design, make endearing failures in their attempts to learn and improve. Like puppies.”

So in some ways it can be better to keep your bot simple and to make it clear the bot isn’t human. The goal here isn’t to pass the Turing test and trick people into thinking your bot is human — it’s more important for your bot to be a useful and reliable tool for your team.

Ben Brown, of XOXCO, a firm that specializes in creating bots for Slack teams, agrees that making your bot less human can make it less creepy, more relatable, and even comical for your team:

“Our approach is for our bots to avoid trying to be too human. They will never claim to be a real person, and when confronted with troubling input, they will basically do what R2D2 does when he runs into a staircase – beep, whir and say “I am just a robot, I can’t do everything!” This is in large part based on Matt Jones’ maxim, and also the Hitchhikers Guide to the Galaxy gag where the “Genuine People Personality” system built into the robots is a hilarious failure.”

Good Conversation

Even if your bot doesn’t pretend to be human, you can still give it loads of personality. Much of the advice for making good conversation in social situations can also be applied to the design of your bot.

A good place to start is to follow Grice’s Maxims for conversation, which are what social scientists use to describe how real people typically behave in conversations.

The Jack Principles

Jellyvision is a game development company that set out to make a quiz game with a computer-human interface that was realistic and fun. They developed a set of principles dubbed “The Jack Principles” [PDF], which are aimed to be a practical set of guidelines for designing human-computer interfaces.

The three main principles are:

Maintain Pacing — Principles that help a designer maintain the pacing of an interactive conversation interface program. Create the Illusion of Awareness — Principles that help a designer create the illusion that the characters on the screen are actually aware of the person sitting in front of the screen. Maintain the Illusion of Awareness — Principles that a designer must follow to maintain the illusion that the characters are actually aware of the person sitting in front of the screen.

The key quality of this style of human-computer interface is described by Jellyvision as “cinematic and makes you feel like you’re really talking to someone”.

There’s a bit of skill in designing a good bot — it’s very different to the kind of user interface most people are used to. Help by giving your bot some small touches such as a sense of humour and the ability to take a compliment.

Bots into the Future

As more and more teams embrace group messaging systems like Slack, developing natural language empowered software bots to automate tasks seems like an eventual next evolution, and perhaps a key productivity advantage. According to Brown, bots will only become more and more ubiquitous:

“…bots will grow to take over a lot of features that apps and websites currently provide. Bots are a great way to delivery a wide variety of content and features on small screens. I think in the future, we’ll all have personal bots as well as work bots that help us with our lives, automating common tasks and providing an interface to the exploding number of connected devices.”

Key Takeaways

Bots enable new kinds of applications Don’t overthink it. Keep it simple! Natural language can make your bot more powerful—but use with care.

Resources

A list of the helpful links mentioned throughout this article and more to help you get started:

[Disclosure: Dennis Hotson is an engineer at 99designs, whose API is referenced in an above code sample]