How To Build A Slack Bot To Efficently Manage Your Timesheet

In this Slack bot tutorial we’re going to cover how we can use a chatbot and a conversational flow to efficently and frictionless record the time spent by each person of your team.

When the Xenioo team started growing steadily a long time ago, two tools became the staple of our internal communication and company life: Slack and the timesheet.

Being mainly remote, our team found Slack to be invaluable for communication and immediate sharing of information, ideas and content. Our timesheet, that came later, is now a key indicator of where we’re putting more effort or where we’re bleeding precious time.

Given this premises, and given our company focus, it was just a matter of time before a full timesheet chatbot would be pitched and green lit.

We all agreed that the key points for us would be:

  • the chatbot would be accessible on Slack like any other user
  • the chatbot would use Xenioo AI engine to let everyone enter their timesheet with a conversational approach
  • the conversation should pose as little friction as possible, tolerating user typing mistakes and vagueness

Setting up the timesheet

As we all know that the primary purpose of a timesheet is to record how much time each person of a team is allocating on different projects. Truth be said, often timesheet applications are so cumbersome that more often than not, team members would ask to open a project named “Timesheet filling” to allocate the time wasted using them.

To make sure that it wasn’t the case for us, we went on a quest to find the easiest and leanest timesheet application available. Eventually, we found Harvest to be the best for us. It is clean, focused and has a good number of API ready to use for our integrations.

Once our account was created, we proceded to create our projects and add all the team members.

harvest integrations

Training Slack bot AI

The key point for our training was the idea that each user could enter their daily timesheet in a conversational fashion. No buttons or clicks but users saying things like “I’ve worked all day on Xenioo” or “I’ve been all the morning on ProjectX” and so on.

To achieve this kind of results we started setting up our intent with some very generic expressions. For example where we would use a generic “project” word when we expected the user to specify the project name.

The result would be a number of expressions like:

  • I’ve worked on project all day
  • I’ve just finished 2 hours of work on project
  • …and so on
start to create a slack bot

Our project word is of course an entity.

The challenge here would be to dynamically detect our project entity with the actual project name. The idea of having our entity pre-trained with all projects was quickly discarded though. In fact , projects and teams come and go and we didn’t want to keep going back to Xenioo to adjust configurations every time.

Thankfully Xenioo helped us tremendously here as we just changed our project entity type from standard to Wildcard.

Wildcard entities are special Xenioo entities capable of wrapping around any text inside the trained sentence and extract any dynamic content.

As we hit the training section we immediately saw this was exactly the right idea!

Even with some very basic training, Xenioo AI engine was already capable of detecting our dynamic project names and let us use them later in our flow.

What we were missing now was some kind of time information.

Users would most of the time say something like:

  • I’ve worked on project all day!
  • I spent the whole afternoon on project 🙁
  • 9 hours on project! can you believe that?

So we had not just information on the project but also some kind of (sometimes) general information about duration.

May we assume all day would be 8 hours or the whole afternoon to be 4? We just needed to extract that information too, so back to training!

We gave to all time information a first pass using Xenioo contextual entities creation:


Of course, we needed a little more complexity as we wanted to have as little changes as possible so that, on the flow, we would just need to check for a small number of variations.

To do this, we moved to direct entity edit. There we specified how our time information would be using synonyms and grouping.

Our very simple initial setup would look something like this:

So saying half a day or afternoon or morning would always be referred and transformed to half a day while all day or whole day to a complete day.

As you can see, we did not check for numbers. Xenioo engine automatically detects numbers in both figure and textual form so we’re getting those for free!

Our next test after some more training lead to a very satisfactory result. Time to hit the design flow!

Creating Slack bot flow

Where do we start to create a Slack bot on Xenioo?

Being a fully conversational chatbot, our flow would have very little (let’s say no) buttons. It need an initial “Project” interaction that would receive our AI trigger with project and time.

Once the interaction was created, we just configured our trained intent so that it would redirect automatically as soon as the expression was detected.

The first thing we want to do next, in our interaction, is to call Harvest API. In fact, we need to retrieve the list of all projects.

Unfortunately, Harvest doesn’t have a project search API. For this reason, we will need to actually download the whole list of projects. However this helps us in another way: we can leverage Xenioo comparison engine to find matches inside typos and misspells.

But first things first. Let’s start with the REST API call we needed to get our projects, which was quite easy to setup:

This call will basically retrieve all the projects that are available on Harvest as a structured json.

If successful, our variable that you can see named harvest-data, will contain the full json reply. It would look something like this:

{
  "projects": [
    {
      "id": 27664097,
      "name": "Xenioo",
      "code": ""
    }
  ]
}

