- August 29, 2024
- 7 min read
Building an AI Agent for Google Calendar - Part 1/2
Have you ever wished for a personal assistant who could effortlessly manage your day-to-day tasks while helping you find relevant information online? Enter AI agents—intelligent software programs that use generative AI models to interact with users and autonomously perform tasks.
With Friendli Serverless Endpoints and Friendli Tools, you can build AI agents that integrate seamlessly with Google Calendar to optimize your productivity.
In this article, we’ll explore a real-world application of AI agents by learning how to code an AI agent that utilizes tools to connect with Google Calendar and conduct web searches. Stay tuned for part 2 of this blog, where we will build on this code to enhance the AI agent's UI/UX for a visual, interactive user experience on the web.
Figure 1: FriendliAI AI Agent Using Google Calendar- Easily manage your schedule by asking about, summarizing, or adding your events!
Highlights of this blog include…
- Complete Source Code: Includes full AI agent JavaScript code using Meta’s Llama 3.1 70B Instruct model on Friendli Serverless Endpoints and Vercel AI SDK.
- Beginner-Friendly Tutorial: Perfect for beginners, this guide provides all the code and instructions to help you run your first Node.js project, even if you're new to JavaScript.
- FriendliAI Examples GitHub Repository: Visit https://github.com/friendliai/examples/tree/main/tutorials/calendar-cli to check out the complete project on GitHub.
Understanding AI Agents Through the 'Calendar AI Agent'
What is an AI agent in real-life examples?
AI agents are intelligent software programs that autonomously perform tasks using large language models (LLMs). These agents can manage activities like adding calendar events or conducting web searches, similar to virtual assistants like Siri. To demonstrate how these agents work in real life, we’ll walk you through a demo of a user-agent conversation, where the calendar AI agent is asked the following questions:
- Can you tell me my schedule for this week?
- Can you schedule a dinner date event for this Saturday at 6 pm?
- Can you search for the best seafood restaurants near the Hudson River that I can visit for my dinner date?
In Figure 2, the AI agent demonstrates its ability to handle a user query like, “Can you tell me my schedule for this week?” by utilizing tool calls to access the user's upcoming events. For example, the agent responds, “It looks like you have a lunch date scheduled for Thursday, August 29, from 1:00 PM to 2:00 PM.” This response is accurate, as confirmed by the user’s Google Calendar shown in Figure 1, which indeed lists this event in the last week of August.
Figure 2: FriendliAI AI Agent Responding to “Can you tell me my schedule for this week?” Using the 'authorizeCalendarAccess' and 'fetchCalendarEvents' Tool
What is function calling in LLMs?
Function calling in LLMs refers to the capability of the model to recognize when a user query requires a specific function call with what function arguments. For example, as shown in Figure 3, if a user asks, "Can you schedule a dinner date for this Saturday at 6 pm?", the LLM recognizes this as a request to add a new event to the Google Calendar. It further knows that it can complete these types of tasks using the createCalendarEvent
function with ‘Dinner Date’ as the event title.
Figure 3: FriendliAI AI Agent Responding to “Can you schedule a dinner date event for this Saturday at 6 pm?” Using the ‘createCalendarEvent’ Tool
The AI agent powered by this LLM brain takes this information to call the createCalendarEvent
function with the appropriate parameters. The result of the function call is a properly updated calendar, illustrated in Figure 4. Moreover, the result of the function call is informed back to the LLM brain which gives an adequate response.
Figure 4: Dinner Date Event Added to Google Calendar for Saturday, August 31, at 6:00 PM
This functionality also enables AI agents to perform complex tasks, such as searching for the best seafood restaurants near the Hudson River, as demonstrated in Figure 5, by interacting with external tools and APIs. Through function calling, AI agents extend their capabilities beyond simple conversation, allowing them to execute sophisticated tasks by leveraging these external resources.
Figure 5: FriendliAI AI Agent Responding to “Can you search for the best seafood restaurants near the Hudson River?” Using the ‘webSearch’ Tool
By understanding the concept of function calling in LLMs, you're already on the path to building powerful AI agents capable of executing complex tasks. If you're eager to apply this knowledge and create your own AI agent, our tutorial on building the calendar AI agent is the perfect place to start.
Function Calling AI Agents Tutorial Overview
List of Tools used for Web Search and Google Calendar Tools
Our AI agent uses the following four tools:
webSearch
authorizeCalendarAccess
fetchCalendarEvents
createCalendarEvent
webSearch Tool
- Function description: This tool is designed for searching on DuckDuckGo for the desired query.
- Function parameters:
query
: The query to search for. - Return value: The search results in a JSON format.
javascriptwebSearch: { description: 'This tool is designed for searching DuckDuckGo for the desired query.', parameters: z.object({ query: z.string().describe('The query to search for.'), }), execute: async ({ query }) => { try { const truncatedQuery = query.length > 500 ? query.substring(0, 500) : query; const searchResult = await search(truncatedQuery); return JSON.stringify({ message: `Here are the search results for "${query}".`, data: searchResult.noResults ? `No results found for "${query}".` : searchResult.results, }); } catch { return 'Search tool is not available at the moment.'; } }, },
authorizeCalendarAccess Tool
- Function description: This tool grants access to the user's calendar.
- Function parameters: None.
- Return value: “Successfully authorized access to your calendar.”
javascriptauthorizeCalendarAccess: { description: 'It must be called first before accessing any tools that allow you to control your personal calendar.', parameters: z.object({}), execute: async () => { isAuthorized = true; const auth = await authorize(); calendar = google.calendar({ version: 'v3', auth, }); return 'Successfully authorized access to your calendar.'; }, },
fetchCalendarEvents Tool
- Function description: This tool retrieves calendar events within a specified date range.
- Function parameters:
startDate
: Start date of the search range (format: yyyy-MM-dd).endDate
: End date of the search range (format: yyyy-MM-dd). - Return value: The searched events in a JSON format including each event’s summary, start date, and end date.
javascriptfetchCalendarEvents: { description: 'Retrieves calendar events within a specified date range.', parameters: z.object({ startDate: z.string().describe('Start date of the search range (format: yyyy-MM-dd)'), endDate: z.string().describe('End date of the search range (format: yyyy-MM-dd)'), }), execute: async ({ startDate, endDate }) => { const payload = { calendarId: 'primary', summary: 'Calendar Events', timeMin: new Date(`${startDate} 00:00`).toISOString(), timeMax: new Date(`${endDate} 23:59`).toISOString(), singleEvents: true, orderBy: 'startTime', }; try { const calendarRes = await calendar.events.list(payload); const events = calendarRes.data.items ?.map((item) => {
createCalendarEvent Tool
- Function description: This tool creates a new calendar event.
- Function parameters:
summary
: Title of the event to be added.startTime
: Date and time of the event, format should be 'yyyy-MM-dd HH:mm'.endTime
: Date and time of the event, format should be 'yyyy-MM-dd HH:mm'. - Return value: The data of the newly added calendar event in a JSON format.
javascriptcreateCalendarEvent: { description: 'Creates a new calendar event.', parameters: z.object({ summary: z.string().default('New Event').describe('Title of the event to be added'), startTime: z .string() .default(format(new Date(), 'yyyy-MM-dd HH:mm')) .describe("Date and time of the event, format should be 'yyyy-MM-dd HH:mm'"), endTime: z .string() .default(format(new Date(), 'yyyy-MM-dd HH:mm')) .describe("Date and time of the event, format should be 'yyyy-MM-dd HH:mm'"), }), execute: async ({ summary, startTime, endTime }) => { const payload = { calendarId: 'primary', requestBody: { summary, start: { dateTime: new Date(startTime).toISOString(),
Code Breakdown
Reading this section before diving into the full code is helpful because it provides a clear understanding of the main loop that contains the core source code. Learn the overall structure and functionality of the program before reading the detailed code in the Run the Full AI Agent Code section.
Here's a breakdown of how the main while loop operates:
- User Input Collection (line 43):
- The loop begins by waiting for input from the user through the
terminal.question("You: ")
method. This input serves as the prompt or query that the AI agent will respond to.
- Text Generation (lines 45-50):
- Once the input is received, the code calls the
streamText
function to generate a response. - The streamText function uses a model, specifically
meta-llama-3.1-70b-instruct
, with specific parameters liketemperature
,frequencyPenalty
, andmaxSteps
. These parameters control the creativity of the response, the likelihood of repeating phrases, and the maximum number of automatic roundtrips for tool calls, respectively. - The
prompt
key in the function call is set to the user's input, driving the model's response generation.
- System Prompting (lines 51):
- Before generating a response, the AI model is guided by this system prompt, which instructs its behavior.
- Tool Definitions (lines 52-183):
- A list of tools that are accessible and can be called by the model.
- The previously explained
webSearch
,authorizeCalendarAccess
,fetchCalendarEvents
, andcreateCalendarEvent
are included as the tools.
- Response Output (line 186):
- After generating the response using the
streamText
function and possibly invoking some of the tools, the loop ends by printing the generated response withprintResult(result);
.
Setup Instructions
Now that we are done with the theoretical part, let’s get our hands on the actual stuff. Follow these steps to set up your AI agent Node.js project:
- Prepare a Friendli Personal Access Token
A Friendli Personal Access Token is needed to authorize your account when sending inference requests through Friendli Serverless Endpoints.
- Sign up at Friendli Suite.
- Get a Personal Access Token (PAT).
- Copy the token.
- Set up Google Cloud Platform Credentials for the Google Calendar API
A credentials.json
file needs to be uploaded to the project directory to use the Google Calendar API.
- Create a project in the Google Cloud Console.
- Follow the steps in the Google Calendar API Python Quickstart to enable the Google Calendar API and download the credentials.json file.
- Rename the
credentials-xxxxx.json
file tocredentials.json
and upload it to the current working directory.
- Initialize the Node.js Project
npm init # Creates package.json file # Add "type": "module" to the package.json file
By default, Node.js treats JavaScript files as CommonJS modules. To use the modern JavaScript module system (using ‘import’ and ‘export’ statements), you need to add a "type": "module"
line to the package.json
file.
- Install the Dependencies
npm install zod ai @friendliai/ai-provider googleapis @google-cloud/local-auth duck-duck-scrape chalk date-fns # Creates package-lock.json file
The Final Example package.json
File:
{ "name": "calednar-cli", "version": "1.0.0", "type": "module", "scripts": { "start": "node main.js" }, "dependencies": { "@friendliai/ai-provider": "^0.1.16", "@google-cloud/local-auth": "^3.0.1", "ai": "^3.4.12", "chalk": "^5.3.0", "date-fns": "^4.1.0", "duck-duck-scrape": "^2.2.5", "googleapis": "^144.0.0", "zod": "^3.23.8" } }
- Configure Environment Variables
Export your Friendli Personal Access Token (PAT) as the FRIENDLI_TOKEN
environment variable. In your actual environment, make sure to fill in your own PAT as the environment variable.
export FRIENDLI_TOKEN="{YOUR PERSONAL ACCESS TOKEN e.g. flp_XXX}"
Run the Full AI Agent Code
Toggle the collapse button below and paste the following code to your main.js file, to run the code using the command:
node main.js
View the full 'main.js' code:
javascriptimport path from 'path'; import fs from 'fs/promises'; import process from 'process'; import * as readline from 'node:readline/promises'; // vercel ai sdk dependencies import { z } from 'zod'; import { streamText } from 'ai'; import { friendli } from '@friendliai/ai-provider'; // for calendar features import { google } from 'googleapis'; import { authenticate } from '@google-cloud/local-auth'; // for web search tool import { search } from 'duck-duck-scrape'; // utility dependencies import chalk from 'chalk'; import { format } from 'date-fns';
Final Thoughts
In this tutorial, we have been able to develop a simple AI agent for Google Calendar using the Vercel AI SDK and the Friendli Serverless Endpoints. The project can be easily deployed and operated within minutes with help from Vercel and FriendliAI. Furthermore, if you wish to use custom or fine-tuned generative AI models for your applications, you can also build your application using Friendli Dedicated Endpoints, which lets users upload their own models on the GPUs of their choice.
Congratulations on completing this tutorial. We hope that you found it informative and useful. We will soon come back with part 2 of this blog, which handles the UI and the visual parts of the application.
Happy coding!
Written by
FriendliAI Tech & Research
Share