When someone emails you asking for a meeting, your AI agent needs to check your calendar, propose available times, and create the event once confirmed. Here's how to architect this integration using n8n, Gmail API, Google Calendar API, and Google Gemini.
Architecture Overview
The workflow follows this data flow:
Gmail (new message) → AI Agent → Calendar API (check availability) → AI Agent (compose reply) → Gmail API (send reply) → Calendar API (create event)
Why this architecture? Gmail's trigger provides the entry point, but the AI agent needs tools to query your calendar and send responses. Rather than hardcoding logic, the agent orchestrates API calls dynamically based on email content.
Alternatives considered: Calendly-style booking pages work but lack context awareness. This AI approach reads natural language requests and adapts to different communication styles.
Gmail API Integration
Authentication: OAuth2 flow with Gmail API scope https://www.googleapis.com/auth/gmail.modify
Polling for new messages:
// Gmail Trigger polls every 60 seconds
GET https://gmail.googleapis.com/gmail/v1/users/me/messages?q=is:unread
Headers: { "Authorization": "Bearer <access_token>" }
Response structure:
{
"messages": [
{
"id": "18d4f2c8a9b3e7f1",
"threadId": "18d4f2c8a9b3e7f1"
}
]
}
Sending threaded replies:
POST https://gmail.googleapis.com/gmail/v1/users/me/messages/send
Headers: { "Authorization": "Bearer <access_token>" }
Body: {
"threadId": "18d4f2c8a9b3e7f1",
"raw": "<base64-encoded-email>"
}
Rate limits: 250 quota units per user per second. Each message send costs 100 units, so max 2.5 sends/second.
Error handling: 429 Too Many Requests requires exponential backoff. Invalid threadId returns 404 but message still sends (creates new thread).
Google Calendar API Integration
Authentication: OAuth2 with scope https://www.googleapis.com/auth/calendar
Fetching availability:
GET https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=2025-01-20T00:00:00Z&timeMax=2025-02-03T23:59:59Z
Headers: { "Authorization": "Bearer <access_token>" }
Response structure:
{
"items": [
{
"id": "event123",
"start": { "dateTime": "2025-01-22T14:00:00Z" },
"end": { "dateTime": "2025-01-22T15:00:00Z" },
"summary": "Existing meeting"
}
]
}
Creating events with Meet links:
POST https://www.googleapis.com/calendar/v3/calendars/primary/events?conferenceDataVersion=1
Headers: { "Authorization": "Bearer <access_token>" }
Body: {
"summary": "Meeting with John",
"start": { "dateTime": "2025-01-25T10:00:00Z" },
"end": { "dateTime": "2025-01-25T11:00:00Z" },
"attendees": [{"email": "john@example.com"}],
"conferenceData": {
"createRequest": { "requestId": "random-string-123" }
}
}
Gotcha: conferenceDataVersion=1 query parameter is required for Meet link generation. Without it, conferenceData is ignored.
Rate limits: 500 requests per 100 seconds per user. Calendar reads cost 1 unit, writes cost 10 units.
Google Gemini API Configuration
Authentication: API key from Google AI Studio
Model request format:
POST https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent
Headers: { "x-goog-api-key": "<api-key>" }
Body: {
"contents": [{
"role": "user",
"parts": [{ "text": "Check calendar and propose meeting times" }]
}],
"tools": [{
"function_declarations": [
{ "name": "get_calendar_events", "parameters": {...} },
{ "name": "send_email", "parameters": {...} }
]
}]
}
Response with tool calls:
{
"candidates": [{
"content": {
"parts": [{
"functionCall": {
"name": "get_calendar_events",
"args": { "timeMin": "2025-01-20", "timeMax": "2025-02-03" }
}
}]
}
}]
}
Cost: Gemini Flash charges $0.075 per 1M input tokens, $0.30 per 1M output tokens. Typical scheduling conversation: ~2,000 tokens total = $0.0006.
Implementation Gotchas
Missing email data: Gmail API sometimes returns messages without body content if they're still syncing. Add a 5-second delay after trigger fires.
Timezone handling: Calendar API returns times in UTC. Your AI agent prompt must specify your working hours in your local timezone:
"Working hours: 9:00-18:00 Europe/Paris. Convert all times to this timezone when proposing slots."
Duplicate event creation: If the agent receives the same meeting request twice (forwarded email, CC'd message), it might create duplicate events. Add a check for existing events with matching summary and attendee before creating.
AI hallucination on availability: The agent might propose times that appear free but ignore buffer time between meetings. Explicitly instruct: "Require 15-minute buffer before and after each event."
Email threading errors: When replying, if the original message's threadId is malformed, Gmail creates a new thread instead of replying inline. Always validate threadId format before using it.
Prerequisites
Required accounts:
- n8n instance (self-hosted or cloud)
- Google Cloud project with Gmail API and Calendar API enabled
- Google AI Studio account for Gemini API key
API credentials needed:
- Gmail OAuth2 client (client_id and client_secret from Google Cloud Console)
- Google Calendar OAuth2 (same credentials work for both)
- Gemini API key (from Google AI Studio)
Links to official docs:
Estimated costs:
- n8n Cloud: Free tier supports 5,000 workflow executions/month
- Gmail/Calendar API: Free (quota limits sufficient for personal use)
- Gemini API: ~$0.02 per 100 scheduling conversations
Get the Complete n8n Workflow Configuration
This tutorial covers the API integration architecture and key implementation patterns. For the complete n8n workflow file with all node configurations, AI agent system prompt, and a video walkthrough of the setup process, check out the full implementation guide.
Top comments (0)