docspluginsextensionscalendar

calendar

CalDAV calendar access as a capability — list and inspect events, create, update, or delete them through an approval ladder, with an append-only audit trail. Works with Google, iCloud, Fastmail, and Nextcloud.

What the agent can do

  • Read — list events in a time range, and fetch one by id.
  • Write — create, update, and delete events, gated by write_mode.
  • Audit — every write is appended to a changelog the agent can review, with before/after snapshots.

Connecting a calendar

Two paths, depending on the provider. Google uses OAuth; everything else uses CalDAV with an app-specific password.

  1. Create a Google Cloud project with the Calendar API enabled.
  2. Create an OAuth 2.0 Web-application client; register the redirect URI the admin shows you.
  3. Paste the Client ID and Secret into the admin, then run the consent flow.
  4. The flow writes the refresh token and account email into secrets.json for you.

secrets.json

json · config/ext/calendar/
{
  "PROVIDER": "google",
  "GOOGLE_CLIENT_ID": "...",
  "GOOGLE_CLIENT_SECRET": "...",
  "GOOGLE_REFRESH_TOKEN": "...",
  "GOOGLE_EMAIL": "you@gmail.com"
}
⚠ HEADS UP
Publish the OAuth consent screen. While it's in Testing mode Google expires the refresh token after 7 days.

Configuration

capabilities.json

json · extensions.calendar slice
{
  "extensions": {
    "calendar": {
      "enabled": true,
      "write_mode": "approval",
      "calendars": ["Work"]
    }
  }
}
FieldTypeDefaultEffect
write_modedisabled | approval | personal | fulldisabledApproval ladder for create / update / delete. Reads never prompt.
calendarsstring[][]Calendar display names to operate on, resolved over CalDAV.
calendar_urlsstring[][]Pre-resolved CalDAV URLs — required for Google, and takes priority over names.

The read window is set by view_past (default 30d) and view_future (default 365d), as durations like 7d or 3m.

The write ladder has four rungs:

ModeBehavior
disabledWrite tools aren't registered — read-only.
approvalEvery write prompts for approval.
personalPersonal writes run without prompting; writes with attendees still prompt, since attendees trigger real invitations.
fullAll writes run without prompting.

Tools

calendar__list(after?, before?)

List calendar events in a time range, sorted by start time.

Parameters

  • optional after[ISO date]Only events after this timestamp.
  • optional before[ISO date]Only events before this timestamp.

Returns

UID: UID
Title: TITLE
Time: START — END
Location: LOCATION
Description: DESCRIPTION
Attendees: EMAIL, EMAIL, …
Recurrence: RECURRENCE
Status: STATUS
when one block per event, separated by blank lines
No events found.
when empty range
Calendar error: ERROR
when connection or config error

calendar__get(uid)

Retrieve a single calendar event by UID with full details.

Parameters

  • uid[string]Event UID.

Returns

UID: UID
Title: TITLE
Time: START — END
…
when event found (same format as calendar__list)
Event not found.
when uid not matched
Calendar error: ERROR
when connection error

calendar__changes(limit?)

List recent calendar changes (create, update, delete) from the audit log.

Parameters

  • optional limit[integer, default 50]Max entries to return.

Returns

[ISO_TIMESTAMP] CREATE — UID
  After: TITLE (START)
[ISO_TIMESTAMP] UPDATE — UID
  Before: TITLE (START)
  After: TITLE (START)
when audit entries present
No changes recorded.
when empty log
Calendar error: ERROR
when file read error

calendar__create(title, start, end, allDay?, location?, description?, attendees?)

Create a calendar event. Approval/auto-execution depends on write_mode.

Parameters

  • title[string]Event title.
  • start[ISO datetime or YYYY-MM-DD]Start time. Use date-only for all-day events.
  • end[ISO datetime or YYYY-MM-DD]End time. Use date-only for all-day events.
  • optional allDay[boolean, default false]Mark as an all-day event.
  • optional location[string]Event location.
  • optional description[string]Event description.
  • optional attendees[string[]]Attendee email addresses. In personal mode, presence of attendees forces an approval prompt.

Returns

Created: TITLE (START — END)
UID: UID
when success
Missing required arguments: title, start, end
when incomplete input
Calendar error: ERROR
when writes disabled, no calendar, or server error

calendar__update(uid, title?, start?, end?, allDay?, location?, description?, attendees?)

Update a calendar event by UID. Only specified fields are changed.

Parameters

  • uid[string]Event UID.
  • optional title[string]New title.
  • optional start[ISO datetime or YYYY-MM-DD]New start.
  • optional end[ISO datetime or YYYY-MM-DD]New end.
  • optional allDay[boolean]Mark as all-day.
  • optional location[string]New location.
  • optional description[string]New description.
  • optional attendees[string[]]Replaces the existing attendee list.

Returns

Updated: TITLE (START — END)
when success
Missing required argument: uid
when uid absent
Calendar error: ERROR
when event not found, writes disabled, or server error

calendar__delete(uid)

Delete a calendar event by UID.

Parameters

  • uid[string]Event UID.

Returns

Deleted event: UID
when success
Missing required argument: uid
when uid absent
Calendar error: ERROR
when event not found, writes disabled, or server error

Notes & gotchas

🔒 SECURITY
Start write_mode at disabled and step up to approval when the agent is actively scheduling. Reserve personal and full for when you mean it — full sends meeting invitations without asking.