Making BotFramework Bots Chainable and Semantic


The purpose of this tutorial is to demonstrate how to make a BotFramework bot chainable and semantic.


The instructions in this document assume that you’ve already created a BotFramework bot and an organization in the Workspace portal. If you need information on how to create a BotFramework bot and an organization with a botlet underneath it, see Getting Started with the Azure Bot Service.

Use Case

A developer has created Cortana skills in BotFramework and has heard the announcement that you can take BotFramework bots and make them chainable and semantic. The developer wants to know how to do this. Before we begin to explore how to make a BotFramework bot chainable and semantic, you should know what it means to build a skill semantically and what are the two levels of chainability.

Building a skill semantically

A BotFramework bot or botlet becomes a skill once it is published to a channel. A skill built semantically means that it will have a set of actions that consumes and produces entities. It will access the knowledge base where the search layer allows your skill to search the set of actions that control the user intents and entities. This means that your smart skill can execute its function without any user input. The actions can display content in the canvases of the channels they are published to.

Two levels of Chainability

  • Botlet chainability is developer facing because developers explicitly chain botlets together.
  • Skills chainability is user facing because users implicitly chain skills together in Cortana to make a unified experience.

As an example, a user invokes Cortana to find a restaurant, make a dinner reservation, and orders a taxi to go to the restaurant.

For both levels of chainability, there are three basic steps that you must do to make a BotFramework bot chainable.

  1. Register your BotFramework bot in the Store.
  2. Create a botlet in the Workspace that wraps your BotFramework bot.
  3. Define the actions of your BotFramework bot.

Step 1. Registering your BotFramework Bot in the Store

The steps below describe how to register and connect an existing BotFramework bot to the Store. To perform this task, you must meet the following prerequisites.

  • Have a Microsoft Account (MSA) registered in the BotFramework portal and the Store
  • Have one organization and one botlet under the organization created in the Workspace portal
  • Have a BotFramework bot registered in the BotFramework portal
  1. Visit the Bot Framework portal and sign in with your Microsoft account (MSA) credentials.
  2. Click My bots in main navigation ribbon or click Create a bot or skill.
alternate text
  1. Under My bots, select the bot that you want to register into the Knowledge Store Workspace.
alternate text
  1. Under Connect to channels, click Edit.

Note: If you do not have a BotFramework bot connected to the Cortana channel, refer to steps 5a through 5b for instructions on how to add the Cortana channel and register it in the Store.

alternate text

  1. To add the Cortana channel to your BotFramework bot, scroll down the page and click Cortana displayed under Add a feature channel.
alternate text
  1. Scroll down to Discovery and Management and click an organization from the drop-down list, and then click Register.
alternate text


If you do not see your organization in the drop-down list, it means that you did not create one in the Workspace. For more information about creating an organization in the Workspace, see: Creating an Organization.

Omit this step if you already have an account registered in the Store and an organization created in the Workspace. Proceed to step 5 below.

  1. After the Bot Framework bot has been registered in the Store, click Manage.
alternate text

Note: Upon clicking Manage, this will open the Workspace portal and the BotFramework bot will display with the Overview menu tab showing the botlet’s properties.

At this point, your BotFramework bot is connected to Cortana and can serve as a stand-alone skill. However, if you want to create a complete chainable experience, follow the next two steps. It is here that you can add logic to your botlet you create.

Step 2. Creating a Botlet in the Workspace

Botlets are the building blocks of a conversational flow. They contain part of the flow logic. They are reusable and can be chained together to create a more complex user experience. To wrap a botlet to a BotFramework bot, you must first have an organization created in the Workspace.

If you want information on how to create an organization and a botlet underneath it starting from the BotFramework portal, see Getting Started with the Azure Bot Service for more details.

After you’ve created a botlet that wraps your BotFramework bot, you can now add a line of Semantic Composition Language code to define its actions.

Adding SCL Code to your BotFramework Bot

Now that you have a botlet created in the Workspace, you are now at the point where you can call your BotFramework bot and use the entities that get returned. In this example, we are going to enter the following SCL code in the Code Viewer.

CALL “botframework.helper”, “execute”, bot_id = “demobot.my_demo_bot”

To call your BotFramework bot, go to the Code Viewer of the botlet created back in Step 2:

In the Code Viewer pane, enter your SCL Code and then click Save.

alternate text

The purpose for having this botlet shell is to create a wrapper around the BotFramework bot that can interpret raw data that is returned by this bot. Actual interpretation and use of the created entity types are shown below.

Analyzing BotFramework Bot SCL Code

