Botkit is designed to ease the process of designing and running useful, creative bots that live inside Slack, Facebook Messenger, Twilio IP Messaging, Microsoft Bot Framework, and other messaging platforms.
The Microsoft Bot Framework makes it easy to create a single bot that can run across a variety of messaging channels including Skype, Group.me, Facebook Messenger, Slack, Telegram, Kik, SMS, and email.
Built in to Botkit are a comprehensive set of features and tools to deal with any of the platforms supported by the Microsoft Bot Framework, allowing developers to build interactive bots and applications that send and receive messages just like real humans.
This document covers the Bot Framework implementation details only. Start here if you want to learn about to develop with Botkit.
Table of Contents
- Getting Started
- Bot Framework Specific Events
- Working with the Bot Framework
- Sending Cards and Attachments
- Typing Indicator
-
Install Botkit more info here
-
Register a developer account with the Bot Framework Developer Portal and follow this guide to register your first bot with the Bot Framework.
- You'll be asked to provide an endpoint for your bot during the registration process which you should set to "https:///botframework/receive". If your using a service like ngrok to run your bot locally you should set the "" portion of your endpoint to be the hostname assigned by ngrok.
- Write down the App ID and App Password assigned to your new bot as you'll need them when you run your bot.
-
By default your bot will be configured to support the Skype channel but you'll need to add it as a contact on Skype in order to test it. You can do that from the developer portal by clicking the "Add to Skype" button in your bots profile page.
-
Run the example bot using the App ID & Password you were assigned. If you are not running your bot at a public, SSL-enabled internet address, use the --lt option and update your bots endpoint in the developer portal to use the URL assigned to your bot.
app_id=<MY_APP_ID> app_password=<MY_APP_PASSWORD> node botframework_bot.js [--lt [--ltsubdomain CUSTOM_SUBDOMAIN]]
- Your bot should be online! Within Skype, find the bot in your contacts list, and send it a message.
Try:
- who are you?
- call me Bob
- shutdown
Since the Bot Framework delivers messages via web hook, your application must be available at a public internet address. Additionally, the Bot Framework requires this address to use SSL. Luckily, you can use LocalTunnel to make a process running locally or in your dev environment available in a Bot Framework friendly way.
When you are ready to go live, consider LetsEncrypt.org, a free SSL Certificate Signing Authority which can be used to secure your website very quickly.
Once connected to the Bot Framework, bots receive a constant stream of events.
Normal messages will be sent to your bot using the message_received
event. In addition, several other events may fire, depending on the channel your bot is configured to support.
Event | Description |
---|---|
message_received | A message was received by the bot. Passed an IMessage object. |
conversationUpdate | Your bot was added to a conversation or other conversation metadata changed. Passed an IConversationUpdate object. |
contactRelationUpdate | The bot was added to or removed from a user's contact list. Passed an IContactRelationUpdate object. |
typing | The user or bot on the other end of the conversation is typing. Passed an IEvent object. |
In addition to the event specific fields, all incoming events will contain both user
and channel
fields which can be used for things like storage keys. Every event also has an address field. The user
field is just a copy of the events address.user.id
field and the channel
field is a copy of the events address.conversationId.id
field.
Other notable fields for incoming messages are the text field which contains the text of the incoming message, the attachments field which would contain an array of any images sent to the bot by the user, the source field which identifies the type of chat platform (facebook, skype, sms, etc.) that the bot is communicating over, and the sourceEvent field containing the original event/message received from the chat platform.
Botkit receives messages from the Bot Framework using webhooks, and sends messages to the Bot Framework using APIs. This means that your bot application must present a web server that is publicly addressable. Everything you need to get started is already included in Botkit.
To connect your bot to the Bot Framework follow the step by step guide outlined in Getting Started.
Here is the complete code for a basic Bot Framework bot:
var Botkit = require('botkit');
var controller = Botkit.botframeworkbot({
});
var bot = controller.spawn({
appId: process.env.app_id,
appPassword: process.env.app_password
});
// if you are already using Express, you can use your own server instance...
// see "Use BotKit with an Express web server"
controller.setupWebserver(process.env.port,function(err,webserver) {
controller.createWebhookEndpoints(controller.webserver, bot, function() {
console.log('This bot is online!!!');
});
});
// user said hello
controller.hears(['hello'], 'message_received', function(bot, message) {
bot.reply(message, 'Hey there.');
});
controller.hears(['cookies'], 'message_received', function(bot, message) {
bot.startConversation(message, function(err, convo) {
convo.say('Did someone say cookies!?!!');
convo.ask('What is your favorite type of cookie?', function(response, convo) {
convo.say('Golly, I love ' + response.text + ' too!!!');
convo.next();
});
});
});
Argument | Description |
---|---|
settings | Options used to configure the bot. Supports fields from IChatConnectorSettings. |
Creates a new instance of the bots controller. The controller will create a new ChatConnector so any options needed to configure the chat connector should be passed in via the settings
argument.
Generally speaking your bot needs to be configured with both an appId and appPassword. You can leave these blank but then your bot can only be called by the Bot Framework Emulator.
Argument | Description |
---|---|
port | port for webserver |
callback | callback function |
Setup an Express webserver for
use with createWebhookEndpoints()
If you need more than a simple webserver to receive webhooks, you should by all means create your own Express webserver! Here is a boilerplate demo.
The callback function receives the Express object as a parameter, which may be used to add further web server routes.
This function configures the route https://_your_server_/botframework/receive
to receive webhooks from the Bot Framework.
This url should be used when configuring Facebook.
One of the more complicated aspects of building a bot that supports multiple chat platforms is dealing with all the various schemes these platforms support. To help ease this development burden, the Bot Framework supports a cross platform card & attachment schema which lets you use a single JSON schema to express cards and attachments for any platform. The Bot Frameworks channel adapters will do their best to render a card on a given platform which sometimes result in a card being broken up into multiple messages.
The frameworks attachment schema lets you send a single image/file using contentType
and contentUrl
fields:
bot.reply(message, {
attachments: [
{
contentType: 'image/png',
contentUrl: 'https://upload.wikimedia.org/wikipedia/en/a/a6/Bender_Rodriguez.png',
name: 'Bender_Rodriguez.png'
}
]
});
Rich cards can be expressed as attachments by changing the contentType
and using the content
field to pass a JSON object defining the card:
bot.reply(message, {
attachments: [
{
contentType: 'application/vnd.microsoft.card.hero',
content: {
title: "I'm a hero card",
subtitle: "Pig Latin Wikipedia Page",
images: [
{ url: "https://<ImageUrl1>" },
{ url: "https://<ImageUrl2>" }
],
buttons: [
{
type: "openUrl",
title: "WikiPedia Page",
value: "https://en.wikipedia.org/wiki/Pig_Latin"
}
]
}
}
]
});
The full list of supported card types and relevant schema can be found here
There may be times where the Bot Frameworks cross platform attachment schema doesn’t cover your needs. For instance, you may be trying to send a card type not directly supported by the framework. In those cases you can pass a message using the platforms native schema to the sourceEvent
field on the message. Examples of this can be found here (note: you should use sourceEvent
instead of channelData
and you don’t need to worry about the from & to fields, these will be populated for you when you call bot.reply()
.)
You can easily turn on the typing indicator on platforms that support that behaviour by sending an empty message of type "typing":
bot.reply(message, { type: "typing" });