Calendar

For Coding Agents

calendar.md

AGNT Calendar

Why AGNT Calendar

Agents that schedule meetings need to understand calendars. Not just "is this slot free" — the full picture. Which calendars are active, what events exist, what the user's working hours are, and how all of that combines into a real-time availability timeline.

AGNT Calendar syncs from Google and Microsoft, normalizes everything into a unified model, and computes availability timelines that account for working hours, buffers, all-day events, and multi-calendar conflicts. Your agent asks "when is this person free?" and gets a structured answer. No iCal parsing. No timezone math. No polling.

Quick Start

1. Sync Calendars from an OAuth Provider

After a user grants OAuth access through an identifier, sync their calendars:

bash
curl -X POST https://api.agnt.ai/identifiers/idn_abc123/calendars/sync \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "platform": "google" }'
json
{
  "ok": true,
  "calendars": [
    {
      "id": "cal_def456",
      "platform": "google",
      "name": "jane@acme.co",
      "timezone": "America/Los_Angeles",
      "isPrimary": true,
      "role": "owner",
      "eventCount": 0,
      "lastSyncedAt": null
    },
    {
      "id": "cal_ghi789",
      "platform": "google",
      "name": "Acme Team Calendar",
      "timezone": "America/Los_Angeles",
      "isPrimary": false,
      "role": "reader",
      "eventCount": 0,
      "lastSyncedAt": null
    }
  ]
}

2. Sync Events

bash
curl -X POST https://api.agnt.ai/calendars/cal_def456/sync-events \
  -H "Authorization: Bearer $TOKEN"
json
{
  "ok": true,
  "calendar": {
    "id": "cal_def456",
    "eventCount": 47,
    "lastSyncedAt": "2026-03-01T12:05:00.000Z"
  }
}

3. Get Availability Timeline

bash
curl https://api.agnt.ai/identifiers/idn_abc123/timeline \
  -H "Authorization: Bearer $TOKEN"

The timeline tells you exactly when a person is free or busy, broken down by day and time slot.

Core Concepts

Architecture

The calendar system follows a clear chain:

Identifier -- An identifier (like an email address) connects to OAuth providers. When a user grants Google or Microsoft access, the identifier's platforms.google.accessGranted or platforms.azure.accessGranted flag is set to true.

Sync -- Calling sync-resources on an identifier pulls calendar metadata from all connected providers. This creates Calendar records in AGNT.

Calendar -- A normalized representation of a calendar from any provider. Linked to the identifier via a UserCalendar join table. Contains metadata like timezone, role, and sync status.

Events -- Calling sync-events on a calendar pulls the actual event data. Events are stored locally and used to compute availability.

Timeline -- The computed output. Takes all calendars for an identifier, layers in working hours and buffer preferences, and produces a structured availability timeline.

Timelines

The timeline is the main output your agent cares about. It's structured as:

blockSets (one per day)
  > blocks (time slots within the day)
    > entries (availability status per identifier)

Each entry has a status and a type:

StatusMeaning
freeAvailable for scheduling
busyNot available
TypeMeaning
working_hoursWithin defined working hours, no conflicts
eventA calendar event occupies this slot
all_day_eventAn all-day event covers this slot
outside_working_hoursOutside the user's defined working hours
bufferBuffer time before or after an event

A single time slot can have multiple entries if the user has multiple calendars. Your agent should treat the slot as busy if any entry is busy.

Platforms

AGNT supports two calendar providers:

  • Google (google) -- Google Calendar via Google OAuth
  • Microsoft (azure) -- Outlook/Microsoft 365 via Microsoft OAuth

Both are normalized into the same Calendar and Event models. Your agent doesn't need to care which provider a calendar comes from.

Sync Strategy

Calendar sync is pull-based. You trigger it, AGNT fetches the latest from the provider. There's no webhook-based real-time sync (yet). For scheduling agents, trigger a sync before computing availability to ensure fresh data.

