Calendar
Calendar mirrors your Google Calendar into Subspace so agents can read your schedule and, with your approval, create events on it, while you keep using your native calendar app for everything else. Subspace doesn’t try to replace it, it adds a thin agenda view and an event-driven hook into the rest of the system.
Connecting
Section titled “Connecting”Calendar rides the same OAuth grant as Mail: /oauth/gmail/start requests
the calendar scope alongside Gmail’s, so connecting one account connects both. If an
existing grant predates the calendar scope, the account shows the same amber reconnect
banner Mail does; re-running the OAuth flow (always prompt=consent) mints a fresh
full-scope grant.
How sync works
Section titled “How sync works”Every 30 seconds, the calendar sync engine first mirrors your calendar directory into
comms.cal_calendars, then syncs each calendar using Google’s events.list syncToken
semantics:
- No stored sync token triggers a full listing.
- A stored token fetches only what changed since last time, an incremental delta.
- An expired token (Google returns 410 GONE) triggers a silent full resync that also purges any mirrored events the provider no longer lists.
Every changed event commits in one transaction: the comms.cal_events row upserts
(attendees as a JSON array of {email, name?, self?}, and any CRM page ids
already resolved for its attendees are preserved across the update rather than overwritten,
so a meeting page linked to an event survives the next sync). A cancelled event
(status: 'cancelled') deletes its mirror row.
Identity resolution
Section titled “Identity resolution”Attendees resolve to CRM pages through the same identity resolver mail and CRM auto-create use: an exact, case-insensitive email match first, falling back to a normalized-name match (lowercased, diacritics stripped, punctuation collapsed to spaces) against known CRM identities. An attendee that resolves gets a real page link in the agenda; one that doesn’t just shows as plain text.
Two-way: agents can create events
Section titled “Two-way: agents can create events”Calendar isn’t read-only. An agent (through a gated tool) can push a new event upstream
first, then commit the local mirror and its change-feed row in one transaction, returning
the new event’s id, provider id, and calendar. Google round-trips the write as
agent-created through extendedProperties.private, so both the provider and Subspace agree
on provenance. Gating happens at the tool layer, the write to Google itself carries no
approval prompt of its own; whatever policy governs the tool call governs the event.
The agenda page
Section titled “The agenda page”/p/calendar is deliberately thin: a this-week list (Monday through Sunday), grouped
by day, each row showing the time range, title, and calendar name.
- Attendee chips that resolved to a CRM page are
[[page]]links; clicking one navigates straight to that person’s page. - Events an agent created carry an agent-created chip.
- Any event with attendees gets a Record button. Clicking it calls the meeting-start flow and navigates you straight to the new meeting page.
There’s no month grid, by design, Subspace isn’t trying to be your calendar app, just a one-week-ahead surface agents and you can both act on.
Agent tools
Section titled “Agent tools”cal.events.list {from?, to?} is an ungated, read-only tool that lists synced events in a
date range (defaulting to the next 7 days, capped at 200 rows), returning {eventId, title, start, end, attendees, calendar} per event. It’s the read half of the calendar surface
agents reach for when reasoning about your schedule, for example before proposing a
meeting time or checking whether you’re free.