For Coding Agents
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:
curl -X POST https://api.agnt.ai/identifiers/idn_abc123/calendars/sync \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "platform": "google" }'{
"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
curl -X POST https://api.agnt.ai/calendars/cal_def456/sync-events \
-H "Authorization: Bearer $TOKEN"{
"ok": true,
"calendar": {
"id": "cal_def456",
"eventCount": 47,
"lastSyncedAt": "2026-03-01T12:05:00.000Z"
}
}3. Get Availability Timeline
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:
| Status | Meaning |
|---|---|
free | Available for scheduling |
busy | Not available |
| Type | Meaning |
|---|---|
working_hours | Within defined working hours, no conflicts |
event | A calendar event occupies this slot |
all_day_event | An all-day event covers this slot |
outside_working_hours | Outside the user's defined working hours |
buffer | Buffer 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
| Method | Path | Description | Auth |
|---|---|---|---|
GET | /calendars | List all calendars for authenticated user | Delegated |
GET | /calendars/:calendarId | Get calendar details | Delegated |
GET | /calendars/:calendarId/events | List events for a calendar | Delegated |
POST | /calendars/:calendarId/sync-events | Trigger event sync for a calendar | Delegated |
GET | /identifiers/:identifierId/calendars | List calendars for an identifier | Delegated |
POST | /identifiers/:identifierId/calendars/sync | Sync calendars from an OAuth provider | Delegated |
POST | /identifiers/:identifierId/sync-resources | Sync calendars + contacts from all providers | Delegated |
GET | /identifiers/:identifierId/timeline | Get availability timeline | Delegated |
Calendar Object
{
"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"
}| Field | Type | Description |
|---|---|---|
id | string | Unique calendar ID |
account | string | Account ID |
platform | string | Provider: google or azure |
name | string | Calendar display name |
timezone | string | IANA timezone |
referenceId | string | Provider-side calendar ID |
backgroundColor | string | Calendar color from the provider |
conferenceSolutions | string[] | Available video conferencing options |
lastSyncedAt | string | null | Last successful event sync timestamp |
syncError | string | null | Last sync error message, if any |
eventCount | number | Number of synced events |
role | string | User's role: owner, writer, or reader |
isPrimary | boolean | Whether this is the primary calendar |
userIdentifier | string | Identifier ID this calendar belongs to |
createdAt | string | ISO 8601 creation timestamp |
updatedAt | string | ISO 8601 last update timestamp |
Timeline Object
{
"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
{
"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
| Parameter | Type | Description |
|---|---|---|
platform | string | Filter by provider: google or azure |
Get Calendar Events
GET https://api.agnt.ai/calendars/:calendarId/events
| Parameter | Type | Description |
|---|---|---|
timezone | string | IANA timezone for date interpretation |
startsAt | string | ISO 8601 start of date range |
endsAt | string | ISO 8601 end of date range |
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"{
"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
| Field | Type | Required | Description |
|---|---|---|---|
platform | string | Yes | google 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.
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-resourcesand thensync-eventson 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
statusacross all entries in a block. A time slot is only trulyfreeif every entry in that block hasstatus: "free". Onebusyentry from any calendar means the slot is taken. - Respect buffer types. A
bufferentry 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-nullsyncError, 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
timezonewhen 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
rolefield 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
conferenceSolutionsarray 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.