# How Omi's Calendar Meeting Integration Syncs and Parses Meetings

> Discover how Omi's calendar meeting integration syncs Google Calendar events using LangChain. Learn how it fetches, normalizes, and performs operations on your meetings.

- Repository: [omi/omi](https://github.com/basedhardware/omi)
- Tags: how-to-guide
- Published: 2026-02-26

---

**Omi's calendar meeting integration uses LangChain-based tools to authenticate with Google Calendar, fetch events with intelligent date windowing, normalize them into human-readable formats, and execute create-update-delete operations while automatically resolving contact names to email addresses.**

The `basedhardware/omi` repository implements a robust calendar meeting integration that connects to Google Calendar through OAuth-enabled LangChain tools. This system handles everything from token refresh logic to parsing complex date ranges and storing structured meeting context in Firestore for efficient retrieval.

## Authentication and Token Management

Before any calendar operation executes, the `prepare_access` function in [`backend/utils/retrieval/tools/integration_base.py`](https://github.com/basedhardware/omi/blob/main/backend/utils/retrieval/tools/integration_base.py) validates the user's Google Calendar connection and retrieves a fresh OAuth access token. If the stored token has expired, the system automatically invokes `refresh_google_token` to obtain a new credential without user intervention.

This authentication layer ensures that all subsequent API calls to Google Calendar operate with valid, non-expired tokens. The integration gracefully handles 401 errors by retrying requests after token refresh, particularly within the update and delete tool implementations.

## Fetching and Parsing Calendar Events

The primary entry point for retrieving meetings is `get_calendar_events_tool` defined in [`backend/utils/retrieval/tools/calendar_tools.py`](https://github.com/basedhardware/omi/blob/main/backend/utils/retrieval/tools/calendar_tools.py). When a user asks "What's on my calendar?", this tool orchestrates the request to Google's API with the following logic:

- **Date Parsing**: The tool accepts optional ISO-8601 `start_date` and `end_date` strings, normalizing them with `parse_iso_with_tz` to handle timezone-aware timestamps correctly.
- **Parameter Building**: It constructs the API request using `timeMin`, `timeMax`, `orderBy`, and `singleEvents` parameters, capping `max_results` at 50 events per request.
- **Server-Side Filtering**: When a `search_query` parameter is provided, the tool adds the `q` parameter to filter events directly through Google's API rather than client-side.

For large date ranges exceeding 30 days, the integration implements an **iterative windowed search** that walks backwards month-by-month (maximum 6 months) and merges results, prioritizing the most recent events. This prevents API timeouts while ensuring comprehensive coverage.

The raw event objects returned by Google are normalized into a human-readable string format through a processing loop (lines 81-120) that extracts the title, start/end times (converted from ISO to local time), location, and a truncated description.

```python
from backend.utils.retrieval.tools.calendar_tools import get_calendar_events_tool

result = get_calendar_events_tool(
    start_date=None,          # defaults to now

    end_date=None,            # defaults to now + 7 days

    max_results=5,
    search_query=None,
)
print(result)

```

## Creating, Updating, and Deleting Events

The integration provides full CRUD capabilities through dedicated LangChain tools that handle complex data transformation and error recovery.

### Creating Meetings with Contact Resolution

`create_calendar_event_tool` receives meeting details including title, start/end ISO strings, optional description, location, and a comma-separated `attendees` list. The critical `resolve_attendee_to_email` function (lines 56-73) processes attendee strings by first checking for an "@" symbol to identify raw emails, otherwise searching Google Contacts via `search_google_contacts` from [`backend/utils/retrieval/tools/google_utils.py`](https://github.com/basedhardware/omi/blob/main/backend/utils/retrieval/tools/google_utils.py). If a name cannot be resolved, the tool returns an explicit error prompting for a valid email address.

The event payload is constructed in RFC-3339 UTC format through `create_google_calendar_event`, posted to the Calendar API, and returns a confirmation containing the `htmlLink` to the newly created event.

```python
from backend.utils.retrieval.tools.calendar_tools import create_calendar_event_tool

result = create_calendar_event_tool(
    title="Project Sync",
    start_time="2024-05-15T10:00:00-07:00",
    end_time="2024-05-15T11:00:00-07:00",
    description="Weekly project status update.",
    location="Zoom",
    attendees="alice@example.com, Bob Smith, carol@example.com",
)
print(result)

```

### Modifying Existing Events

`update_calendar_event_tool` and `delete_calendar_event_tool` follow a similar pattern: they locate the target event either by a known `event_id` or by searching with `event_title` combined with a date range, then issue PATCH or DELETE requests respectively. Both tools implement automatic retry logic with refreshed tokens upon encountering 401 authentication errors.

```python
from backend.utils.retrieval.tools.calendar_tools import update_calendar_event_tool

result = update_calendar_event_tool(
    event_title="Project Sync",
    start_date="2024-05-15T00:00:00-07:00",
    end_date="2024-05-16T00:00:00-07:00",
    location="Google Meet",
)
print(result)

```

```python
from backend.utils.retrieval.tools.calendar_tools import delete_calendar_event_tool

result = delete_calendar_event_tool(
    event_title="Lunch with Alex",
    start_date="2024-05-20T00:00:00-07:00",
    end_date="2024-05-20T23:59:59-07:00",
)
print(result)

```

## Internal Meeting Storage Architecture

When meetings are created via the UI or external synchronization, the REST endpoint `POST /v1/calendar/meetings` defined in [`backend/routers/calendar_meetings.py`](https://github.com/basedhardware/omi/blob/main/backend/routers/calendar_meetings.py) persists a structured `CalendarMeetingContext` document to Firestore. This internal storage decouples Omi from repeated Google API calls and enables enrichment with Omi-specific metadata.

The stored payload includes the external calendar event ID, source identifier (`google_calendar`, `macos_calendar`, or `outlook_calendar`), title, participants, platform details, links, start time, calculated duration, and optional notes. This architecture supports transcription ID linking and maintains a local cache of calendar state for fast retrieval.

## Summary

- **Token Management**: The `prepare_access` and `refresh_google_token` functions in [`integration_base.py`](https://github.com/basedhardware/omi/blob/main/integration_base.py) ensure valid OAuth credentials before every Google Calendar API interaction.
- **Intelligent Fetching**: `get_calendar_events_tool` implements windowed searching for ranges exceeding 30 days and normalizes raw API responses into readable formats.
- **Contact Resolution**: The `resolve_attendee_to_email` helper bridges natural language names to email addresses via Google Contacts integration.
- **CRUD Operations**: Create, update, and delete tools handle RFC-3339 formatting, attendee validation, and automatic retry on authentication failures.
- **Persistent Storage**: The [`calendar_meetings.py`](https://github.com/basedhardware/omi/blob/main/calendar_meetings.py) router stores `CalendarMeetingContext` objects in Firestore, caching calendar data with Omi-specific metadata to reduce API dependency.

## Frequently Asked Questions

### How does Omi handle expired Google Calendar tokens?

When the `prepare_access` function detects an expired token, it automatically calls `refresh_google_token` to obtain new credentials before executing the requested calendar operation. Additionally, both `update_calendar_event_tool` and `delete_calendar_event_tool` implement retry logic that refreshes tokens and retries the request upon receiving a 401 error from Google's API.

### Can Omi resolve contact names to email addresses when creating meetings?

Yes. The `create_calendar_event_tool` uses `resolve_attendee_to_email` to process attendee strings. If a string contains an "@" symbol, it treats it as an email address; otherwise, it searches Google Contacts via `search_google_contacts` in [`google_utils.py`](https://github.com/basedhardware/omi/blob/main/google_utils.py) to find matching email addresses. If resolution fails, the tool returns an error requesting valid emails.

### What happens when requesting calendar events for date ranges longer than 30 days?

For ranges exceeding 30 days, `get_calendar_events_tool` activates an iterative windowed search mechanism that walks backwards month-by-month (capped at 6 months), executes multiple API calls, and merges the results while keeping the most recent events. This approach prevents API timeouts while ensuring comprehensive event retrieval.

### How are calendar meetings stored internally in Omi?

The `POST /v1/calendar/meetings` endpoint in [`backend/routers/calendar_meetings.py`](https://github.com/basedhardware/omi/blob/main/backend/routers/calendar_meetings.py) stores meetings as `CalendarMeetingContext` documents in Firestore. These records contain external event IDs, source calendar types (Google, macOS, Outlook), participant lists, platform links, timing information, and calculated duration, enabling Omi to reference meetings without repeated API calls.