Tired of endless email ping-pong for scheduling meetings? An AI agent can automate availability checks, propose slots, and book directly into your calendar. In this tutorial, you'll build a production-ready meeting scheduling agent using Python, LangChain, and Google Calendarâprogressing from basic setup to advanced multi-party handling.
Prerequisites#
Before diving in, ensure you have:
- Python 3.10+ installed.
- API credentials: Google Calendar API (enable in Google Cloud Console), OpenAI API key for the LLM.
- Basic familiarity with virtual environments (
venv) and pip installs. - Optional: Docker for deployment.
Install dependencies:
pip install langchain langchain-openai google-api-python-client google-auth-oauthlib google-auth-httplib2 crewai python-dotenv
Set up a .env file with OPENAI_API_KEY=your_key and Google OAuth credentials. Review our AI agent glossary for terms like "tools" and "reasoning loops." If new to LangChain, check LangChain agents tutorial.
Core Components of a Scheduling AI Agent#
A meeting scheduling agent operates in a ReAct loop: Reason about requests, Act via tools, Observe results, and repeat until resolution. Key components:
- LLM Brain: Uses models like GPT-4o for natural language understanding (e.g., parsing "Meet next Tuesday after 2pm").
- Tools: Custom functions for calendar queries, slot proposals, and bookings.
- Memory: Stores conversation history and preferences (e.g., timezones).
- Communicator: Handles input via email, Slack, or webhooks.
For autonomy, integrate frameworks like CrewAI for multi-agent orchestrationâe.g., one agent checks calendars, another negotiates.
Step-by-Step Implementation#
Step 1: Google Calendar Integration#
Authenticate and build core tools. Create calendar_tools.py:
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
import os
from datetime import datetime, timedelta
SCOPES = ['https://www.googleapis.com/auth/calendar']
def get_calendar_service():
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
if not creds or not creds.valid:
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token.json', 'w') as token:
token.write(creds.to_json())
return build('calendar', 'v3', credentials=creds)
def check_availability(service, start_time, duration_minutes=60):
end_time = start_time + timedelta(minutes=duration_minutes)
events = service.events().list(calendarId='primary',
timeMin=start_time.isoformat() + 'Z',
timeMax=end_time.isoformat() + 'Z',
singleEvents=True).execute()
return len(events.get('items', [])) == 0 # True if free
def book_meeting(service, summary, start_time, end_time):
event = {
'summary': summary,
'start': {'dateTime': start_time.isoformat() + 'Z'},
'end': {'dateTime': end_time.isoformat() + 'Z'},
}
return service.events().insert(calendarId='primary', body=event).execute()
This queries free slots and books events. See calendar integrations for Outlook alternatives.
Step 2: Define Agent Tools with LangChain#
Wrap tools in LangChain format (tools.py):
from langchain.tools import tool
from calendar_tools import get_calendar_service, check_availability, book_meeting
from datetime import datetime
service = get_calendar_service()
@tool
def find_free_slot(duration: int = 60, days_ahead: int = 7) -> str:
"""Find the next free slot within days_ahead."""
now = datetime.utcnow()
for hour in range(9, 18): # Business hours
candidate = datetime.combine(now.date() + timedelta(days=days_ahead),
datetime.min.time().replace(hour=hour))
if check_availability(service, candidate, duration):
return candidate.isoformat()
return "No slots found."
@tool
def schedule_meeting(summary: str, start_str: str) -> str:
"""Book a meeting at specific start time."""
start = datetime.fromisoformat(start_str)
end = start + timedelta(hours=1)
event = book_meeting(service, summary, start, end)
return f"Booked: {event.get('htmlLink')}"
Step 3: Build the Agent with LangChain#
Create the agent (agent.py):
from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain.prompts import ChatPromptTemplate
from langchain.memory import ConversationBufferMemory
from tools import find_free_slot, schedule_meeting
from dotenv import load_dotenv
load_dotenv()
llm = ChatOpenAI(model="gpt-4o", temperature=0)
tools = [find_free_slot, schedule_meeting]
prompt = ChatPromptTemplate.from_messages([
("system", """You are a scheduling assistant. Parse requests like "Schedule a 30min call with John next week."
Propose slots, confirm details (timezone UTC), handle conflicts by suggesting alternatives.
Always ask for confirmation before booking."""),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
agent = create_tool_calling_agent(llm, tools, prompt)
memory = ConversationBufferMemory(return_messages=True)
agent_executor = AgentExecutor(agent=agent, tools=tools, memory=memory, verbose=True)
# Run example
result = agent_executor.invoke({"input": "Schedule a meeting next Tuesday 3pm for 45 mins about AI agents."})
print(result['output'])
Run python agent.py to test. The agent reasons: parses date, finds slot, proposes/asks confirmation.
Step 4: Advanced Features#
- Multi-Party Scheduling: Add a tool to query multiple calendars via shared API access.
- Email/Slack Integration: Use
sendgridorslack-sdkfor input/output.
@tool
def check_multi_availability(emails: list, start_str: str) -> bool:
# Query each calendar, return True if all free
pass
- Voice Mode: Integrate AssemblyAI/LiveKit for real-time calls (use cases).
- Deployment: Wrap in FastAPI, deploy to Vercel. Use CrewAI for scaling:
from crewai import Agent, Task, Crew
scheduler = Agent(role='Scheduler', goal='Book meetings', tools=[find_free_slot, schedule_meeting], llm=llm)
task = Task(description='Handle: {user_request}', agent=scheduler)
crew = Crew(agents=[scheduler], tasks=[task])
result = crew.kickoff(inputs={'user_request': '...'})
Explore CrewAI comparisons for orchestration.
Step 5: Testing#
Simulate requests:
- "Free next week?" â Lists slots.
- Conflicts â "Slot taken, how about 4pm?"
Test edge cases: timezones (
pytzlib), long meetings.
Common Pitfalls and Best Practices#
Pitfalls:
- Rate Limits: Google API quotasâcache queries with Redis.
- Timezones: Always convert to UTC; use
dateutil.parser. - Privacy: Get consent for calendar access; anonymize logs.
- Hallucinations: Ground LLM with few-shot examples in prompts.
Best Practices:
- Use structured output (Pydantic/JSON mode) for dates.
- Add human-in-loop for high-stakes bookings.
- Monitor with LangSmith for debugging.
- Scale with vector stores for user preferences (tutorials).
- No-code pivot: Use MindStudio for prototypes.
Conclusion and Next Steps#
You've built a robust scheduling agent that saves hours weekly. Deploy it via webhook for email triggers. Next, explore autonomous agent use cases or build a sales agent. Fork the code on GitHub and iterateâshare your enhancements!