Completing a conversation
In order to complete a conversation it is usually best to ask the user to confirm their input, and once they are happy with the result, push the data to your backend or trigger some other process outside of the chatbot domain.
Entities Confirmation
Entities confirmation is a crucial step that brings in a lot of value to the conversation:
- it shows the user all the values that they provided
- it allows the user to change any of the values - that is without the need to redo the whole conversation
- it provides a mechanism to confirm the conversation, which allows the chatbot to complete the transaction
There is a special type of a step, entities-confirmation
, which handles all of the above functionality in a simple, but elegant fashion.
Add confirmation step
Add a confirmation step to the rent-car
conversation, which should ask the user to confirm the startDate, endDate, city, car and email entities. Like this:
- Go to the end of the
rent-car
conversation
- Add
entities-confirmation
step => start typing sten and select step-entities-confirmation
. You should get the following code
{
"type": "entities-confirmation",
"entity": "result-entity-name",
"entities": [
"entity-name"
],
"messages": [
"Confirm entities?"
]
}
- Add the startDate, endDate, city, car and email entities to the
entities
array
- Update the
messages
to display a message in the following three lines:
-
Are these the correct details?
-
Press on any of the items you wish to update.
-
Press “Confirm” to complete the transaction.
- Save
Solution
The whole step should look like this:
{
"type": "entities-confirmation",
"entity": "result-entity-name",
"entities": [
"startDate",
"endDate",
"city",
"car",
"email"
],
"messages": [
[
"Are these the correct details?",
"Press on any of the items you wish to update.",
"Press \"Confirm\" to complete the transaction."
]
]
}
Test
Now you should be able to test the confirmation step in the rent-car
conversation.
Try the following steps:
- Send: I want to rent a car
- Select: StartDate, EndDate, Country, City, Car, Email
- You should be presented with the confirmation step and the provided entity values
- Click on the email, and change it
- You should be presented with the confirmation step again, but the email should be changed
- Press: Confirm
Complete the conversation with a Webhook
Once the user completes the conversation and confirms their choice, all you are left with is to take the data collected in the conversation and send it to your backend.
This would usually mean triggering a process to execute on the agreed transaction. For example:
- user: orders a pizza via your chatbot
- chatbot: sends the order to your backend
- payment system: charge the provided payment card
- kitchen: cooks a pizza
- delivery: delivers the pizza
In order to send the data to your backend, you can use a webhook
step. Its purpose is simple, execute an HTTP command described in the data-source
property and display the provided message once that is complete.
Here is what the step-webhook
code snippet generates:
{
"type": "webhook",
"data-source": {
"endpoint": "https://",
"method": "POST",
"headers": {
"header name": "header value"
},
"payload": {
"key": "value"
}
}
}
Conversation Flow for Webhook Steps
A Webhook Step behaves just like a Message Step in the sense that the Conversation Flow Algorithm will execute it every time it steps over it. So, if you follow the pizza order webhook step with a satisfaction question, your customer might get charged twice and will receive two pizza orders.
This can be easily avoided. You can add an entity
property, which is used to store the result returned from executing the webhook. You can use the entity content to display it to the user (more on that in the bonus section below). But in this case, the Conversation Flow Algorithm will see that the webhook already contains a result, and therefore it will not execute it again.
Send the Order to the backend
To finalize the car renting conversation, you need to send the Order to the backend, and then provide the user with a confirmation message.
Backend
For the purposes of the Car Rental service, there is a Cloud Function called BookCar, that allows you to complete the booking process.
BookCar can be reached with the following parameters:
"endpoint": "https://baas.kinvey.com/rpc/kid_r1275v_H4/custom/BookCar",
"method": "POST",
"headers": {
"Authorization": "Basic a2lkX3IxMjc1dl9INDo5YWYxOTcxZTFlY2U0NTNhYWUwOTQ2MzZlYmM5MGJlNw=="
},
The booking details should be provided as the request body (payload
in the chatbot configuration). For example:
{
"pickUpDate": "24 Mar 2019",
"dropOffDate": "30 Mar 2019",
"car": "Smart",
"price": "200",
"city": "Berlin",
"email": "me@email.com"
}
In the real world application, the BookCar function should perform some extra validations, save the new order and trigger additional processes (like an email confirmation etc.).
In the context of this tutorial, BookCar only saves the provided data in a collection and returns a unique booking reference, i.e. { bookingRef: BER01234 }
Additionally, in order to avoid storing sensitive data, the provided email always gets replaced with sample@email.com
.
Add a Webhook step to call BookCar
In order to complete the transaction with a call to the BookCar cloud function, follow these steps:
- Got to the end of the
rent-car
conversation
- Add a
webhook
step => start typing stw
- Configure the
data-source
to call BookCar
(see the configuration above),
- Configure the
payload
, use the following fields
-
pickUpDate
-> startDate
-
dropOffDate
-> endDate
-
car
-> car
-
price
-> car.price
-
city
-> city
-
email
-> email
(although you can ignore this field, as it is not used)
Additionally, you should format the dates, so that they are passed to the backend in a specific format. This can be done with the $date
formatter, like this: {{$date startDate 'D MMM YYYY'}}
.
- Your
data-source
should look like this:
"data-source": {
"endpoint": "https://baas.kinvey.com/rpc/kid_r1275v_H4/custom/BookCar",
"method": "POST",
"headers": {
"Authorization": "Basic a2lkX3IxMjc1dl9INDo5YWYxOTcxZTFlY2U0NTNhYWUwOTQ2MzZlYmM5MGJlNw=="
},
"payload": {
"pickUpDate": "{{$date startDate 'D MMM YYYY'}}",
"dropOffDate": "{{$date endDate 'D MMM YYYY'}}",
"car": "{{car}}",
"price": "{{car.price}}",
"city": "{{city}}",
"email": "{{email}}"
}
},
- Add an
entity
property (preferably, just before the data-source
configuration) => start typing en and select entity
and call it order-response
. This will allow you to capture the response returned by BookCar.
- Add a
messages
array (preferably, at the end of the step configuration) => start typing me and select messages
.
- Then add this message: Your car is booked. Your booking reference is {{order-response.bookingRef}}.
- Save
Solution
The whole step should look like this:
{
"type": "webhook",
"entity": "order-response",
"data-source": {
"endpoint": "https://baas.kinvey.com/rpc/kid_r1275v_H4/custom/BookCar",
"method": "POST",
"headers": {
"Authorization": "Basic a2lkX3IxMjc1dl9INDo5YWYxOTcxZTFlY2U0NTNhYWUwOTQ2MzZlYmM5MGJlNw=="
},
"payload": {
"pickUpDate": "{{$date startDate 'D MMM YYYY'}}",
"dropOffDate": "{{$date endDate 'D MMM YYYY'}}",
"car": "{{car}}",
"price": "{{car.price}}",
"city": "{{city}}",
"email": "{{email}}"
}
},
"messages": [
"Your car is booked. Your booking reference is {{order-response.bookingRef}}"
]
}
Test
Now you should be able to test the full conversation rent-car
conversation.
Try the following steps:
- Send: I want to rent a car
- Select: StartDate, EndDate, Country, City, Car, Email
- Press: Confirm
- You should receive a message with a unique bookingRef
Congratulations
And just like that, you have created a fully functioning chatbot. It can communicate using Natural Language Processing, communicate with the backend to display data, validate user input and save the transaction to the backend.
There is still more to learn. You can learn more from the NativeChat documentation.
Homework
As a bonus, here is the final homework for you, which should use a lot of the knowledge that you’ve learned in this tutorial.
Before booking the car, you should:
- Provide the user with a quote and ask if they would like to go ahead with the booking.
- If the user confirms, then execute the BookCar webhook.
- If not, then just print a message: I understand. I will cancel the quote now.
GetQuote
To get a quote you should call the GetQuote cloud function.
GetQuote can be reached with the following parameters:
"endpoint": "https://baas.kinvey.com/rpc/kid_r1275v_H4/custom/GetQuote",
"method": "POST",
"headers": {
"Authorization": "Basic a2lkX3IxMjc1dl9INDo5YWYxOTcxZTFlY2U0NTNhYWUwOTQ2MzZlYmM5MGJlNw=="
},
It expects the body to be like:
{
"car": "Smart"
"pickUpDate": "10 Mar 2019",
"dropOffDate": "15 Mar 2019"
}
As a result, it returns something like this:
{
"days": 5
"price": 200
}
High-level guide
Here is a high-level guide on how to complete this challenge.
Note, that you should be adding the solution, just after the entity-confirmation step, and before the BookCar webhook step.
Step 0
Before you display the quote. You need to add a webhook step, that will call GetQuote.
Make sure to add the entity
property (you can call it quote
), which you will use to display the result later. Like: {{quote.days}}
.
As a message, you could add something like: Preparing a quote, but that is not necessary.
Step 1
After that, add a confirmation type step.
Make sure to call the entity
property something meaningful like wantsToBook
.
It should display a message like:
Here is the summary of your order:
Car: Smart
Price per day: $50
5 day(s): from 10-Mar-2019 to 15-Mar-2019
Total price $250
Would you like to go ahead and book it?
The number of days you can get from quote.days
(or whatever you called the webhook entity), and the total price from quote.price
.
Also, note that you should use $currency and $date formatters to display the data in the desired format.
Step 2
Add a message step with a condition checking the entity form the confirmation step is false. (i.e. check if wantsToBook
equals false or is not true).
If you don’t remember how, you can go back to the comparison chapter, or check the docs.
The message should be something like: I understand. I will cancel the quote now.
Step 3
Update the BookCar Webhook step. Add a condition, so that it executes when the confirmation entity is true (i.e. check wantsToBook
is true)
Step 4
Test it, you know the drill.
Solution
I hope that you completed the solution all by yourself, and you are here just to compare the results. Either way, here are the three new steps, and the updated BookCar step.
GetQuote Step
{{
"type": "webhook",
"entity": "quote",
"data-source": {
"endpoint": "https://baas.kinvey.com/rpc/kid_r1275v_H4/custom/GetQuote",
"method": "POST",
"headers": {
"Authorization": "Basic a2lkX3IxMjc1dl9INDo5YWYxOTcxZTFlY2U0NTNhYWUwOTQ2MzZlYmM5MGJlNw=="
},
"payload": {
"car": "{{car}}",
"pickUpDate": "{{$date startDate 'D MMM YYYY'}}",
"dropOffDate": "{{$date endDate 'D MMM YYYY'}}"
}
}
},
Confirmation Step
{
"type": "confirmation",
"entity": "wantsToBook",
"messages": [
[
"Here is the summary of your order:",
"Car: {{car}}",
"Price per day: {{$currency car.price 'USD'}}",
"{{ quote.days }} day(s): from {{$date startDate 'D MMM YYYY'}} to {{$date endDate 'D MMM YYYY'}}",
"Total price {{$currency quote.price 'USD'}}.",
"Would you like to go ahead and book it?"
]
]
},
Message Step
{
"type": "message",
"messages": [
"I understand. I will cancel the quote now."
],
"conditions": [
"{{$not wantsToBook}}"
]
},
Webhook BookCar step
{
"type": "webhook",
"entity": "order-response",
"data-source": {
"endpoint": "https://baas.kinvey.com/rpc/kid_r1275v_H4/custom/BookCar",
"method": "POST",
"headers": {
"Authorization": "Basic a2lkX3IxMjc1dl9INDo5YWYxOTcxZTFlY2U0NTNhYWUwOTQ2MzZlYmM5MGJlNw=="
},
"payload": {
"pickUpDate": "{{$date startDate 'D MMM YYYY'}}",
"dropOffDate": "{{$date endDate 'D MMM YYYY'}}",
"car": "{{car}}",
"price": "{{car.price}}",
"city": "{{city}}",
"email": "{{email}}"
}
},
"messages": [
"Your car is booked. Your booking reference is {{order-response.bookingRef}}"
],
"conditions": [
"{{wantsToBook}}"
]
}