Teneo Developers

Teneo Orchestration Bot

In Conversational AI projects, it is common to work with several different business use cases and domains or knowledge fields. These multiple topics are commonly managed through different bots that can co-exist, representing the same brand or business with different services. This is a varied ecosystem in which many different teams can be involved. The question is, how can we most efficiently coordinate this multiple bot situation? To answer this question, we have created a Teneo solution: the Orchestration Bot.

The main idea of this approach is to add an extra layer that will decide between the different bots - known as Child bots - that are included in a business. Thanks to the Orchestration Bot you will be able to control as many Child bots as you wish and coordinate them with a single solution. This is how the process might look:

orchestration bot

The third episode of #TeneoTube focuses on the Orchestration Bot. You can watch it here.


  1. Download the Orchestrate bot solution. If using our example Child bot solution (as opposed to using one or several Child bot solutions of your own), download this as well. Both solutions and information on how to import them into Teneo can be found below.
  2. Publish your Orchestration bot.
  3. Make a note of the Engine URL of your Orchestration bot, as you will need to store this value inside the solution later on. You can find the Engine URL on the Bots page under My Teneo.

Core concepts

  • Child bot
  • Orchestration bot
  • Listeners
  • Scripts
  • Trigger ordering

Solution outline (Child bot)


In this Child Bot solution, you will find a basic flow that will exemplify the flow process with the Purchase iPhone flow. This is a multi-step flow that requires confirmation from the user to proceed with the transaction of the use case. It looks like this:

2-purchase iphone flow

The solution also contains two Global variables named sLuisEndpointUrlDev and sLuisEndpointUrlProd. These two global variables will be used to store the URLs of your LUIS classifier depending on the environment you are working on. To set up the solution, you will simply need to change the values of these variables to your LUIS URLs following this format: https://name.cognitiveservices.azure.com/luis/[...]query=

Using a different solution as Child bot

You may also want to use a pre-existing solution of your own as a Child bot that can be connected with the Orchestration Bot. To do this, you will need to add a Post-processing script to the solution.

Post-processing scripts are one of several types of scripts found in the Global Scripts section. The Post-processing script will be executed after the engine has constructed a response, so we can adapt it. You can read find more examples about the rest Global scripts here.

In this example we will add the necessary script in these steps:

  1. Open the 'SOLUTION' tab in the solution's window.
  2. Select 'Globals' in the sidebar, and then select 'Scripts'.
  3. Click on the 'Add' button to add a new script, and select 'Post-processing' from the dropdown.
  4. Paste in this script:


1// adapt bot answer
2def text=_.getOutputText()
3_.setOutputText("[Child] "+text)
5def nActiveFlows=_.getActiveFlows().size()
6def sActive="free";
7if (nActiveFlows>0)sActive="busy";
9// add parameters
  1. Click on 'SCRIPT' to edit the script properties, and add a name for the script like Connect Child bot to Orchestration bot.
  2. Click 'Save'. The result should look like this:

Using a different solution as Child bot

Please note the following:

  • We included a prefix to the Child Bot answers (“[Child]”) to recognize the origin of each message and check the change between bots. This can, of course, be deleted if you wish, since this is here only used for demo purposes (lines 1-3).
  • The variable sActive indicates important information to the Orchestration Bot: using the values ‘Busy’ and ‘Free’, the Orchestration Bot will recognize the inactive or active flows that are currently taking place in the Child bot. With this information, the Orchestration Bot will not need to call another Child Bot if there is a conversation still going on in one of them.
  • The used output parameters can be adjusted to the specific situation or use case of your project. The example we are using here includes commonly used output parameters making reference to the LUIS Classifier.

Solution outline (Orchestration bot)

Global and resources

This solution has a special configuration - or code setting - that will allow you to use this solution as your Orchestrator. The main characteristics are:

  1. Call Child Bot Global pre-listener: this script runs before any flow is triggered and is key to making communication between bots happen. Here, you will be able to identify the information sent and received between the Child bots and the Orchestration Bot. You will also be able to decide when to call your bot, especially if the bot’s conversation state indicates an ongoing process which we do not want to interrupt – this will be indicated by the Child Bot with the value ‘Busy’ mentioned above. You can find this Global pre-listener in the Solution > Global > Listener section. It will look like this:

4-call child bot

  1. TeneoEngineClient Groovy Class: the included code makes sure that session persistence is given in the communication between Orchestration and Child Bot. This is important, as otherwise we would be creating new sessions all the time in the Child Bot and not be able to have a follow-up to an ongoing process in this bot. You can find the TeneoEngineClient Groovy Class in the Solution > Resources > File section. This is how it will look:

5-teneoengineclient groovy

  1. externalTeneoEngine Global variable: to use the Teneo engine client implemented in the previously mentioned TeneoEngineClient Groovy class, you will need to create a Map object to include the URL of the Teneo engine you want to communicate with in its "url" property. The easiest way to create this Map object is by using a Global variable. In the Orchestration Bot you will find an example of an existing one ready to use: externalTeneoEngine. You will need to update the value of this variable with your URL engine. The format of the variable value should look like this: [ url: 'https://example.com/']

In this Orchestration Bot you will also find two flows that exemplify the process of changing between contents which sit in the knowledge base of the Orchestration Bot itself and those that come from the Child Bot.


The first flow is named Child Bot Flow and it is located in the External Bots folder. The Trigger will be in charge of evaluating the suggested answer of the Child Bot and its fit as final answer by the Orchestration Bot. In this example, we are going to pay attention to the confidence of the external Child Bot and the top intent identified by the LUIS Classifier. This Match Requirement can of course be adapted to anything that you may like to use (business rules, etc.).

The Output node will display the answer of the Child Bot. The next iteration has a recursive design so it will check the current status on the Child Bot, and decide if it will continue displaying answers or if it is time to leave the flow and find a new best candidate to answer on the current input (Orchestration Bot or another Child Bot).

The second flow is found in the Flows folder and is named Bank Account Change. It works as a follow-up flow with two simple steps. It will be used to show how the Orchestration Bot can manage its own flows without calling any Child Bots and how these flows are evaluated against the suggested answers of its connected Child Bots:

6-bank account flow

A note about the Post-processing script: in Solution > Global > Scripts > Post-processing you will find this first line: sLastStatus = sStatus;. Since in the previous call of the Child Bot Global pre-listener the Child Bot call is running, the Orchestration Bot will need to check the status of the previous interactions. This status is being overwritten by the current interaction before we move forward inside the Child Bot Flow which handles the Child Bot’s answer. To decide whether or not to display the answer from the Child Bot, the Orchestration Bot needs to know the status of the previous call.

Trigger ordering

Trigger Ordering can be very helpful for orchestration purposes since it lets you handle with all details how the triggers of the Orchestration and the Child Bot are evaluated against each other. A business rule logic can also be used here to make sure that certain keywords always result in an answer from a specific bot, etc.

Example conversation

Note that the answer with the [Child] prefix is included for demonstration purposes to indicate the Child Bot interaction. This prefix would not otherwise need to be included in a real bot.

User: Can I get an iphone?
Bot: [Child] Do you want to buy an iPhone?
User: Yes
Bot: [Child] Here is your iPhone
User: Bank account change
Bot: We will now proceed to change your bank account information. Can you tell me your IBAN please?
User: 211244243243432
Bot: Thanks, we have updated your bank account information. What else can I help you with?


  1. Download the Child bot solution here and the Orchestration bot solution here.
  2. Import the solutions into Teneo. For more details see How to import solutions.