Over the last few years, voice assistants have changed the way we interact with our devices. To some, this was a somewhat strange experience, but many more felt that this was a more natural way of interacting with most services provided by our phones and computers.
Many companies took this as an opportunity to enhance the experience for their customers and provided some of their core functionality via a set of voice commands, thus becoming more customer-friendly and strengthening their brand.
Voice chatbots are not only popular because of the convenience of talking to a device, but they also come very handy, when your hands are busy (ex. when you are cooking) or more importantly when your eyes should be focused elsewhere (ex. when you are driving).
In this article, you will learn how to build your own voice assistant. You will use NativeChat to build an Alexa skill.
To build something worthwhile we need a "real" customer and a set of "real" scenarios.
A telecommunications company called C-Mobile provides various services to its customers. They identified a need to assist their pay-as-you-go customers with various services around topping up their accounts and buying data packages.
As a customer, I want to be able to ask my Alexa device to check my balance.
Alexa should respond with the amount of credit I have left on my account together with the remaining minutes, texts and data.
As a customer, I want to be able to top up my account.
Alexa should guide me through the required steps, provide with a list of options, and at the end provide the updated credit on the account.
As a customer, I want to be able to buy additional data packages.
Alexa should guide me through the required steps, provide me with a list of data packages, which should be paid for with the credits on the account.
Usually, when you build applications for services like this, you will have functionality that allows your user to log in to their specific account. In the case of voice assistants, this usually is handled through the admin portal, which then automatically associates the user account with their app.
This is a whole topic on its own, which I am planning to cover in another blog post. For the purposes of this demo, we will hardcode the user id in the project.
C-Mobiles provides you with a very simple API, which allows you to manage individual accounts.
You can access all of the calls from the following https://demoapis.com/cmobile/012345678/<function-name>:
https://demoapis.com/cmobile/012345678/<function-name>
Please note that all API calls expect an id parameter. Please pick a number 9-11 digits long, and use it for all of your calls. This way when you top up an account and then ask for the account status, you will see the balance updated.
Also, if you happen to use a number that someone else is also using (this is not very likely unless you use the demo id), just pick a different number and you should be fine.
Here is the list of available functions:
getAccountStatus allows you to ask for the Account balance, minutes, SMS, and data.
getAccountStatus
Signature:
/availableCards
You need to provide your selected account id.
Example:
Here is an example of how to get the account balance for id 012345678
https://demoapis.com/cmobile/012345678/getAccountStatus
Result:
{ "balance": 12, "minutes": 100, "SMS": 200, "megabytes": 29, "data": "29 MB" }
topUp allows you to top up your account balance, as a result, the balance will increase and you will receive an updated account status.
topUp
/topUp?val={amount}&card={4-digits}
Additionally, you need to provide two query params:
val
card
Here is an example of how to top the account id 012345678 with 10 credits using the card ending with 9876 (don't worry no card payment will actually happen 😉).
https://demoapis.com/cmobile/012345678/topUp?val=10&card=9876
{ "SMS": 200, "balance": 22, "minutes": 100, "data": "29 MB", "megabytes": 29 }
availableCads allows you to look up all associated payment cards with the account.
availableCads
Here is an example of how to check what payment cards are associated with the account id 012345678.
https://demoapis.com/cmobile/012345678/availableCards
[ { "card": "6575", "val": 6575 }, { "card": "3688", "val": 3688 } ]
resetAccount allows you to reset your account. This can come useful when you want to start from scratch.
resetAccount
/resetAccount
Here is an example of how to reset the account id 012345678.
https://demoapis.com/cmobile/012345678/resetAccount
dataPackages allows you to view available data packages for purchase.
dataPackages
For each package, you will receive a name, formatted data size, megabytes, and a price.
/dataPackages
No parameters are required.
Here is an example of how to view available data packages.
https://demoapis.com/cmobile/012345678/dataPackages
[ { "name": "lite", "data": "512 MB", "megabytes": 512, "price": 7 }, { "name": "small", "data": "1 GB", "megabytes": 1024, "price": 10 }, { "name": "medium", "data": "3 GB", "megabytes": 3072, "price": 20 }, { "name": "big", "data": "5 GB", "megabytes": 5120, "price": 25 } ]
buyData allows you to purchase more data for your account. As a result, more data will be added to the account, and the price of the package will be deducted from the balance.
buyData
/buyData?dataPack={name}
Additionally, you need to provide a query param dataPack with the name of the package that you want to purchase.
dataPack
Here is an example of how to buy a medium data pack for the account id 012345678.
https://demoapis.com/cmobile/012345678/buyData?dataPack=tiny
{ "SMS": 200, "balance": 5, "minutes": 100, "data": "0.5 GB", "megabytes": 541 }
We will tackle this project in two rounds.
The getting started is as simple as 1,2,3, which can be done in these really easy steps.
First, you need to sign in to NativeChat Console.
If you don't have an account yet, you can create it here. Don't worry, you can get started for free.
After you sign in you can create a new chatbot. Press the [+ New bot] button:
This will create a simple chatbot, with a couple of super basic conversations.
To test it, press the [Test] button. Then when the chatbot loads:
Now that you have a working chatbot, it is time for you to implement the first conversation, which is for the check my balance scenario.
When the user says "Check my balance", the chatbot should call the getAccountStatus function, and then print out the message with the status returned from the API.
Are you ready? Let's go.
In the Cognitive Flow tab (which is the tab you arrive by default), on the right-hand side, there is a list of all conversations in this project. Click on the conversationTwo, which will take you to that conversation.
At the end of the json containing conversationTwo add a comma, and in the new line start typing con, this should trigger a little pop-up with a list of code snippets.
json
conversationTwo
con
The code snippets are really useful in the process of constructing your chatbot, as they help you generate the JSON in the correct format, plus they save you a lot of time.
Select the conversation-goal snippet and press enter. This should output the following code:
conversation-goal
"conversation-name": { "type": "goal", "steps": [ ] }
Change "conversation-name" to "check-my-balance".
"conversation-name"
"check-my-balance"
Next, you need to add a message step to the conversation.
Hint: If you press tab, the cursor will jump inside the steps[ ] array.
steps[ ]
From inside the steps[ ] array, start typing step (or stme for step message) and select the step-message snippet. This should produce the following code:
step
stme
step-message
{ "type": "message", "messages": [ "Your message" ] }
Change "Your message" to "I am checking your balance".
"Your message"
"I am checking your balance"
The check-my-balance conversation should look like this:
check-my-balance
"check-my-balance": { "type": "goal", "steps": [ { "type": "message", "messages": [ "I am checking your balance" ] } ] }
Here is how to do it:
Next, you need to train the chatbot to understand when to trigger this conversation.
Navigate to the Training tab, click on Conversation built-in, and then press the [Add value] button.
Set the value to "check-my-balance" — this how the chatbot engine knows which conversation to trigger
value
Add the following expressions — this how you tell the chatbot engine when to trigger this conversation:
expressions
Press the [Save] button.
To test this new conversation, press the [Test] button and type: Check my balance
The chatbot should respond with your message.
Now that you have the conversation working, it is time to change it so that it returns real data.
Remove the message step, so that the "steps": [ ] array is empty.
"steps": [ ]
Start typing stwe and select step-webhook. Remove all the properties in the data-source, but keep the endpoint.
stwe
step-webhook
data-source
endpoint
Add an "entity" property (it is best to place it below "type": "webhook",) and call it "status" — the result of the API call will be stored in status.
"entity"
"type": "webhook",
"status"
status
Finally, you need to add a "messages" property to this step, which will contain the message to be printed when the API returns the result, like this:
"messages"
"messages": [ "Let's have a look at your account. You have {{status.balance}} dollars left." ]
Hint: You could also, make the response multiline — which is not very important with voice chatbots, as chatbots tend to read the whole output, as one line, but it looks better when we test it in the console. To add a multiline response, we need to use an array of arrays. Here are two examples: One Array "messages": [ "Line 1", "Line 2", "Line 3" ] This will result in one of the lines printed (or spoken) at random. Two Arrays "messages": [ [ "Line 1", "Line 2", "Line 3" ] ] This will result in all of the lines printed (or spoken).
Hint: You could also, make the response multiline — which is not very important with voice chatbots, as chatbots tend to read the whole output, as one line, but it looks better when we test it in the console.
To add a multiline response, we need to use an array of arrays.
Here are two examples:
One Array
"messages": [ "Line 1", "Line 2", "Line 3" ]
This will result in one of the lines printed (or spoken) at random.
Two Arrays
"messages": [ [ "Line 1", "Line 2", "Line 3" ] ]
This will result in all of the lines printed (or spoken).
Here are messages containing all of the data returned from the getAccountStatus API call:
messages
"messages": [ [ "Let's have a look at your account. You have:", "{{$currency status.balance 'USD'}}", "{{status.minutes}} minutes, {{status.SMS}} text messages", "and {{status.data}} left" ] ]
The whole check-my-balance conversation should look like this:
"check-my-balance": { "type": "goal", "steps": [ { "type": "webhook", "entity": "status", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/getAccountStatus" }, "messages": [ [ "Let's have a look at your account. You have:", "{{$currency status.balance 'USD'}}", "{{status.minutes}} minutes, {{status.SMS}} text messages", "and {{status.data}} left" ] ] } ] }
To test this new conversation, press the [Test] button and type: What is my balance?
Before you move on, it is a good idea to tidy up the initial messages.
Your chatbot project has 3 support conversations:
welcome
help
restart
Update the welcome message
Find the welcome conversation and change: "This is a welcome conversation for your chatbot" text to "Welcome to the c-mobile self service."
"This is a welcome conversation for your chatbot"
"Welcome to the c-mobile self service."
Update the help message and the list of proposed actions
Find the help conversation and remove the line "If you get stuck, you can always restart our conversation by typing 'restart'",. This way the intro conversation will be a lot shorter.
"If you get stuck, you can always restart our conversation by typing 'restart'",
Additionally, you should change the display options from "Conversation 1", "Conversation 2" to "Check my balance", "Top up", "Buy data". You will implement Top up and Buy data later, but it is good to already have these options.
display
"Conversation 1", "Conversation 2"
"Check my balance", "Top up", "Buy data"
Top up
Buy data
Your welcome and help conversations should look like this:
"welcome": { "type": "support", "steps": [ { "type": "message", "messages": [ "Welcome to the c-mobile self-service." ] }, { "type": "conversation", "conversation": "help", "conditions": [ "{{$not ($has conversation) }}" ] } ] }, "help": { "type": "support", "steps": [ { "type": "message", "messages": [ [ "Here is what I can do for you:" ] ], "display": { "type": "quick-reply", "data": [ "Check my balance", "Top up", "Buy data" ] } } ] },
To test this new configuration, press the [Test] button and type: Hi
The welcome message should be different.
Additionally, you can remove ConversationOne and ConversationTwo, as these are not needed anymore.
ConversationOne
ConversationTwo
This should be done in two steps:
-
Conversation
The whole cognitive flow should look like this:
{ "conversations": { "welcome": { "type": "support", "steps": [ { "type": "message", "messages": [ "Welcome to the c-mobile self service." ] }, { "type": "conversation", "conversation": "help", "conditions": [ "{{$not ($has conversation) }}" ] } ] }, "help": { "type": "support", "steps": [ { "type": "message", "messages": [ [ "Here is what I can do for you:" ] ], "display": { "type": "quick-reply", "data": [ "Check My Balance", "Top up", "Buy more data" ] } } ] }, "restart": { "type": "support", "steps": [ { "type": "message", "messages": [ "Your conversation is restarted." ] }, { "type": "conversation", "conversation": "welcome" } ] }, "check-my-balance": { "type": "goal", "steps": [ { "type": "webhook", "entity": "status", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/getAccountStatus" }, "messages": [ [ "Let's have a look at your account. You have:", "{{$currency status.balance 'USD'}}", "{{status.minutes}} minutes, {{status.SMS}} text messages", "and {{status.data}} left" ] ] } ] } }, "settings": { "invalid-replies": [ "I am not sure I understood what you said." ], "general-failure": [ "We are experiencing technical difficulties at this moment." ], "previous-conversation-messages": [ "I am going back to the {{ conversationDisplayName }} now." ] }, "commands": { "NEXT-PAGE": [ "Next 5" ], "RESTART": [ "restart" ] } }
Now that you have a working chatbot, it is time to start talking to it with actual voice commands. The best thing is that you don't even need an Alexa device to do that.
All you need is a configured Alexa Developer Console and the NativeChat Proxy skill.
Next, you need to go to the Alexa Developer Console and open the Alexa Test simulator.
To open the simulator you need to use an Alexa skill. If you already have one, you can just go to the Test tab and you are good to go.
If you don't have an Alexa skill yet, here is what you need to do:
In the Alexa Developer Console, press the Create Skill button.
Note, you could use this skill later when you are ready to publish your chatbot as an Alexa skill.
Call the skill C Mobile, and select Custom model and Provision your own hosting method, and press the Create skill button.
Select the Start from scratch template, and press the Choose button.
Open the JSON Editor, and find "Amazon.FallbackIntent" and set the samples to "Sample" (at this stage it could be any word, we just need something in there), it should look like this:
{ "name": "AMAZON.FallbackIntent", "samples": [ "Sample" ] },
Press the Build Model button and wait for a little bit.
Finally, open the Test tab, and switch the skill testing from Off to Development.
NativeChat Proxy is a skill, which is designed to easily connect with your NativeChat chatbots without having to publish a new skill. It works like a sandbox skill, which relays all messages from the user to the connected NativeChat chatbot.
You can install it using the Alexa Developer Console. Just type: enable nativechat proxy
Note: the NativeChat Proxy skill, works with the following languages:
Now, to complete the loop, you just need to get the proxy id and pass it to the NativeChat Proxy skill.
In NativeChat, expand the Test options, and choose Test in Alexa Developer Console. This will provide you with instructions on how to make it work.
You should see something like this:
Copy the last message that contains the proxy id. (hint. you can click on the little icon next to it).
Go back to the Alexa Developer Console:
And voila, your chatbot is ready to listen and to speak back to you.
There are two ways that you can interact your chatbots in Alexa Developer Console.
Note, if you reload the Alexa Developer Console page, or close it and open it again, then the console will disconnect from the NativeChat Proxy skill. All you need to do is say: "NativeChat Proxy", and you will be back where you left it (no need to provide the Proxy ID again).
To hear the welcome message, say: "hi"
Then say: "Check my balance"
And just like that, you have just talked to your first NativeChat chatbot through an Alexa skill.
Well done, you deserve a pat on the back:
The way this works is pretty straight forward.
One of the trickiest challenges you will face is with voice recognition.
There might be cases when your users will try to say things like: "Pay now", while Alexa might understand it as "Play now". This can be quite problematic when your chatbot expects a specific item.
To work around that, you should train your chatbot to understand different ways of saying the same thing — this includes different phrases, but also different words that sound similar — so that it would respond with the same action regardless of how someone might pronounce their commands.
In the case of this chatbot, a user could say: "Check my balance", which Alexa might understand as "Shake my balance". This is still close enough, so NativeChat might accept it.
However, if you are struggling with some voice commands, you can investigate what messages are sent to NativeChat, and how NativeChat interpreted them. This will come especially useful when you start using your chatbots outside of the Alexa Developer Console.
In NativeChat portal, navigate to the History tab. Find the conversation that was causing trouble and click on it.
Hint: you can add a filter to show only conversations for specific dates, or Alexa only.
From here, you can see all the messages sent and received. If you click on the user input, you will see how this was interpreted by NativeChat. In the case of "Shake my balance", NativeChat was 75% sure that you wanted to check your balance, so all is good.
To make it 100%, you would need to add "Shake my balance" to the Conversation training for check-my-balance.
Now that you have your chatbot connected with Alexa, you can proceed with implementation of the remaining conversations, "Top up" and "Buy data".
This time, you will be able to edit the conversations and test them straight away with voice commands. No need to configure the proxy id, or anything else. All changes will be available in Alexa as soon as you save them.
In this conversation the chatbot should ask the user:
Then finally, it should either execute the top up (if confirmed) or cancel the process (if confirmation rejected).
For this conversation, you should use the following API calls:
availableCards
account id
card number
Reminder: to avoid conflicting with other people using this API, please use a different account id to the one used in the example (012345678).
First, you need to create a new conversation called top-up, which is done just like you did it with the check-my-balance.
top-up
"top-up"
Add a sample step
Just to see that the conversation works, you should add a sample message step.
steps
Set the message to "top-up works".
"top-up works"
The conversation should look like this:
"top-up": { "type": "goal", "steps": [ { "type": "message", "messages": [ "top-up works" ] } ] }
Train the chatbot to know when to use your new conversation
Finally, train the chatbot to understand when to trigger this conversation.
Add the following expressions:
Test
To test this, go to Alexa Developer Console, and say Top up or Add more funds
Alexa should respond with your message.
Note #1 If Alexa doesn't understand your expressions, like when you say "top up" it might understand it as "top pop" then you can add this expression to the training. Note #2 You should be able to continue to use your chatbot through the proxy app. But if not just say "NativeChat Proxy".
Note #1
If Alexa doesn't understand your expressions, like when you say "top up" it might understand it as "top pop" then you can add this expression to the training.
Note #2
You should be able to continue to use your chatbot through the proxy app. But if not just say "NativeChat Proxy".
Now, that you have the top-up conversation wired up, it is time to implement it with the proper logic.
Note, you should test the conversation each time you add a new step.
Clean up
Start by removing the sample message step, so that the steps array is empty, like this
"top-up": { "type": "goal", "steps": [ ] }
The first step of this conversation is to ask the user how much they would like to top up.
In the steps array, start typing step and select the step-question snippet.
step-question
You should be presented with the following code:
{ "type": "question", "entity": "entity-name", "entity-type": "", "messages": [ "How to ask for entity?" ] }
Here is what his all means:
entity
entity-type
Your step should look like this:
{ "type": "question", "entity": "top-up-value", "entity-type": "Number", "messages": [ "How much would you like to top up?" ] }
Press the [Save] button and test.
Now, when you say:
Alexa will not say anything after you provide the answer. Don't worry, that is OK, as you don't need to confirm the answers provided to the chatbot questions.
Adding a reaction
Note, that the chatbot can recognize entity values at any time during the conversation. For example, when you say "Top up twenty five", the chatbot will understand that:
top-up-value
25
In this case, the chatbot should respond with a confirmation that it understood the extra entity value. This is done with acknowledgements.
After the end of messages array, add a comma, then add the following code:
"reactions": { "acknowledgements": [ "I understand that you want to top up {{$currency top-up-value 'USD'}}" ] }
Now, when you say: "Top up twenty five"
Alexa should respond with: "I understand that you want to top up $25.00"
The full step should look like this:
{ "type": "question", "entity": "top-up-value", "entity-type": "Number", "messages": [ "How much would you like to top up?" ], "reactions": { "acknowledgements": [ "I understand that you want to top up {{$currency top-up-value 'USD'}}" ] } },
The next step should be to ask the user to provide the payment card they want to use.
In the case of the c-mobile API, you only need to provide the last 4 digits of the card, which is already stored in the system. You can see all available cards by calling: https://demoapis.com/cmobile/012345678/availableCards.
Go to the Cognitive Flow tab, and find the end of the top-up-value question step.
Add a comma, and start typing stq and select the step-question snippet.
stq
Set the properties to:
Make it explicit
Additionally, to avoid the number in the card ending clashing with the top-up-value, you need to make this question explicit. This means that when the user is asked for the card number, no other entities of type Number can be updated.
Add a new line after entity-type and add "is-explicit": true,
"is-explicit": true,
Provide possible values
To help the user choose the right value, you can call availableCards, and provide the users with the possible values.
After the messages array, add a comma and then add the following code:
Reminder: to avoid conflicting with other people using this API, please change account id
"display": { "type": "quick-reply", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/availableCards" }, "template": "ending **{{card}}" }
Now try to say:
Alexa truncating leading zeroes
Note, when you tell Alexa a number that starts with leading zeroes, Alexa will skip these digits.
For example, input: Use card 0020, will be captured as Use card 20.
Make sure to be aware of this behavior, so that when you expect a 4 digits card or PIN, and if you receive less, you should be safe to assume that the missing digits are zeroes.
(Optional) Validation
If you would like to make this conversation more robust and make sure that the user always provides a card number that is actually stored on the system, you could use a validation.
There are various types of validations, which allow you to validate that a provided value is a telephone number, or that it matches a specific regular expression, and many more. You can read all about validation rules in the docs.
The validation that you need to use in this scenario is a custom webhook validation. This validation allows you to execute a query, then validate that the entity value matches the _response returned from the query.
custom
webhook
_response
Add the following code after the display section:
Reminder: remember to update your account id
"reactions": { "validations": [ { "type": "custom", "parameters": { "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/availableCards", "selector": "$[:].val" }, "condition": "{{$in card _response}}", }, "error-message": [ "Card number {{card}} not found on the system." ] } ] }
Here is how to understand this code:
endpoint: contains the URL with a query
selector: parses the response to a specific format, it uses JSON Path Expressions to do the job.
selector
In this case, the response from /availableCards query will look something like this:
While you just want to check if the card value matches one of the val values.
To do that $.[:] will give you all objects from the response, while .val will return all values of val. As a result $:[:].val will return:
$.[:]
.val
$:[:].val
[ 6575, 3688 ]
condition: the expression to test the validation.
condition
$in card _response checks if the value of card exists in the parsed _response
$in card _response
error-message: the error message, you can use {{card}} to tell the user what card number doesn't seem to work.
error-message
{{card}}
{ "type": "question", "entity": "card", "entity-type": "Number", "is-explicit": true, "messages": [ "Which card would you like to use? " ], "display": { "type": "quick-reply", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/availableCards" }, "template": "ending **{{card}}" }, "reactions": { "validations": [ { "type": "custom", "parameters": { "condition": "{{$in card _response}}", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/availableCards", "selector": "$[:].val" } }, "error-message": [ "Card number {{card}} not found on the system." ] } ] } }
Before, the chatbot performs the top-up operation, it should ask the user to confirm the top-up-value and the card.
This can be done with a Confirmation step.
Go to the end of the card question step, add a comma and start typing stco and select the step-confirmation snippet. The snippet should look like this.
stco
step-confirmation
{ "type": "confirmation", "entity": "result-entity-name", "messages": [ "Confirm action?" ] }
{ "type": "confirmation", "entity": "top-up-confirmation", "messages": [ "Just to confirm. Do you want to top up {{$currency top-up-value 'USD'}} with the card ending with {{card}}?" ] }
If the user rejects the confirmation, then the chatbot should respond with a message confirming the choice.
This can be done by simply adding a new message step.
However, you want this step to only trigger when top-up-confirmation is false. This can be done with the help of the conditions property.
top-up-confirmation
false
conditions
You can learn more about Conditions in the docs.
Add a new message step at the end of the conversation, start typing stme and select the step-message snippet.
Set the messages to Top-up has been cancelled.
Add the conditions property with the following (self-explanatory) condition:
"conditions": [ "{{$not top-up-confirmation}}" ]
Start the chat, and say "No" when you get asked to confirm.
The chatbot should respond with the cancellation message.
{ "type": "message", "messages": [ "Top-up has been cancelled" ], "conditions": [ "{{$not top-up-confirmation}}" ] },
The final step is to execute the top-up call, by calling the cmobile API topUp function. This operation can be done with a Webhook step.
However, once again you don't want this step to be executed every time. You want this step to be executed when top-up-confirmation is true.
true
Add a new Webhook step at the end of the conversation, start typing stwe and select the step-webhook snippet. The snippet should look like this:
{ "type": "webhook", "data-source": { "endpoint": "https://", "method": "POST", "headers": { "header name": "header value" }, "payload": { "key": "value" } } }
Data Source
You don't need the method, headers and payload properties, so just delete them. Then update the endpoint to call the topUp API function and pass top-up-value as val, like this:
method
headers
payload
"data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/topUp?val={{top-up-value}}" },
Condition
To make sure that this step is only triggered when the user confirms they want to proceed, add the following conditions property to the step (not inside the data-source):
"conditions": [ "{{top-up-confirmation}}" ]
Confirmation message
Finally, you need to display a message confirming that the transaction is complete.
To do that you need to add two properties: entity and messages.
Add an entity property called top-up-response (it is best to add it below type)
type
"entity": "top-up-response",
Add a messages property with the following message (it is best to add it below conditions:
"messages": [ "Your new balance is {{$currency top-up-response.balance 'USD'}}" ]
{ "type": "webhook", "entity": "top-up-response", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/topUp?val={{top-up-value}}" }, "conditions": [ "{{top-up-confirmation}}" ], "messages": [ "Your new balance is {{$currency top-up-response.balance 'USD'}}" ] }
Go through the chat conversation, and say "Yes" when you get asked to confirm. The chatbot should execute the Top-Up API call and respond with updated balance value. It should be increased by the amount specified in the first step.
The whole top-up conversation should look like this:
"top-up": { "type": "goal", "steps": [ { "type": "question", "entity": "top-up-value", "entity-type": "Number", "messages": [ "How much would you like to top up?" ], "reactions": { "acknowledgements": [ "I understand that you want to top up {{$currency top-up-value 'USD'}}" ] } }, { "type": "question", "entity": "card", "entity-type": "Number", "is-explicit": true, "messages": [ "Which card would you like to use? " ], "display": { "type": "quick-reply", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/availableCards" }, "template": "ending **{{card}}" }, "reactions": { "validations": [ { "type": "custom", "parameters": { "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/availableCards", "selector": "$[:].val" }, "condition": "{{$in card _response}}" }, "error-message": [ "Card number {{card}} not found on the system." ] } ] } }, { "type": "confirmation", "entity": "top-up-confirmation", "messages": [ "Just to confirm. Do want to top up {{$currency top-up-value 'USD'}} with the card ending with {{card}}?" ] }, { "type": "message", "messages": [ "Top up has been cancelled" ], "conditions": [ "{{$not top-up-confirmation}}" ] }, { "type": "webhook", "entity": "top-up-response", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/topUp?val={{top-up-value}}" }, "conditions": [ "{{top-up-confirmation}}" ], "messages": [ "Your new balance is {{$currency top-up-response.balance 'USD'}}" ] } ] }
In this conversation the chatbot should:
data-pack
First, you need to create a new conversation called buy-data, which is done just like you did it with the top-up.
buy-data
Go to the Cognitive Flow tab, and find the end of the "top-up" code.
"buy-data"
"steps"
For the chatbot to allow the user to select a Data Pack, you need to train it, so that it understands what Data Packs are available, and how to extract it from a sentence.
For example, when a user says: "I want a small data pack"
The chatbot should understand that small, is the name of the required Data Pack.
Add DataPack to the Entity training list
Creating new entities is quite simple.
Open the Training tab and press the [Add new] button and set:
name
Lookup Strategy
Training data source
Endpoint URL
Value template
Press the [Test] button, which should display a list of possible values.
If everything looks fine, then press the [Create] button.
NativeChat will pull the data, and train the data model to understand the values for DataPack.
Now, that you have the buy-data conversation wired up, and a data model for DataPack, it is time to implement the logic.
The first step should be to provide the user with the list of available data packs and ask them to select one.
In the steps array, start typing stq and select the step-question snippet. Set:
At this point, your code should look like this:
{ "type": "question", "entity": "data-pack", "entity-type": "DataPack", "messages": [ "Which data pack would you like?" ] },
This should be enough to let the user choose a Data Pack, however, we should let user what Data Packs are available.
To help the user choose a DataPack, you can call dataPackages, and provide the users with the possible values.
"display": { "type": "quick-reply", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/dataPackages" }, "template": "{{name}} {{data}} for {{$currency price 'USD'}}" }
{ "type": "question", "entity": "data-pack", "entity-type": "DataPack", "messages": [ "Which data pack would you like?" ], "display": { "type": "quick-reply", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/dataPackages" }, "template": "{{name}} {{data}} for {{$currency price 'USD'}}" } },
The final step is to execute the buy data call, by calling the cmobile API buyData function. This operation can be done with a Webhook step.
Add a new Webhook step at the end of the conversation, start typing stwe and select the step-webhook snippet.
You don't need the method, headers and payload properties, so just delete them.
Then update the endpoint to call the buyData API function and pass data-pack as dataPack, like this:
"data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/buyData?dataPack={{data-pack}}" },
Finally, you need to display a message confirming that the transaction is complete. To do that you need to add two properties: entity and messages.
Add an entity property called buy-data-response (it is best to add it below type)
"entity": "buy-data-response",
"messages": [ "Your purchase is complete. You now have {{buy-data-response.data}}. Your balance is {{$currency buy-data-response.balance 'USD'}}" ]
{ "type": "webhook", "entity": "buy-data-response", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/buyData?dataPack={{data-pack}}" }, "messages": [ "You now have {{buy-data-response.data}}. Your balance is {{$currency buy-data-response.balance 'USD'}}" ] }
Say: "Add Data"
The chatbot should list the available packages.
Say: "Lite"
The chatbot should execute the Buy Data API call and respond with updated data and balance values.
The whole buy-data conversation should look like this:
"buy-data": { "type": "goal", "steps": [ { "type": "question", "entity": "data-pack", "entity-type": "DataPack", "messages": [ "Which data pack would you like?" ], "display": { "type": "quick-reply", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/dataPackages" }, "template": "{{name}} {{data}} for {{$currency price 'USD'}}" } }, { "type": "webhook", "entity": "buy-data-response", "data-source": { "endpoint": "https://demoapis.com/cmobile/012345678/buyData?dataPack={{data-pack}}" }, "messages": [ "You now have {{buy-data-response.data}}. Your balance is {{$currency buy-data-response.balance 'USD'}}" ] } ] }
Just like that, you have created a fully functioning Alexa Skill! It can communicate using Natural Language Processing (NLP) while connecting with the cmobile API to provide the users with the ability to check their account status, top up and buy more data.
There is still more to learn. You can learn more from the NativeChat documentation.
Sebastian Witalec is a Senior Developer Advocate for Progress who specializes in Angular and NativeScript. He loves working on both serious and fun projects and one day he will use his robot army to conquer the world.
Subscribe to get all the news, info and tutorials you need to build better business apps and sites
Progress collects the Personal Information set out in our Privacy Policy and Privacy Policy for California Residents and uses it for the purposes stated in that policy.
You have the right to request deletion of your Personal Information at any time.
You can also ask us not to pass your Personal Information to third parties here: Do Not Sell My Info
Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.