Making a CALL to the BotFramework bot references the organization and botlets in the Workspace. In this section, we are going to describe the different ways to use BotFramework bots in your code depending on the scenario.


These are just a few code samples that demonstrate how to make BotFramework bots chainable and semantic.

For more details about SCL, see Semantic Composition Language.

To see a list of SCL reference commands, see SCL Commands.

For more information about SCL system variables, see: System Variables.

Code Sample:

1  CALL "botframework.helper", "execute", bot_id = "demobot.my_demo_bot"
2  SET last_message = CALL_RESULT.last_message
3  CALL "botframework.helper", "extract_entities", activities=last_message STORE  result
4  SET entities = result.entities

And now we are going to analyze the sample code line-by-line.

Executing the Whole Conversation

CALL "botframework.helper", "execute", bot_id = "demobot.my_demo_bot"

When you call line 1, it will execute the whole conversation that was programmed in BotFramework. It will then end and will return the whole conversation back to the botlet. The parameters are listed below.

bot_id is a reference to the organization being called, which it is demobot, and the botlet under it is my_demo_bot.

Giving Back Control to the Whole Conversation

SET last_message = CALL_RESULT.last_message

Line 2 gives control back to the whole conversation. If you want to extract something from the conversation, you can do this from the last_message.

The last_message contains the list of activities sent on the last turn of the conversation with Bot Framework. This last message may be a list of activities. Activities are the way that Bot Framework communicates to Cortana.

Extracting Entities

CALL "botframework.helper", "extract_entities", activities=last_message STORE  result

SET entities = result.entities

The BotFramework bot returns your raw data. In order to semantically chain it and pass it to other botlets and skills, they need to be represented as entity types.

Botframework.helper’s method “extract_entities” does this for you and returns a list of entities that can be further consumed (i.e., in the code sample stored in the entities variable).

Step 3. Defining Semantic Actions

Semantic actions make your skill chainable. BotFramework bots by nature are not semantic meaning that they do not consume and return structured entities. Still, there are some workarounds that can make them interact like semantic elements.

The steps below describe how to create an action on a botlet.

Creating an Action

Actions are the interfaces for botlets and services to allow them to be chained together. Actions take entity types as input and output parameters to ensure the semantic nature of the flow.

To create an action and add input and output parameters, refer to the steps below.

Note: There is no strict validation of entity types returned by BotFramework bots. In the steps below, ensure to use entity types that match the output of the bot.

  1. Select a botlet under the organization, and then click the Actions menu tab.
alternate text
  1. Enter a name and description of your action, and then click Add.
  2. Click Save.
  3. Click Add parameters, and then enter the input and output parameters.
alternate text
  1. Click Add after entering all your input parameters, and then click Add after entering all your output parameters.
  2. Click Save.

For more information on how to create actions on botlets and services, see: Services

Contacting Support

If you encounter a technical issue and you require assistance, please send an e-mail message to:


Action Parameter Descriptions

The following actions were used in the previous SCL code samples of the BotFramework bot.

  • execute
  • get_end_of_conversation
  • extract_entities

Refer to the following screenshot to see an example of how they are displayed in the Overview menu tab.

alternate text



The execute action calls your BotFramework service and executes the full flow until it reaches and end of conversation. It returns the last activity before the end of conversation is reached.

Input (required) - bot_id, string

Execute has a required input parameter, which it is the bot_id. The bot_id is the imported BotFramework service.

Input - initial_input, string

Execute has an optional input parameter initial_input. This is the initial message sent to the service. By default, if you do not pass anything, this action will then send an empty string.

Output - last_message, list<$mst.botframework.activity>

The last_message output parameter is the list of activities. The last_message returns the very last activity message before the end of the conversation is reached.

Output - end_message, $mst.botframework.activity

The end_message output parameter is the activity at the end of the conversation message.



The get_end_of_coversation is a helper that is used when you do not use the execute action. It is a helper method where you can pass a list of activities, and it will tell if one of those activities is the end of conversation.

Input - activities, list<$mst.botframework.activity>

This input parameter returns a list of activities at the end of the conversation message.

Output - end_message, list<$mst.botframework.activity>

The end_message output parameter is the activity at the end of the conversation message.



The extract_entities is another helper method. You can use this with the execute method or not. It will look through a list of activities, and it checks if has the entities list declared. If it has determined that it has its entities list declared, it will aggregate them all into another list and give it back to the user.

Input - activities, list<$mst.botframework.activity>

This input parameter returns a list of activities.

Output - entities, list<any>

The output entities parameter lists the entities that are found.