Hello everyone!
Welcome to the step-by-step tutorial for building
Sicky - a chatbot that can send out-of-office emails if you are sick (or just don't want to work today
😉 ).
This tutorial is part of
SAP CAI's tutorial challenge, so feel free to give a Like if you like it!
Introduction
Our plan is to build a chatbot that can send out-of-office emails. We want to do this because it's fun and we like to explore things.
However, if we want to convince the business people that this is a good idea, we better have some arguments! So we will start this tutorial by looking at the related business process and try to find reasonably good reasons to change this process (to introduce a chatbot
🙂 ). After we have conviced the business, we are starting with the actual implementation of the bot and the integration with Telegram. We will encounter some issues (with respect to buttons and Telegram) and learn how to analyze issues like this and find workarounds for them. At the end, we also take a look at possible extentions of our chatbot.
So without further ado, let's go!
Changing a business process
The as-is business process
Let me introduce you to Barbara, the technical lead of our SAP CAI experts team. She is not feeling well today; indeed, she is feeling terrible and would very much like to stay in bed the whole day. Nevertheless, she has to get up, boot up her laptop and email Marc, our business unit assistant, telling him that she is ill and out of office today (and probably also tomorrow and the day after tomorrow). Then she can shut down her laptop and go back to bed.
Marc receives Barbara's email and does a couple of things:
- First, he writes an email to all members of Barbara's team informing them that Barbara is out-of-office today.
- Second, Marc forwards the out-offfice info to the payroll team.
- Third, he reminds Barbara that she needs an official sick note from her doctor if she is out-of-office for more than two days.
- And of course, he also whishes her a speedy recovery!
Why change this process?
If you have been in Barbara's situation (I certainly have been there), you know that sometimes it is rather annoying to start up your laptop just to write that one teeny-tiny email to Marc. I mean its not suuuper annoying, but... you know, if something could be done about it, why not?
Additionally, have you tried writing an email while NOT checking your inbox? Sure, it's no big thing - but Barbara would rather not have read her emails on that particular day.
One the other side, we have Marc. For him it is just a couple of simple, repetitive tasks. Receive an email, write some emails. Depending on the size of the business unit Marc is responsible for (and the season of the year, I guess), it maybe takes up 30-60 minutes per week.
Not too much time, you might think but it adds up. Maybe there are other similar tasks? Maybe reducing this repetitive workload on Marc allows him to take up other, additional roles (or just have a longer coffee break). In any case, I don't think Marc would miss this particular task if it was taken from him.
How do we want to change the process?
What would be the ideal situation?
Barbara would like to not get up from here bed and to not accidentally read her email (physical and mental healthcare
😉 ). Ideally, she would just pick up her phone and message someone that she is out of office today. Maybe via Telegram or WhatsApp?
Marc doesn't mind writing these out-of-office emails. It has been part of his job up until now but he also doesn't care if this part of his job is taken over by somebody else.
Well, guess who this
somebody could be?
Yep, it's
Sicky, our SAP Conversational AI chatbot for handling the whole reporting sick process.
Botbuilding
Planing the conversational flow
Let's start by looking at the planned conversational flow.
A few notes about this one:
- Sicky immediately asks if Barbara wants to report sick. Why? Because we want to make it as easy as possible for Barbara to get things done. And at the moment Sicky can do one thing and one thing only. So why not directly ask if Barbara wants to do the only thing that Sicky can do? Ideally, we can show buttons for answering this question.
- Why do we ask for the email address? Well, we need to somehow know who is reporting sick. The name might not be unique. And we can also use the email address to send a confirmation email to Barbara.
Why would we want to that? Just to make sure that you at least get an email if somebody else reports you as out-of-office via Sicky 😉
- Before Sicky sends all necessary emails, there is a small summary of all the information Sicky wants to send via email. This is just to make sure that Barbara has the chance to correct anything that might not be correct.
Building the conversational flow
There are couple of things that we have to do here:
- first we need to create a bot
- next we have to build our conversational flow in our new bot
- third we have to integrate our bot with Telegram
- and lastly, we should test if everything works as intend.
Creating the chatbot
Let's go to
www.cai.tools.sap sign in (or sign up) and hit the big blue button:
We want to create a chatbot that can
Perform Actions and we equip
Sicky with the
Greetings and the
Small Talk skills.
We give
Sicky the correct name and enter a perfect description
😉
Continue by choosing the language that you want
Sicky to understand initially. Support for multiple languages can be added later.
As for the Data Policy, we are going with
Sensitive Personal and start with
Storing the data. Later on, we can change this setting but it is helpful while we are still developing
Sicky to see everything that is going on.
Finally,
create your bot and we are ready to start training
Sicky.
Building the flow
This is a (sort-of) long process, so let's first get an overview of what we want to do.
Sicky should:
- respond with "Hi I'm Sicky" when someone says "hi"
- immediately ask if the user wants to report sick, ideally using pre-defined buttons
- ask for how long the user is out-of-office
- ask for the email address
- provide a summary
- send an email to Marc
Step 1 - "Hi I'm Sicky!"
Since we decided to equip
Sicky with the
Greetings and the
Small Talk skills, we already see a lot of pre-defined intents.
Following our planned conversational flow, we don't need to introduce a custom intent (for the moment). A conversation would always start by the user saying "hi" or something like this, which should be recognized as the
@greetings intent. Meaning we don't have to do anything here for now.
So let's go directly to the
Build tab and select the
greetings skill.
We want to modify the response that
Sicky gives when somebody says "hi". For this, we go to the
Actions tab and edit the pre-defined responses to the
@greetings intent.
Don't forget to click
SAVE!
Let's see if it works. Open the
Chat Preview in the bottom right corner and say "HI".
Step 2 - "Feeling sick?"
Next, we want
Sicky to ask the user if they want to report sick.
For this, we go back to the
Build tab (just click on the Build tab again) and create a new skill.
Enter a reasonable name for the new skill and
Add it to
Sicky.
Open the skill and go the
Actions tab. There, we
add a message group and choose to
Send a Message.
As said earlier, we want the user to answer this question by pushing some
buttons, so this is the option that we choose.
Let's ask the user if they want to report sick and add a button that says "yes". When creating the button, we have to choose what should happen when the button is pressed. Let's go with
Trigger Skill for the moment, since we want to redirect to another skill, when a user answers "yes".
Leave the "Select a skill to trigger" box empty (we have not create these skills yet) and create another button for "no".
What's next? We need to link the first skill ("Hi, I'm
Sicky") to the skill that we just created. For this, let's go back to the
greetings skill and select the
actions tab. Right below the last greeting we can choose to
update the conversation.
We select to
Go To another skill and enter the name of the skill we just created. In my case, this is "wanna-report-sick".
Again, don't forget to hit
SAVE.
Let's check again if it works.
As we can clearly see, we are lacking the skills (hahaha) to continue after a user selected "yes" or "no".
So let's go to the
Build tab and create two new skills (one for "yes" and one for "no"). And give them some reasonable names - I called them
bye and
ask-sick-period.
Next, we go to the
wanna-report-sick skill, enter the
actions tab and link the "yes" button to our
ask-sick-period skill and the "no" button to the
bye skill.
Now, these skills are automatically executed when the user selects "yes" or "no"
If the user selects "no", then there is nothing left to do for them with this bot. So
Sicky can kindly say
bye and
reset the conversation.
Step 3 - "How long are you OOO?"
If a user selects "yes",
Sicky should ask them for how long they want to report sick.
There are a number of different options we can choose from.
- We can add a Requirement for the entities #datetime and #duration and use SAP CAI's built in NLP to determine one or the other from the user input.
- We can just take the raw user input and not rely on SAP CAI's built in entities.
Which option you choose, highly depends on your language. I found that option one works nicely for English. However, for German I found a lot of typical examples that where not recognize as
#datetime or
#duration. So for German, I would go with option two.
Anyways, let's quickly show both options.
Option 1
Go to the
Requirements tab of your
ask-sick-period skill. Add a requirement for the
#datetime entity and another requirement for the
#duration entity. Note that by default these requirements are linked by an
AND. We don't want that. For us it is sufficient (expected) that only one of them is filled. So just click on the
AND to make it an
OR. Additionally, we want to add some user feedback so that they know what they are supposed to do.
Add
New Replies if both requirements are not satisfied and ask the user for how long they intend to be out of office.
Try it out! You can examine the data which is picked up by
Sicky by clicking on the small yellow icons in the chat.
Option 2
As said above, option 1 works nicely for English but there are examples in other langues that just don't work. (Try out the German "bis übermorgen" for example
🙂 )
So instead of relying on SAP CAI's pre-trained entities, we are just going to use the raw user input.
If you have not done this before with SAP CAI, you will probably find it a little cumbersome. But at the moment there is just no other way.
What's the plan?
In the
ask-sick-period skill we will ask the user for how long they plan to be out of office. The answer of the user is picked up in a second skill. We have to trigger that skill from
ask-sick-period, For this to work properly, we have to define a custom memory field "waiting_for_sick_period" and set it in the
ask-sick-period skill.
So let's go to the
action tab of the
ask-sick-period skill. We ask the user for how long they expect to be sick and then choose to
edit the memory.
There, we define the
waiting_for_sick_period memory field and set it to
true.
Additionally, we want to
Go To another skill (say
read-sick-period) which picks up the user input and saves it to memory.
Go ahead and create the skill
read-sick-period and link to it from the
ask-sick-period skill. This time, we have to specify that we want to
wait for user input.
SAVE and go to the
read-sick-period skill (you can click on the skill name after saving) and open the
triggers tab.
Here we specify that this skill should start, if the
_memory.waiting_for_sick_period field is set to
true.
Next, we go to the
actions tab and
update the conversation by
setting a memory field. Whatever the user has entered after
Sicky asked them for how long they expect to be sick, is stored in the field
nlp.source. We want to use this value and save it to a custom memory field, say
sick-period. To do this, we have to
use scripting to build the JSON and we have to put
quotation marks around
{{nlp.source}} (The curly brackets are there to tell SAP's CAI that this is a variable and not a string).
Additionally, we
unset the
waiting_for_sick_period memory field, since we are no longer waiting for the user input.
Now we are done and can continue the flow of the conversation by redirecting to the next skill.
Step 4 - "What's your email address?"
We create a new skill in the
Build tab and call it
ask-email. In this skill, we add a
requirement for the
#email entity. Also, we add some replies like "What's your email?" to
if #email is missing.
Right now,
Sicky should have collected all the information required to send the out-of-office-email to Marc. Before doing so,
Sicky should confirm that the information that was picked up is correct.
Step 5 - Summary
Let's create another skill and call it
provide-summary.
If you chose Option 2 earlier, then this is straightforward: create a button and ask the user if they are happy with the data picked up by
Sicky. If so, we continue to another skill,
send-email. If the user is not happy with the data, we reset the conversation and start again from the beginning (of course, we could do better by asking which part is wrong and make the user only correct this one - but I will leave this as an exercise for you
😉 ).
If you chose Option 1 earlier, we don't know in which memory field the input of the user is stored. Therefore, we have to distinguish between the two cases:
- the user wrote something like "for 2 weeks"
In this case, the input is stored in the #duration entity. We can access this information via the memory.duration field and format the output to display the number of days.

- the user wrote something like "until tomorrow"
In that case, the information is stored in the #datetime entity. We access the information via memory.datetime and can choose if we want to display it formatted or in iso format.

- the user wrote something like "until the end of the week"
In this particular case, the information is stored again in the #datetime entity but only in the raw field of the #datetime entity. All the other fields are null.
In this case, we want to display the raw user input.

- there are even more cases than this - but I leave this part of breaking Sicky, then fixing Sicky to you 🙂
Again, if the user is not happy they can select "NO" and we redirect to a
reset skill. There, we reset the conversation and redirect to the beginning.
If the user is happy, we redirect to the
send-email skill.
Step 6 - Send an email to Marc
We create the
send-email skill via the
Build tab and add an action to
connect to an external service and
call a webhook. There, we just have to enter the URL of our email service and specify the JSON payload.
If you don't want to send an email, just print a message that you got to that skill successfully.
If you want to send an email, you will need a web service that can do that for you.
On my GitHub, there is a very
simple example email service that you can use for this. Check the readme on GitHub to see how to deploy it to the SAP Cloud Platform.
After deploying to the SAP CP, you can find the public route to your app in the application overview.
We take this URL and paste it into the webhook configuration. We specify the endpoint ("/send") and adapt the JSON
body to fit the expectation of the email service.
Again, we have to add conditions to format the message accordingly, basically the same as we did in Step 5.
And then, we are good to go!
Go ahead and test
Sicky and see if you receive an email (assuming that you have put your email instead of Marc's email
😛 ).
Integration with Telegram
Lastly, we want to integrate
Sicky with Telegram.
Luckily, integrating bots with Telegram is not too complicated. Basically, we just follow the instructions given in the
Connect tab.
When we are done with this, let's go ahead and test it!
Testing
We start the bot in telegram (search for the bot handle) and
START the conversation.
But what is this? oO
It appears that our button does not work with Telegram? What's going on there?
Let's have a look at the
Monitor tab an see what we can see
🙂
Looks like Telegram is returning the id (?) of the "yes" button. But it worked with the integrated chat, right? So let's check what the logs say for a conversation via the integrated chat.
Looks like there is no logged interaction for the "yes" button press at all. So that doesn't help.
Making buttons work with Telegram
Hm, what do we do?
Well, there were other options when we created these buttons (instead of
trigger another skill).
It turns out that the
postback button is the option that fixes our problem (albeit at the cost of some additional work).
Go to the first skill that uses buttons (in my case its the
wanna-report-sick skill) and remove the old "yes" and "no" buttons. Instead create new
postback buttons and put
true and
false ("yes" and "no" are also fine
😉 ) on the right.
When you press a postback button, whatever you put in the box on the right side will be send to
Sicky. If a user now presses the "yes" button we actually receive a
true and can read it.
As for reading the result, we do the same as we did before:
- set a custom memory field (waiting_for_wanna) to true in the wanna-report-sick skill
- create a skill for reading the user input (read-wanna-report)
- redirect from the wanna-report-sick skill to the read-wanna-report skill and wait for user input

- choose to trigger the read-wanna-report skill if the waiting_for_wanna memory field is true

- store the value of {{nlp.source}} into another custom memory field (wannareport)
Note that there a no quotation marks on {{nlp.source}} because true and false don't need quotation marks in JSON. If you decided to go with "yes" and "no" as postback answers, you need the quotation marks.
- redirect to ask-sick-period or bye based on the value of wannareport
Now we are almost done. We just have to do the same for every
trigger a skill button we have
🙂
Luckily, there is only on more button left (after the summary).
I'll leave this to you as a lovely exercise
😛
And then we are done!
Our bot works with Telegram!
Time to tell all your friends that they can use this completely public bot to send out-of-office emails to poor Marc!
😉
Summary and look ahead
In this tutorial, we have seen
- how to look at a business process and come up with an idea for automation
- how to get from a conversation flow to the actual conversation
- how to read generic input from the user
- how to distinguish answers based on the format of data you have read
- how to integrate with Telegram
- how to test and track arising issues
- how to make redirect-buttons work with Telegram
What else could be done by Sicky?
- Of course, we could send out more emails to other people in the company. You already know how to do this 😉
But this is not super interesting.
- We should also introduce an intent for reporting sick. This would allow people who know Sicky to bypass some of the button clicking, by putting all necessary information in the first message to Sicky.
- We could try to integrate with Outlook (Google, ...) to decline/cancel all meetings that are happening during the out-of-office period.
- Thinking about meetings: we could introduce the general usecase of canceling/declining meetings. This seems pretty sexy!
If you are late for any meeting because of traffic or whatever, just take your phone and message Sicky to cancel your next meeting.
Feel free to get in touch with me, if you have any questions or suggestions!
Enjoy and have fun with
Sicky!
Best regards,
Daniel