Skip to content
Technical Guides
Technical Guides15 min read2 views

Integrating AI Voice Agents with Google Calendar: Production Guide

How to build production-grade Google Calendar integration for AI voice agents — OAuth, real-time availability, conflict resolution.

The appointment problem

Roughly 60% of inbound calls to any service business end with "can I book an appointment?" If your AI voice agent cannot actually put an event on the right calendar, it is a very expensive answering machine. Google Calendar is the most common backend, and integrating it sounds simple — until you meet OAuth refresh tokens, shared calendars, timezone chaos, and the race condition where two agents try to book the same 10am slot.

This guide walks through a production Google Calendar integration for an AI voice agent, from OAuth setup to conflict-safe booking.

caller → agent
          │
          │ check_availability(provider_id, date)
          ▼
    Google Calendar API (freebusy)
          │
          │ book_appointment(provider_id, start, end)
          ▼
    Google Calendar API (events.insert with idempotency)
          │
          ▼
    Postgres (appointments mirror)

Architecture overview

┌──────────────────┐
│ Voice agent edge │
└────────┬─────────┘
         │ tool call
         ▼
┌──────────────────────────┐
│ /calendar service        │
│ • OAuth token store      │
│ • freebusy cache (60s)   │
│ • idempotent bookings    │
└────────┬─────────────────┘
         │
         ▼
┌──────────────────────────┐
│ Google Calendar API      │
└──────────────────────────┘

Prerequisites

  • A Google Cloud project with the Calendar API enabled.
  • OAuth 2.0 credentials and a consent screen (Internal if you control the workspace, External otherwise).
  • Refresh tokens stored encrypted in Postgres.
  • A table for mirroring booked appointments.

Step-by-step walkthrough

1. Get refresh tokens once, use forever

Walk the business owner through OAuth once during onboarding. Store the refresh token encrypted.

from google_auth_oauthlib.flow import Flow

flow = Flow.from_client_secrets_file(
    "credentials.json",
    scopes=["https://www.googleapis.com/auth/calendar.events"],
    redirect_uri="https://app.yourapp.com/oauth/google/callback",
)

@app.get("/oauth/google/start")
async def start():
    auth_url, _ = flow.authorization_url(access_type="offline", prompt="consent")
    return RedirectResponse(auth_url)

@app.get("/oauth/google/callback")
async def callback(code: str):
    flow.fetch_token(code=code)
    creds = flow.credentials
    await store_refresh_token(tenant_id, encrypt(creds.refresh_token))
    return {"ok": True}

2. Build a freebusy check with a short cache

Google's freebusy endpoint is the canonical source of truth, but calling it on every turn burns quota. Cache responses for 60 seconds per calendar.

import redis.asyncio as redis
from googleapiclient.discovery import build

r = redis.from_url("redis://cache:6379/0")

async def free_slots(calendar_id: str, day_iso: str) -> list[dict]:
    cache_key = f"fb:{calendar_id}:{day_iso}"
    cached = await r.get(cache_key)
    if cached:
        return json.loads(cached)
    service = build("calendar", "v3", credentials=load_creds(calendar_id))
    body = {
        "timeMin": f"{day_iso}T00:00:00Z",
        "timeMax": f"{day_iso}T23:59:59Z",
        "items": [{"id": calendar_id}],
    }
    resp = service.freebusy().query(body=body).execute()
    busy = resp["calendars"][calendar_id]["busy"]
    slots = compute_slots(busy)
    await r.set(cache_key, json.dumps(slots), ex=60)
    return slots

3. Book with an idempotency key

Every events.insert accepts a requestId that Google uses for idempotency. Pass a hash of (caller_id, start_time, provider_id).

import hashlib

def request_id(caller: str, start: str, provider: str) -> str:
    return hashlib.sha256(f"{caller}|{start}|{provider}".encode()).hexdigest()