What we’re looking for is the id and the name fields.

What we can see from the structure is that we’re receiving (of course) an array of projects.

Now we could use a Cloud Scripting Action to get the json from the harvest-data variable, transform it into a complete object and use a “for cycle” to check all the names. However, that would have hidden inside a script some important logic.

We decided instead to fully use Xenioo dynamic parsing and action capabilities to create a fully designed loop.

Creating a no-code loop in Xenioo

The fundamental idea of a no-code approach is that you are still doing what you would do by writing lines and lines of code but using a high level designer.

It is not quite different from designing your software using a meta-language, although in this case we’re using a graphical designer.

The first thing we need to do is initialize a looping variable. With great creativity, we’re going to call it loop. We’re setting loop to zero as we will be starting from the very first project and we will move away to enter the real loop right away.

Now, inside our loop we need to check if the project name is somewhat matching with the project our user has mentioned.

We’ll be using Xenioo dynamic JSON parsing and text comparison capabilities to check exactly the contents of the current entry.

The ingenious thing happening here is that Xenioo dynamic parsing is recursive. Therefore first {{loop}} will be replaced with its current value and then, using JSON dynamic parsing, we will be able to evaluate the value of name for the current project.

The value we want to check is the current value of project, the wildcard entity we’ve used in our AI (everything is coming together!).

Last but not least, we’re telling Xenioo comparison engine to accept an 80% similarity, which gives space to some typos and misspells.

If the project is found, we move to the project found interaction. If not, we increase our loop variable value and go back to the beginning.


Of course, we do not want to have loop go higher than the count of projects. To avoid this, we also add that check, using the Length keyword of Xenioo JSON dynamic parsing.

Our loop is done and completed in a true no-code fashion! What we’re missing now is to check that our conversation has all the data we need.

Handling incomplete chatbot requests

As you start working with user requests that are not coming from a fixed flow, you will quickly realize two very important things:

  1. Users may (and quite often will) use expressions you would never think of.
  2. Users may (and quite often will) split their request into multiple steps.

The first one is a matter of continuously training your AI.

You can surely do a great initial job (even more if you have already a good number of examples to import for AI pre-training). However, be ready to get back to check sample conversations or interactively re-train your AI using Xenioo real-time AI logs.

Of course, the more your chatbot will become capable of handling users request, the less you’ll need to come back to train your AI.

The second one, instead, means that while a user may say “I’ve worked all day on Slack”, another user may say “I’ve worked on Slack”. The first user has given us both the information we want: time and project. The second one, just the project.

To handle these cases, we need to check, in our flow, if everything has been extracted by our AI. If not, we need to ask the user to complete the information supplied.

Since the entity handling the time is called timeslice, we will check for that.

how to create a dialog flow chatbot


But what if our user fully specifies a number of hours? We said in the beginning, that Xenioo would automatically detect and create numeric entities parsed inside the user sentence. In this case timeslice, as we have defined it, could be empty, but we can still have a number.

Let’s make sure we also handle these cases too.

flow editor of xenioo

Once we’ve all of our data ready, we can simply call Harvest Time Entry API to add our work to the timesheet.

And what would be a full day of work without some motivational quote? Let’s add some of them too, making sure they are always random.

Our flow is done and ready for prime time!

slack bot flow on xenioo

Activating your Slack bot on the Workspace

To activate our chatbot on our Slack Workspace we must head to our Workspace Administration pages. Just make sure your Slack account has all the required administration privileges and move to the Apps area.

From there create your Slack App.

how manage slack api

Since Slack apps can be many things, we will need to specify we’re creating a Bot application. Give your Slack App a fancy name and save everything.

On the left menu, you should see a “Oauth & Permissions” link. Click on that and make sure to copy the Bot User OAuth Access Token value you see.

chatbot permission token slack


The token you’ve just copied is the only value you need to specify when publishing the Slack bot.

Let’s go back to Xenioo as we’re ready for publish now. Let’s pick the Slack channel, paste our token and click on publish.

That’s it! As soon as your chatbot is online, you’ll receive the very first start message on your Slack Workspace.

Your chatbot is alive and kicking!

how a slack bot works

To Sum Things Up…

Phew! That was a nice run, wasn’t it? So now you know how we internally manage our team timesheet using Xenioo and Slack.

In this post we also understood how to write a no-code loop, how to effectively train our AI in conversational chatbot by both direct expressions and import and how we could attach to external services using API.

Do you want to do something similar for you team and create a Slack bot? Then I’ve got very good news for you! This chatbot is now available for free among tens of other free Xenioo templates. Just sign up now and start building!