Sync resources (calendar list) and sync events (event data) are separate operations. Sync resources first to discover calendars, then sync events on the calendars you care about.

API Reference

Endpoints

MethodPathDescriptionAuth
GET/calendarsList all calendars for authenticated userDelegated
GET/calendars/:calendarIdGet calendar detailsDelegated
GET/calendars/:calendarId/eventsList events for a calendarDelegated
POST/calendars/:calendarId/sync-eventsTrigger event sync for a calendarDelegated
GET/identifiers/:identifierId/calendarsList calendars for an identifierDelegated
POST/identifiers/:identifierId/calendars/syncSync calendars from an OAuth providerDelegated
POST/identifiers/:identifierId/sync-resourcesSync calendars + contacts from all providersDelegated
GET/identifiers/:identifierId/timelineGet availability timelineDelegated

Calendar Object

json
{
  "id": "cal_def456",
  "account": "acc_ghi789",
  "platform": "google",
  "name": "jane@acme.co",
  "timezone": "America/Los_Angeles",
  "referenceId": "jane@acme.co",
  "backgroundColor": "#4285f4",
  "conferenceSolutions": ["hangoutsMeet"],
  "lastSyncedAt": "2026-03-01T12:05:00.000Z",
  "syncError": null,
  "eventCount": 47,
  "role": "owner",
  "isPrimary": true,
  "userIdentifier": "idn_abc123",
  "createdAt": "2026-03-01T12:00:00.000Z",
  "updatedAt": "2026-03-01T12:05:00.000Z"
}
FieldTypeDescription
idstringUnique calendar ID
accountstringAccount ID
platformstringProvider: google or azure
namestringCalendar display name
timezonestringIANA timezone
referenceIdstringProvider-side calendar ID
backgroundColorstringCalendar color from the provider
conferenceSolutionsstring[]Available video conferencing options
lastSyncedAtstring | nullLast successful event sync timestamp
syncErrorstring | nullLast sync error message, if any
eventCountnumberNumber of synced events
rolestringUser's role: owner, writer, or reader
isPrimarybooleanWhether this is the primary calendar
userIdentifierstringIdentifier ID this calendar belongs to
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last update timestamp

Timeline Object

json
{
  "ok": true,
  "timeline": {
    "blockSets": [
      {
        "date": "2026-03-01",
        "blocks": [
          {
            "start": "2026-03-01T09:00:00-08:00",
            "end": "2026-03-01T09:30:00-08:00",
            "entries": [
              {
                "identifierId": "idn_abc123",
                "status": "free",
                "type": "working_hours"
              }
            ]
          },
          {
            "start": "2026-03-01T09:30:00-08:00",
            "end": "2026-03-01T10:30:00-08:00",
            "entries": [
              {
                "identifierId": "idn_abc123",
                "status": "busy",
                "type": "event"
              }
            ]
          },
          {
            "start": "2026-03-01T10:30:00-08:00",
            "end": "2026-03-01T10:45:00-08:00",
            "entries": [
              {
                "identifierId": "idn_abc123",
                "status": "busy",
                "type": "buffer"
              }
            ]
          },
          {
            "start": "2026-03-01T10:45:00-08:00",
            "end": "2026-03-01T12:00:00-08:00",
            "entries": [
              {
                "identifierId": "idn_abc123",
                "status": "free",
                "type": "working_hours"
              }
            ]
          }
        ]
      }
    ]
  }
}

List Calendars

GET https://api.agnt.ai/calendars
json
{
  "ok": true,
  "calendars": [
    {
      "id": "cal_def456",
      "platform": "google",
      "name": "jane@acme.co",
      "isPrimary": true,
      "eventCount": 47,
      "..." : "..."
    }
  ]
}

List Calendars for Identifier

GET https://api.agnt.ai/identifiers/:identifierId/calendars
ParameterTypeDescription
platformstringFilter by provider: google or azure

Get Calendar Events