async def book(calendar_id: str, start_iso: str, end_iso: str, caller: str, summary: str):
    service = build("calendar", "v3", credentials=load_creds(calendar_id))
    event = {
        "summary": summary,
        "start": {"dateTime": start_iso, "timeZone": "America/Los_Angeles"},
        "end": {"dateTime": end_iso, "timeZone": "America/Los_Angeles"},
    }
    return service.events().insert(
        calendarId=calendar_id,
        body=event,
        sendUpdates="all",
    ).execute()

4. Expose the tool to the voice agent

const tools = [
  {
    type: "function",
    name: "check_availability",
    description: "Return available 30-minute slots for a provider on a given date",
    parameters: {
      type: "object",
      properties: {
        provider_id: { type: "string" },
        date: { type: "string", description: "YYYY-MM-DD" },
      },
      required: ["provider_id", "date"],
    },
  },
  {
    type: "function",
    name: "book_appointment",
    description: "Book an appointment for a caller",
    parameters: {
      type: "object",
      properties: {
        provider_id: { type: "string" },
        start_iso: { type: "string" },
        end_iso: { type: "string" },
        caller_name: { type: "string" },
        reason: { type: "string" },
      },
      required: ["provider_id", "start_iso", "end_iso", "caller_name"],
    },
  },
];

5. Mirror to Postgres

Always write the booking to your own database so you can answer "what did we book today?" without hitting Google's API.

Production considerations

  • Timezones: always store UTC in your DB, but send RFC3339 with the calendar's display timezone to Google.
  • Rate limits: Google Calendar is 500 queries/100s/user by default. Use exponential backoff.
  • Conflicts: two callers can race. Re-check freebusy inside the booking transaction.
  • Refresh token expiry: if a user revokes consent, your refresh token is dead. Alert on 401s.
  • Shared calendars: delegate access via a service account with domain-wide delegation for workspace customers.

CallSphere's real implementation

CallSphere uses Google Calendar as one of the primary scheduling backends for its healthcare, salon, and real estate verticals. The voice agent runs on the OpenAI Realtime API with gpt-4o-realtime-preview-2025-06-03, PCM16 at 24kHz, and server VAD. Calendar tools live inside the 14-tool healthcare agent, the 4-tool salon agent, and the 10-agent real estate stack, all orchestrated through the OpenAI Agents SDK.

See AI Voice Agents Handle Real Calls

Book a free demo or calculate how much you can save with AI voice automation.

Bookings are mirrored to per-vertical Postgres databases, and a GPT-4o-mini post-call pipeline attaches the booked appointment to the call record so the business owner can audit every scheduling decision. Across 57+ languages and sub-second response times, the idempotency key pattern has eliminated double-booking on our production traffic.

Common pitfalls

  • Skipping the idempotency key: retries create duplicate events.
  • Caching freebusy too long: you book over real conflicts.
  • Storing tokens unencrypted: a breach becomes a calendar breach.
  • Ignoring the sendUpdates flag: callers do not get their confirmation email.
  • Confusing calendar ID with user email: they can differ for shared calendars.

FAQ

Do I need domain-wide delegation?

Only if you want to book on behalf of any user in a Google Workspace without each user granting consent.

How do I handle cancellations?

Expose a cancel_appointment tool that deletes the event by ID and updates your mirror.

Can I sync external changes back to the agent?

Yes — use Calendar push notifications (watch) to invalidate your cache on external edits.

What happens if the refresh token is revoked mid-call?

Catch the 401, fall back to "let me transfer you to someone who can book that manually", and alert ops.

Is Outlook/Microsoft 365 different?

Same architecture, different SDK. The patterns translate directly.

Next steps

Want to see Google Calendar scheduling working on a real voice agent? Book a demo, read the platform page, or explore pricing.

#CallSphere #GoogleCalendar #VoiceAI #Integration #OAuth #Scheduling #AIVoiceAgents

Share
C

Written by

CallSphere Team

Expert insights on AI voice agents and customer communication automation.

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.