(function() { var utmInheritingDomain = "appstore.com", utmRegExp = /(&|\?)utm_[A-Za-z]+=[A-Za-z0-9]+/gi, links = document.getElementsByTagName("a"), utms = [ "utm_medium={{URL - utm_medium}}", "utm_source={{URL - utm_source}}", "utm_campaign={{URL - utm_campaign}}" ]; for (var index = 0; index < links.length; index += 1) { var tempLink = links[index].href, tempParts; if (tempLink.indexOf(utmInheritingDomain) > 0) { tempLink = tempLink.replace(utmRegExp, ""); tempParts = tempLink.split("#"); if (tempParts[0].indexOf("?") < 0 ) { tempParts[0] += "?" + utms.join("&"); } else { tempParts[0] += "&" + utms.join("&"); } tempLink = tempParts.join("#"); } links[index].href = tempLink; } }());
  • August 29, 2024
  • 7 min read

Building an AI Agent for Google Calendar - Part 1/2

Building an AI Agent for Google Calendar - Part 1/2 thumbnail

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…

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:

  1. Can you tell me my schedule for this week?
  2. Can you schedule a dinner date event for this Saturday at 6 pm?
  3. 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.
javascript
webSearch: {
  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.”
javascript
authorizeCalendarAccess: {
  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.
javascript
fetchCalendarEvents: {
  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.
javascript
createCalendarEvent: {
  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.

Figure 6: Main While Loop in the AI Agent Code

Here's a breakdown of how the main while loop operates:

  1. 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.
  1. 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 like temperature, frequencyPenalty, and maxSteps. 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.
  1. System Prompting (lines 51):
  • Before generating a response, the AI model is guided by this system prompt, which instructs its behavior.
  1. 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, and createCalendarEvent are included as the tools.
  1. 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 with printResult(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:

  1. 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.

  1. 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 to credentials.json and upload it to the current working directory.
  1. 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.

  1. 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"
  }
}
  1. 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:

javascript
import 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 logo

FriendliAI Tech & Research


Share