GET https://api.agnt.ai/calendars/:calendarId/events
ParameterTypeDescription
timezonestringIANA timezone for date interpretation
startsAtstringISO 8601 start of date range
endsAtstringISO 8601 end of date range
bash
curl "https://api.agnt.ai/calendars/cal_def456/events?timezone=America/Los_Angeles&startsAt=2026-03-01T00:00:00Z&endsAt=2026-03-07T23:59:59Z" \
  -H "Authorization: Bearer $TOKEN"
json
{
  "ok": true,
  "events": [
    {
      "id": "evt_abc123",
      "title": "Team Standup",
      "start": "2026-03-01T09:30:00-08:00",
      "end": "2026-03-01T10:00:00-08:00",
      "allDay": false,
      "status": "confirmed",
      "location": null,
      "conferenceUrl": "https://meet.google.com/abc-defg-hij"
    }
  ]
}

Sync Calendars from Provider

POST https://api.agnt.ai/identifiers/:identifierId/calendars/sync
FieldTypeRequiredDescription
platformstringYesgoogle or azure

Fetches the calendar list from the specified provider and creates or updates Calendar records in AGNT.

Sync All Resources

POST https://api.agnt.ai/identifiers/:identifierId/sync-resources

No body required. Syncs calendars and contacts from all connected OAuth providers for this identifier. This is the "refresh everything" endpoint.

Sync Events

POST https://api.agnt.ai/calendars/:calendarId/sync-events

No body required. Pulls the latest events from the provider for this calendar. Call this before reading events or computing timelines if you need fresh data.

Get Availability Timeline

GET https://api.agnt.ai/identifiers/:identifierId/timeline

Returns the computed availability timeline for the identifier, factoring in all linked calendars, working hours, and buffer preferences.

bash
curl https://api.agnt.ai/identifiers/idn_abc123/timeline \
  -H "Authorization: Bearer $TOKEN"

For Coding Agents

If you're building a scheduling agent, here's the playbook:

  • Sync before you read. Call sync-resources and then sync-events on relevant calendars before computing availability. Stale calendar data means double-bookings.
  • Use the timeline, not raw events. The timeline accounts for working hours, buffers, and multi-calendar conflicts. Parsing raw events yourself means rebuilding logic the platform already handles.
  • Check status across all entries in a block. A time slot is only truly free if every entry in that block has status: "free". One busy entry from any calendar means the slot is taken.
  • Respect buffer types. A buffer entry means the user wants padding around meetings. Don't schedule into buffer slots just because technically nothing is there.
  • Handle syncError. If a calendar has a non-null syncError, the last sync failed. The user may need to re-authorize OAuth access. Surface this to the user rather than silently using stale data.
  • Timezone is everything. Always pass timezone when querying events. The timeline returns timezone-aware timestamps, but your agent needs to interpret them in the user's local context.

For Product Teams

AGNT Calendar is the availability backbone for scheduling features. Here's what shapes the product:

  • Two providers, one model. Google and Microsoft calendars are normalized into the same structure. Your UI doesn't need separate code paths for each provider.
  • Sync is explicit, not real-time. There's no webhook listener keeping calendars perpetually fresh. Your application triggers syncs at the right moments — before showing availability, before booking a meeting. This keeps the system predictable and debuggable.
  • Timelines are the product surface. The raw calendar and event APIs exist for inspection, but the timeline endpoint is what you build scheduling UI on top of. It handles the combinatorics of multiple calendars, working hours, all-day events, and buffers.
  • Calendar roles matter. A user might own one calendar, have write access to a team calendar, and read-only access to a company-wide calendar. The role field tells you what level of access the sync was granted.
  • Conference solutions are synced. If a user's Google Calendar supports Google Meet or a Microsoft calendar supports Teams, the conferenceSolutions array tells you. Use this to auto-create video links when booking.
  • Working hours and buffers live in preferences. The timeline computation pulls working hours and buffer settings from the identifier's preferences (see AGNT Identity). If a user hasn't set preferences, the timeline still works — it just won't filter by working hours.