4 min read

The Executive Assistant (Calendar)

How to build an agent that can actually manage your time, finding free slots and booking meetings.

Dw

Dwizi Team

Editorial

The Executive Assistant (Calendar)

For decades, the ultimate promise of Artificial Intelligence has been the "Digital Executive Assistant."

We want an entity that knows our schedule better than we do. We want to say: "Book 30 minutes with Alice next week," and have it magically happen. We want it to handle the tedious back-and-forth emails of scheduling ("Are you free Tuesday?" "No, how about Wednesday?" "What time zone?").

But despite billions of dollars of investment, most of us still schedule meetings manually.

Why? Because giving an AI write access to your calendar is terrifying.

  • What if it deletes your Board Meeting?
  • What if it books a call at 3:00 AM because it messed up the time zone conversion?
  • What if it overwrites your anniversary dinner?

The cost of a mistake is high. It’s not just data loss; it’s social embarrassment.

The Problem: The High Stakes of Time

Calendars are surprisingly complex distributed databases. They handle recurring events, time zones, daylight savings, tentative statuses, and permissions.

A "naive" agent that just tries to write to the API will fail. It will double-book you. It will annoy your colleagues.

The Solution: Read-Heavy, Write-Careful

To build a safe Calendar Agent, we need to separate Reading (which is safe) from Writing (which is risky).

We will build two tools:

  1. get_availability: A robust, read-only tool that analyzes your schedule and returns "white space."
  2. book_meeting: A high-friction tool that performs the actual insert.

The Implementation

We will use the Google Calendar API. Note the use of Time Windows to keep the data manageable.

/**
 * Finds free time slots in the user's calendar.
 * 
 * Description for LLM: "Check the calendar for existing events before scheduling anything. Returns a list of busy slots."
 */

type Input = {
  day: string; // ISO Date "2024-05-20"
  timezone: string; // "America/New_York"
};

export default async function checkAvailability(args: Input) {
  const token = Deno.env.get("GOOGLE_CALENDAR_TOKEN");
  if (!token) throw new Error("Missing Calendar Token");

  // 1. Time Math
  // We strictly define the window: Start of day to End of day in the USER'S timezone.
  // This prevents the "3 AM" bug.
  const startOfDay = new Date(args.day);
  const endOfDay = new Date(startOfDay.getTime() + 86400000); // +24 hours

  const url = `https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=${startOfDay.toISOString()}&timeMax=${endOfDay.toISOString()}&singleEvents=true`;
  
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${token}` }
  });
  
  const data = await res.json();
  
  // 2. The Abstraction
  // We don't return the full JSON blob from Google. It's too noisy.
  // We return a simplified view of "Busy-ness".
  // This helps the LLM focus on the gaps.
  const busySlots = data.items.map((event: any) => ({
    start: event.start.dateTime,
    end: event.end.dateTime,
    title: event.summary, // Context helps ("Lunch" is movable, "Board Meeting" is not)
    status: event.status // "confirmed" vs "tentative"
  }));

  return {
    date: args.day,
    timezone: args.timezone,
    busySlots
  };
}

The Execution Story

User: "Find time for a 30-min sync with the design team next Tuesday afternoon."

Agent Action:

  1. Parse: The Agent identifies "next Tuesday" as Feb 13th. It identifies "afternoon" as 12pm - 5pm.
  2. Read: It calls check_availability({ day: "2024-02-13", timezone: "America/Los_Angeles" }).
  3. Analyze: The tool returns:
    • 12:00 - 1:00: Lunch
    • 1:00 - 2:00: Busy
    • 3:30 - 4:00: Quick Sync
  4. Reason: The Agent looks at the gaps.
    • 2:00 - 3:30 is free.
    • 4:00 - 5:00 is free.
  5. Propose: "I found a few slots on Tuesday afternoon: 2:00 PM or 4:00 PM. Which do you prefer?"

Notice that the Agent did not book anything yet. It acted as an analyst.

User: "Let's do 2:00 PM."

Agent Action: Now, and only now, does it call the book_meeting tool.

The Takeaway

By splitting the task into "Analyze" and "Act," we reduce the risk of hallucination. The Agent has to "show its work" (by proposing times) before it commits to the database. This pattern—Analyze -> Propose -> Confirm -> Execute—is the secret to building trust with AI.

Subscribe to Dwizi Blog

Get stories on the future of work, autonomous agents, and the infrastructure that powers them. No fluff.

We respect your inbox. Unsubscribe at any time.

Read Next

The Junior Dev (GitHub)

Automating the first 15 minutes of every bug report. How to build an agent that triages issues.

Read article