Google Calendar API integrated into Autonomous BotPress ChatBot
🔍 Deep Dive into AI Technology: This video is more than just a demonstration; it’s a deep dive into the potential of AI in our daily lives. Whether you’re an AI enthusiast, a professional looking to integrate similar technology, or just curious about the future of AI in practical applications, this video has something for you.
Seamless Integration: Watch how Google Calendar API blends perfectly with the BotPress platform, creating a smooth and efficient booking experience.
Natural Language Processing: See the chatbot in action, handling real-life booking requests with ease and understanding, just like a human assistant.
Autonomous Functionality: Explore how this chatbot autonomously manages appointments, from scheduling to rescheduling, without any manual intervention.
Google Calendar API AI Integration DEMO
This demo has limited functionality as showcased in the video presentation.
It was created to present the Natural Language Processing ability of chatbots, in transforming relevant user input into an API Call.
This is the same model from the video, you can test it here.
To access the google calendar: View API Test Calendar
To download the BotPress Bot Template: Download G. Calendar Api Ai integration demo
The Programming and Logic Behind this demo
This diagram showcases one of the potential ways into building simple autonomous Ai Systems that can cooperate with 3rd party applications, transforming “natural language” into computer commands.
At the core of this system is a LLM model that analyzes the user input, looking to determine the user’s intention and routing it towards the appropriate “Ai Agent”
How do you make an Ai Chat Bot setup Google Calendar Apointments for You?
This Ai based system:
- can check availability for a particular date/time,
- can book appoinments for clients,
- can verify details of already booked appoinment,
- can rescheadule meetings,
- can cancel meetings.
This system can answer requests formulated in natural language, and uses both natural language and classic code to achieve it’s goals.
Hello – Introduction
The first step is Hello!
The second step is letting the chat partner know who we are and what we can do for them.
First Question
First question addressed to the user.
In this example it will be also our fall back question.
Ai – Intention Managment Hub
This is the first call upon Ai
In this node the Ai is tasked to categorize the user intention and it’s answer will send the userinput to one of our “Logical Agents” for further processing.
Intention Relay Hub
Once the Ai answers, the result is put through a relay hub and pushed towards the next step in it’s solving.
Ai Task Instructions:
You are a booking agent.
You will be provided with the last message the user sent. Your task is to categorize the the user's intention into one of the following categories:
0 = wants a generic check if a specific time/date is available
1 = wants to make a booking / reservation
2 = wants to verify/confirm/find out about a reservation
3 = wants to change the reservation to another date
4 = wants to cancel, delete, or annul the reservation
5 = wants something else
Do not respond to the user input directly. Instead, respond with the categorization number, like this:
workflow.ai_categorize = x // where x is a number from 0 to 5 based on the categorization made.
Ai Task Input:
user intention:[ @workflow.userIntention ]
Once the user inputs his/her request the task is processed, if found to be booking related is sent to the booking agents down the relay hub.
The first time it passes from start to booking agents it loads scheduling rules, current time and Google Calendar API keys.
Load Company Rules:
workflow.companyBookingSchedule = 'Bookings can be made only from Monday to Saturday between 12:00 to 17:00.'
workflow.companyBookingSlots = 'Bookings have an one hour lenght'
workflow.companyBookingRules = 'Bookings can be made up to 7 days in advance from current date.'
workflow.companyHours = '12:00-17:00' //must be in this format eg. '00:00-12:00'
Load Current Date/Time:
const currentDate = luxon.DateTime.local().setLocale('en').toUTC().toFormat("EEEE, yyyy-MM-dd ' | ' HH:mm");
workflow.gc_systemTime = currentDate;
Load Google Calendar API + credentials - Get OAuth Key:
// Define the credentials for Google OAuth. These should ideally be stored in a secure environment or configuration file.
const credentials = {
APIkey: '',
clientId: '',
clientSecret: '',
refreshToken: '',
calendarId: ''
}
/**
* Get access token from Google OAuth using the refresh token.
*
* @param {Object} credentials - The OAuth credentials.
* @returns {string} - The access token.
*/
async function getAccessToken(credentials) {
try {
// Make a POST request to Google's OAuth token endpoint.
const response = await axios.post('https://accounts.google.com/o/oauth2/token', {
client_id: credentials.clientId,
client_secret: credentials.clientSecret,
refresh_token: credentials.refreshToken,
grant_type: 'refresh_token'
});
// Log the successful retrieval of the access token.
console.log("Successfully fetched the access token.");
// Return the access token from the response data.
return response.data.access_token;
} catch (error) {
// Log the error and re-throw to handle it at a higher level.
console.error("Error fetching access token:", error);
throw error;
}
}
// Using top-level await to get the access token.
try {
const accessToken = await getAccessToken(credentials);
// Assign the access token to the workflow object.
workflow.gc_bearer = accessToken;
workflow.credentials = credentials;
// Log the successful assignment of the access token to the workflow object.
console.log("Successfully assigned the access token to the workflow object.");
} catch (error) {
// Handle or log any errors that might occur during the process.
console.error("Error in main execution:", error);
}
Relay Hub
Once the Auth is over the first message, or any other further initial message that triggers the booking system is assigned to 1 of our 5 agents.
- 00 Availability checker
- 01 Book Maker
- 02 Booking Checker
- 03 Booking Editor
- 04 Booking Cancelar
The hub can also be used as an internal relay for more advance applications.
Ai Availability Checker Agent
Ai Availability Checker Agent
The availability checker agent is made of ai logical processing units that opperate togheter at achieving
- data colection by interogating the user.
- data transformation by levreging the natural language capabilities of Ai
- data transference by executing API calls.
AI Data Retrieval Logical Module
Scans and interrogates user for essential details, in this case date and time.
AI Date/Time Transformer
whatever format date and time format the user input it will be transformed into the standard for the API and saved to a variable.
The request is sent to the API
Once we get and validate all data we initiate the api calls.
AI Availability Report
once the API call logic has a result the AI analyzes it and replays to the user.
Once the user input arrives into the Ai AC Agent it’s processed along an ai task that is required to make a simple form to keep track of both time and date, and also tries to extract both the time and the date if they are present in the user input. This task will be called only once at the beginning of the process.
Ai Data Colection Module
This is the logical core incharge with colecting the required data for checking booking availability.
This system needs to interogate the user for, date and time. Once it has this information it passes it on the next core.
Ai Task Instructions:
You are a booking agent.
You will be provided with the last user message.
1. Check if the user asks about a specific date and note it in the report.
2. Check if the user asks about a specific time and note it in the report.
report Desired Result:
Date For Booking: [write null or place the date you found]
Time For Booking: [write null or place the time you found]
Ai Task Input:
User Intention: [ @workflow.userIntention ]
After this process the result is sent to another AI task that is requested to check if in the form both the time and date are filled, if yes the message is sent further into the next core else it is remains in this core. This task will be called every time until “yes”.
Ai Task Instructions:
You are a booking agent.
You will be provided with a user's booking entry.
Format for Input:
Date For Booking: [Filled or null]
Time For Booking: [Filled or null]
Confirm with "yes" if all the two values are filled and neither null. Indicate with "no" if any value is null.
Desired Result:
workflow.ai_BookingCheckReady: [yes/no]
Ai Task Input:
User's Booking Details:
@workflow.ai_catchBookingCheck
Relay Hub:
ai_BookingCheckReady = 'yes'
If the answer was no, the form will be sent to this task that has to come up with a question for the user requiring for any missing details, in this case the date and/or the time.
Ai Task Instructions:
You are a booking agent.
You will receive a booking entry.
Craft a response requesting only for the unfilled or null entries field in the entry details.
Format for Input:
User's Booking Entry Details:
Date For Booking: [Date or null]
Time For Booking: [Time or null]
Desired Result:
workflow.ai_checkBookingCheck: [Your request for the user]
Ai Task Input:
"User's Booking Entry Details:
@workflow.ai_catchBookingCheck "
User Input: [user gives date and or time hopefully]
After we get the new user input we process it with the next task that has the job to check the user input for date and time and update the form.
Ai Task Instructions:
You are a booking agent.
You'll Receive:
1. The "Last Question Addressed to the User."
2. The "Last Chat Message Sent by the User."
3. The "User's Last Booking Details."
Your responsibility is to synthesize this information to complete or update the booking entry accurately.
the user can provide as an answer, a number, a day name or the day's number. Correlate the user answer with the last question.
Construct your response in the following format:
workflow.ai_catchBookingCheck:
Date For Booking: [Enter or Update the booking date or "null" if not provided]
Time For Booking: [Enter or Update the booking time or "null" if not provided]
Ai Task Input:
[Last Question Addressed to the user: @workflow.ai_checkBookingCheck]
[Last Chat Message sent by the user: @workflow.userIntention]
[User's Last Booking Details:
@workflow.ai_catchBookingCheck ]
Once this is completed the result will be sent back for checking to see if both date and time are filled in the form, if no this loop will run again, asking the user for date and time, getting the user input and analyzing, filling the form rechecking etc.
If the answer after recheck is yes then the form will be sent to the next core.
Ai Date / Time Transformation
The time and date provided by the user are transformed into standardized date/time format.
If the user provided a time and date like the first monday of next month at noon, here this input would be transformed into something like 04.12.2023 at 12:00, but in a very specific format that is required for the API call
Ai Task Instructions:
You are a booking agent
You will recieve a booking entry and your task is to convert the time and date format.
1. Use the "system time" to convert the day into a specific date (e.g., "Monday" to "Monday, 2023-11-06").
2. Convert the provided time into full UTC time format (e.g., "2" or "2 PM" to "14:00").
answer like this:
workflow.user_BookingDate: yyyy-mm-ddThh:mm:ssZ
Ai Task Input:
Booking Entry: @workflow.ai_catchBookingCheck
System Time: @workflow.gc_systemTime
Now the google calendar api call logic is triggered. (to see it skip forward)
once the result comes back, depending on the finding, it’s sent to one of the two availability reports.
Ai Availability Report
The Ai recieves information through Google Calendar API. Formulates an answer back to the user.
If Unavailable - Ai Task Instructions:
You are a booking agent.
You will receive a booking entry and a list of available time slots for the day, if any.
The client was turned down as the time slot he requested is unavailable.
Explain the client the issue, Make a recommendation to the client based on available time slots you received properly formatting into readable format.
Ai Task Input:
User's Last Booking Details: [ @workflow.ai_catchBookingCheck ]
availlable time slots: [ @workflow.companyBookingDailyAvail ]
If Available - Ai Task Instructions:
You are a booking agent.
You will receive a booking entry and a list of available time slots for the day, if any.
The user requested to check a time slot availability, acknowledge the user by confirming the day and hour of it's choosing are available.
Ai Task Input:
User's Last Booking Details: [ @workflow.ai_catchBookingCheck ]
user booked time: [ @workflow.user_BookingDate ]
Ai Book Maker Agent
Ai Book Maker Agent
The book maker agent is made of ai logical processing units that opperate togheter at achieving
- data colection by interogating the user.
- data transformation by levreging the natural language capabilities of Ai
- data validation by analizing the request against company policy.
- data transference by executing API calls.
Ai Data Collection Module
This is the logical core in charge with collecting the required data for a booking.
This system needs to interrogate the user for the name, date and time. Once it has this information it passes it on the next core.
Ai Date / Time Transformation
The time and date provided by the user are transformed into standardized date/time format.
With the exception of the form requiring a name as well not just a date and time, this first core of the Booking Agent is pretty much the same with the first core of the Availability Agent, as well as the date and time transformation. The exact prompts can be extracted from the botpress template.
Ai Policy Validator
This is the logical core incharge with validating the booking details against Company Policy. If validation failed, user is informed about the issue and sent back to ai data colection module. If it passes the info goes through the next step.
Ai Task Instructions:
As a booking agent, you will be given essential resources to conduct your duties:
1. Current Date/Time: This is the reference point for all bookings.
2. Company's Booking Policies: These are the guidelines that determine booking compliance.
3. User's Booking Details: This is the information submitted by the user that needs to be evaluated.
Your role is to cross-reference the user's booking details with the company's policies and the current date/time to determine if the booking is compliant.
Report Guidelines:
Your report should be structured as follows, with each section filled out based on whether the user's booking details adhere to the company's policies, check date and time separately :
Desired Result:
Booking Name: [Compliant if it adheres to the policy; if not, detail the reason for non-compliance.]
Date For Booking: [Compliant if it meets the policy standards; otherwise, explain the discrepancy.]
Time For Booking: [Compliant if it is within the allowed time slots; if it violates policy, describe the issue.]
Ai Task Input:
Current Date/Time: @workflow.gc_systemTime
Company Booking Policies: @workflow.companyBookingRules, @workflow.companyBookingSchedule, @workflow.companyBookingSlots
User's Booking Details: @workflow.ai_reviewBookingDetails
Carefully analyze the provided booking details and develop your report, ensuring that it accurately reflects compliance or non-compliance with the established booking policies.
After policy check the result is sent to a validator task that will have to replay with yes or no, if yes, all data is passed foreword if not …
Ai Task Instructions:
You are a booking agent.
1. You will receive a booking entry with a name, day, and time.
2. You will receive a booking entry report that will show if there are any issues with the items in the entry.
If all details are compliant replay with 'yes'
If there are any issues let the user know what does are.
Ai Task Input:
booking entry
@workflow.ai_reviewBookingDetails
booking entry report
@workflow.ai_checkPolicyResult
So if the check failed we will reprocess the data from our little form and send it back to the first core.
Ai Task Instructions:
You are a booking agent.
1. You will receive a booking entry with a name, day, and time.
2. You will receive a booking entry report that will show if there are any issues with the items in the entry.
Your responsibility is to synthesize this information to complete or update the booking entry accurately.
Construct your response in the following format:
workflow.ai_reviewBookingDetails:
Booking Name: [if compliant the client's name or "null" if not compliant ]
Date For Booking: [if compliant the booking date or "null" if not compliant ]
Time For Booking: [if compliant the booking time or "null" if not compliant ]
Ai Task Input:
booking entry
@workflow.ai_reviewBookingDetails
booking entry report
@workflow.ai_checkPolicyResult
If the answer would have been yes, so the form would have passed the check, the form, would have been sent to the last transformer task before it’s sent to the Google Calendar OAuth Call
Ai Task Instructions:
You are a booking agent
You will recieve a booking entry and your task is to preserve the name and convert the time and date format.
answer like this:
workflow.user_BookingName
workflow.user_BookingDate: yyyy-mm-ddThh:mm:ssZ
Ai Task Input:
Booking Entry: @workflow.ai_reviewBookingDetails
Ai Availability Report
The Ai recieves information through Google Calendar API. Formulates an answer back to the user.
If the time slot was available, the booking has been made, if not we will go through another transformer task, let the user know the issue and start all over again.
Ai Task Instructions:
You are a booking agent.
You will receive a booking entry and a list of available time slots for the day, if any.
The client was turned down as the time slot he requested is unavailable.
Explain the client the issue, Make a recommendation to the client based on available time slots you received properly formatting into readable format.
Ai Task Input:
User's Last Booking Details:
[ @workflow.ai_reviewBookingDetails ]
availlable time slots: [ @workflow.companyBookingDailyAvail ]
Ai Task Instructions:
You are a booking agent.
1. You will receive a booking entry with a name, day, and time.
2. You will receive a booking entry report that will show if there are any issues with the items in the entry.
Your responsibility is to synthesize this information to complete or update the booking entry accurately.
Construct your response in the following format:
workflow.ai_reviewBookingDetails:
Booking Name: [Leave the same ]
Date For Booking: [leave if no issues or "null" if not compliant ]
Time For Booking: [leave if no issues or "null" if not compliant ]
Ai Task Input:
booking entry: @workflow.ai_reviewBookingDetails
booking entry report: @workflow.ai_checkBookingDetails
Google Calendar API Get / Post Code
Google Calendar API Check Code
This part of the software does time slot check for a given date/time
This part of the software retrieves all scheaduled events for a given date and filters in available time slots.
So whenever the chatbot is requested to check availability or to push an event to the calendar, makes an API call to google and and checks how many events are booked at that time.
const currentDate = luxon.DateTime.now().toISODate() // Get the current date in ISO format
const calendarId = workflow.credentials.calendarId // Replace with your Google Calendar ID
const selectedTime = luxon.DateTime.fromISO(workflow.user_BookingDate);
const timemax = selectedTime.plus({ hours: 1 }).toUTC().toISO({ suppressMilliseconds: true });
// Set up the Google Calendar API request
const url = `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`
const params = {
timeMin: workflow.user_BookingDate, // Start search time
timeMax: timemax, // End search time
key: workflow.credentials.APIkey // Replace with your Google API key
}
// Make the API request to fetch events for the specified duration
const response = await axios.get(url, { params })
// Extract the events from the response
const events = _.get(response, 'data.items', [])
// Log the count of events for the specified duration
workflow.eventCount = events.length;
console.log(`Total events for the specified duration: ${events.length}`)
While i’ve skipped explaining some of the relays this one is quite important as the software is designed to accept only 2 bookings for a time slot.
If there are less than 2, depending on what agent called the script it will either proceed with pushing the event or returning the information to the AI, and that would be that there is a vacant slot.
workflow.eventCount >= 2
So if the count returns 2 or higher then we know we are booked so we will run a check for the duration of the date and see if we find any openings.
Date/Time Transformer
Here i had to run some judo on the date/time variable and transform it for the next phase.
const timestamp = workflow.user_BookingDate;
const dateObject = new Date(timestamp);
const year = dateObject.getUTCFullYear(); // gets the year (four digits)
const month = dateObject.getUTCMonth() + 1; // getUTCMonth() returns 0-11, so add 1 for 1-12
const day = dateObject.getUTCDate(); // gets the day of the month (1-31)
// Ensuring the month and day are in 'MM' or 'DD' format
const formattedMonth = month < 10 ? `0${month}` : month;
const formattedDay = day < 10 ? `0${day}` : day;
// Combining year, month, and day to YYYY-MM-DD format
const extractedDate = `${year}-${formattedMonth}-${formattedDay}`;
workflow.user_SelectedDate = extractedDate
console.log(workflow.user_SelectedDate); // Outputs: 2023-11-06
Retrieve available time slots with fewer than 2 events.
Here we are going to fetch all events for the day and check witch time slots have fewer than 2 events, we store it in an array and send it back to the ai so it knows what recommendation to make,
// Retrieve the selected date and company hours from the workflow object
const selectedDate = workflow.user_SelectedDate; // Format: 'YYYY-MM-DD'
const companyHours = workflow.companyHours; // Format: 'HH:mm-HH:mm'
const calendarId = workflow.credentials.calendarId; // Google Calendar ID
const APIkey = workflow.credentials.APIkey; // Google API key
// Function to fetch all events for the selected date
async function fetchAllEventsForDay(dayStart, dayEnd) {
try {
// Perform the GET request to the Google Calendar API for the entire day
const response = await axios.get(`https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`, {
params: {
timeMin: dayStart.toUTC().toISO(),
timeMax: dayEnd.toUTC().toISO(),
singleEvents: true,
key: APIkey
}
});
// Extract and return the events from the API response
return _.get(response, 'data.items', []);
} catch (error) {
console.error('Error fetching events for the whole day:', error);
return [];
}
}
// Function to find time slots with fewer than 2 events for the selected date
async function findAvailableTimeSlots() {
// Parse the company hours to get the start and end times
const [startTime, endTime] = companyHours.split('-');
// Combine the selected date with the start and end times to get the DateTime objects
const dayStart = luxon.DateTime.fromISO(`${selectedDate}T${startTime}`);
const dayEnd = luxon.DateTime.fromISO(`${selectedDate}T${endTime}`);
// Fetch all events for the day
const allEvents = await fetchAllEventsForDay(dayStart, dayEnd);
// Prepare an array to hold time slots with fewer than 2 events
let timeSlotsWithFewerEvents = [];
// Loop over each hour within the company hours
for (let hour = 0; hour < dayEnd.diff(dayStart, 'hours').hours; hour++) {
const currentSlotStart = dayStart.plus({ hours: hour });
const currentSlotEnd = currentSlotStart.plus({ hours: 1 });
// Filter events that are within the current time slot
const eventsInCurrentSlot = allEvents.filter(event => {
const eventStart = luxon.DateTime.fromISO(event.start.dateTime || event.start.date);
const eventEnd = luxon.DateTime.fromISO(event.end.dateTime || event.end.date);
return eventStart < currentSlotEnd && eventEnd > currentSlotStart;
});
// If there are fewer than 2 events in the current time slot, add it to the list
if (eventsInCurrentSlot.length < 2) {
timeSlotsWithFewerEvents.push({
start: currentSlotStart.toUTC().toFormat('yyyy-MM-dd\'T\'HH:mm\'Z\''),
end: currentSlotEnd.toUTC().toFormat('yyyy-MM-dd\'T\'HH:mm\'Z\'')
});
}
}
// Return the list of time slots with fewer than 2 events
return timeSlotsWithFewerEvents;
}
// Self-invoking async function to handle the fetching and processing
(async () => {
try {
// Wait for the findAvailableTimeSlots function to complete and get the slots
const slots = await findAvailableTimeSlots();
console.log('Time slots with fewer than 2 events:', slots);
// Now that you have the slots, you can set them on the workflow object
workflow.companyBookingDailyAvail = slots;
} catch (error) {
console.error('Error finding available time slots:', error);
}
})();
Google Calendar API - Push Event To Calendar Code
Whenever we do a booking this will be the final destination, this is the code that makes the final step into transforming natural language into a scheduled booking in Google Calendar.
// Combine the date and time to get the full DateTime
const eventDateTime = luxon.DateTime.fromISO(workflow.user_BookingDate);
const bookingName = workflow.user_BookingName;
const accessToken = workflow.gc_bearer;
const calendarevent = {
summary: bookingName,
start: {
dateTime: eventDateTime.toISO(),
timeZone: 'Europe/Bucharest'
},
end: {
dateTime: eventDateTime.plus({ hours: 1 }).toISO(),
timeZone: 'Europe/Bucharest'
}
};
await createEvent(calendarevent, accessToken, workflow.credentials.calendarId);
async function createEvent(calendarevent, accessToken, calendarId) {
await axios.post(`https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`, calendarevent, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
}