Calendar Integrations — one scheduling contract over two hostile APIs
Second calendar vendor shipped without changing a single AI tool call site
Two calendar APIs. One of them has no free/busy endpoint. Both have to look identical to an LLM holding a tool.
The problem
The trainer product promises that your growth plan lands on your calendar as scheduled sessions. For that to be true, the AI needs to read real availability across a whole team and write real recurring events — against whichever vendor the customer's organisation runs.
The approach
- Extract before extending. Google Calendar calls were inlined in a 5,000-line module. Before adding a second vendor I pulled them into service classes behind a single dispatch point, so every scheduling tool became provider-blind. The entire Microsoft stack then landed without touching a single AI tool call site.
- One recurrence contract. An RFC 5545 RRULE builder with real validation is the only recurrence representation in the system. Graph doesn't speak RRULE, so a translation layer maps frequency, interval, weekday codes with ordinal prefixes stripped, count and until into its patterned-recurrence object model.
- Rebuilding free/busy where none exists. Microsoft Graph has no equivalent of Google's free/busy endpoint. It returns an availability string — one character per interval per user. So the service merges N users' strings character-wise and walks the merged view to reconstruct concrete busy blocks for the slot finder.
- Tokens encrypted, not just signed. OAuth refresh tokens were stored with Django's signer, which is tamper-evident but perfectly readable at rest. Moved every provider to Fernet encryption in one pass.
- The edge cases are all identity. Guest and personal-account UPNs (
alice_outlook.com#EXT#@tenant,live.com#alice@…) silently corrupt invite lists, so they're rejected with a test per shape. Connected-calendar aliases became first-class, so free/busy and attendees use the address the calendar actually knows rather than the platform login.
Stack
Django · Google Calendar API · Microsoft Graph · MSAL · azure-identity · OAuth 2.0 · Fernet · LangChain · React · TypeScript
Outcomes
- Two calendar vendors behind one interface, with dual-provider test coverage over the error paths — no integration, unparseable datetimes, inverted ranges, past starts, invalid recurrence bounds — not just the happy path.
- Fixed the Microsoft tenant-wide admin-consent redirect, which arrives with no authorization code and had been rendering "Connection Failed" to admins who had just successfully approved the app for their whole organisation.
What I learned
- Refactor first, integrate second. The temptation is to add the new vendor alongside and clean up after. Extracting the dispatch point before writing any Microsoft code is why the second integration changed zero call sites.
- Reverse your own design when review is right. I shipped a both-vendors-at-once mode and a per-user preference, then removed both a week later when the product argument — one vendor per organisation — turned out to be correct. I also replaced a disconnect that called Graph's revoke-sessions endpoint after a reviewer pointed out it would sign the user out of Outlook and Teams too.
- Third-party APIs fail in ways docs don't cover. Reserved scopes that raise if you pass them explicitly, consent redirects with no code, synthetic UPNs — none of it appears until real tenants hit it.
Hiring for something like this?
Tell me what you're building