calendar.api.ready — Seed Plan
Concept
Root capability gate: "Can this agent access a calendar?" Provider-agnostic where possible, but must encode real expert knowledge about the three major calendar ecosystems.
The Three Ecosystems
1. Google Calendar API (REST)
- Auth: OAuth 2.0 with project in Google API Console
- Minimal read scope:
calendar.events.readonly(view events on all calendars) - Broader read scope:
calendar.readonly(see + download any accessible calendar) - Verification call:
GET /calendar/v3/users/me/calendarList(lists subscribed calendars — confirms auth + identity in one call) - Common failures:
- Token expired (OAuth tokens expire in ~1hr)
- Insufficient scope (readonly vs readwrite)
- Calendar API not enabled in GCP project (403 with "Calendar API has not been used in project")
- App not verified (OAuth consent screen blocks)
- Refresh token revoked by user
2. Microsoft Graph (REST)
- Auth: OAuth 2.0 via Azure AD / Microsoft identity platform
- Minimal read scope:
Calendars.Read(delegated — read user calendars) - Application scope:
Calendars.Read(app-only — reads all calendars in tenant, requires admin consent) - Verification call:
GET /me/calendarsorGET /me/calendarView?startDateTime=...&endDateTime=... - Common failures:
- Token expired (1hr default)
- Missing admin consent for application permissions
- Tenant restrictions / conditional access policies blocking
- User has no Exchange Online mailbox (Graph calendar requires it)
- Multi-tenant app not consented in target tenant
3. CalDAV (Protocol)
- Auth: HTTP Basic (over TLS), OAuth 2.0 (Google CalDAV), or client certificates
- Discovery:
PROPFIND /.well-known/caldav→ redirect →PROPFINDforcurrent-user-principal→PROPFINDforcalendar-home-set - Verification:
PROPFINDon context path withDepth: 0, requestingcurrent-user-principal— confirms auth and returns principal URL - Common failures:
- Wrong context path (varies per server:
/dav/,/remote.php/dav/for Nextcloud, etc.) - TLS certificate issues (self-signed for self-hosted)
- Basic auth disabled (Google requires OAuth for CalDAV)
- Server doesn't advertise
calendar-accessin DAV header - DNS SRV record missing (
_caldavs._tcp)
- Wrong context path (varies per server:
Minimal Verification Strategy
The seed should instruct: list calendars, not events.
Listing calendars is:
- Cheaper than listing events (no time-range query needed)
- Confirms auth + identity + access level in one call
- Provider-agnostic concept: every calendar system supports "what calendars do I have?"
- Returns useful metadata for downstream seeds (calendar IDs, names, access roles)
This differs from "list next event" — which requires knowing which calendar to query and involves time-range logic. Too much for a capability gate.
How It Differs From gmail.api.ready
| Dimension | gmail.api.ready | calendar.api.ready |
|---|---|---|
| Providers | Google-only | Google, Microsoft, CalDAV (provider-agnostic) |
| Auth patterns | OAuth2 with Gmail scopes | OAuth2 (Google/MSFT) or HTTP Basic (CalDAV) |
| Verification | users.getProfile |
List calendars (provider-appropriate) |
| Identity signal | Email address | Calendar list + default calendar |
| Scope taxonomy | Simple (readonly → modify → compose) | Granular (events.readonly vs calendar.readonly vs full) |
| Discovery | None (single endpoint) | Required for CalDAV (well-known URI, SRV records) |
| Failure modes | Token/scope/API-not-enabled | All of gmail's + CalDAV discovery + missing Exchange mailbox |
Key structural difference: gmail.api.ready is single-provider. calendar.api.ready must be multi-provider OR we split into three seeds.
Design Decision Needed
Option A: Single provider-agnostic root
- One seed covers all three ecosystems
- Prompt instructs: detect which provider, then verify accordingly
- Pro: simpler graph, one capability gate
- Con: long prompt (~1800 chars), mixes three different auth flows
Option B: Three provider-specific roots
calendar.google.ready,calendar.graph.ready,calendar.caldav.ready- Each encodes deep knowledge of its ecosystem
- Pro: each seed is focused, expert-dense, within char limit
- Con: three roots for one capability, agent must know which to pick
Option C: One root + three children
calendar.api.ready(root): detect provider, route- Children:
calendar.google.verify,calendar.graph.verify,calendar.caldav.verify - Pro: natural tree structure, root is lightweight dispatcher
- Con: root seed does minimal work, children do the real verification
Recommendation: Option A — single root. The prompt can be structured as: identify your provider → follow the appropriate verification path → report results in a standard format. This mirrors how gmail.api.ready works (single, complete, self-contained) and keeps the graph clean. The 2048 char limit accommodates it.
Contract (Draft)
"a calendar api connectivity report exists listing accessible calendars with their identifiers and access levels, or a specific failure diagnosis identifying the provider and auth mechanism"
Suggested Slug
calendar.api.ready — mirrors gmail.api.ready, three independent axes (calendar = domain, api = interface, ready = state)
Open Questions
- Should the seed instruct caching calendar IDs for downstream use (like gmail caches the email)?
- Should it explicitly name CLI tools (gcalcli, caldav-cli) or stay tool-agnostic?
- Does the prompt need to handle the case where the agent has access to multiple calendar providers simultaneously?