BlogUpdated 4 November 2026 · 5 min read

How to give your AI agent its own calendar

Should an AI agent schedule from your calendar, or have its own, and how does an agent's calendar work?

The short answer

Give the agent a calendar of its own, on its own email address, and invite it to meetings the way you would invite a colleague. With Pidgeon every inbox already has one: the agent creates events and recurring series over the API, sends and answers real invitations from its address, and a calendar app reaches it over CalDAV. Its own calendar beats access to yours because the agent then acts as itself, and its key reaches nothing of yours.

Why not hand it your calendar

The usual way to let an agent schedule is to connect it to a person's calendar. Then everything it does, it does as that person. An invitation it accepts is accepted in their name. A meeting it moves moves in their week. The other attendees cannot tell the agent from the person, and neither can anyone reading the calendar later.

An agent with its own address and calendar is an attendee like anybody else:

  • It shows up as itself. Invite scheduler@yourcompany.com to the meeting and it appears on the attendee list under its own name. Its acceptance comes from its own address.
  • Its key reaches only what it owns. A Pidgeon key can be limited to one address. A key for the agent's address reads and writes the agent's calendar and nothing else.
  • You decide what it sees. It knows about the meetings it is invited to, not every appointment in your week.
  • What it books is on its record. Events it created say source: "api"; invitations it received say source: "mail" and point to the message they came in.

Nothing to create

The calendar exists because the address does:

curl https://pidgeon.ai/api/v1/identities/$IDENTITY_ID/calendar \
  -H "Authorization: Bearer $PIDGEON_API_KEY"

An event needs a title, a start and an end. Send timezone too. Pidgeon stores the wall-clock time and the zone, and derives the UTC instants from them, so a meeting at 09:00 in London stays at 09:00 in London across the clock change.

curl https://pidgeon.ai/api/v1/identities/$IDENTITY_ID/calendar/events \
  -H "Authorization: Bearer $PIDGEON_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: kickoff-4471" \
  -d '{
    "title": "Kick-off with Priya",
    "start": "2026-11-10T09:00:00",
    "end": "2026-11-10T09:30:00",
    "timezone": "Europe/London",
    "attendees": [{ "email": "priya@example.com", "name": "Priya Raman" }],
    "send_invites": true
  }'

Adding attendees sends nothing on its own. send_invites does, as a separate field, because putting a meeting on a calendar can be undone and telling five people about it cannot. With it, Pidgeon sends a real iCalendar REQUEST from the agent's address, the kind Gmail and Outlook show an Accept button on. Answers come back to the inbox, update the attendee list and fire calendar.event.responded.

To read what is on, GET …/calendar/agenda takes a window and returns events in start order. Edits take If-Match with the event's etag, so an agent never overwrites a change a person made a second earlier. metadata holds your own JSON, such as a ticket id, and never goes into a webhook or into mail to attendees.

Recurring events

A repeating meeting is one event with a rule, in the RFC 5545 form every calendar uses:

{
  "title": "Weekly pipeline review",
  "start": "2026-11-10T09:00:00",
  "end": "2026-11-10T09:30:00",
  "timezone": "Europe/London",
  "recurrence": { "rule": "FREQ=WEEKLY;BYDAY=TU" }
}

The dates are worked out when somebody asks for them. The agenda expands the series, and GET …/events/{id}/instances lists the dates in a window. Each date has an id of its own, {seriesId}::{originalStart}. A change or a delete names a date and a mode: single for that date only, future for that date and every one after it. Deleting one date writes an exception into the rule, so the rule does not produce it again.

Invitations to the agent

An invitation that arrives by email, from an organiser whose mail passes DMARC, becomes an event on the agent's calendar with no code of yours. message.invitation fires for the message, and calendar.event.created for the event. The agent answers from the message or from the event:

curl https://pidgeon.ai/api/v1/messages/$MESSAGE_ID/invitation/respond \
  -H "Authorization: Bearer $PIDGEON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "accepted", "comment": "I will bring the numbers." }'

status is accepted, declined or tentative, and an iCalendar REPLY goes back to the organiser. Answering from the event takes send_reply: false to record the answer and tell nobody.

Only the organiser can change an invited event, and only with mail that passes DMARC. An update or cancellation from anyone else, or from a domain with no DMARC record, stays a message and leaves the calendar alone. A forged From: cannot put a meeting on the agent's calendar or call one off. Pidgeon also never sends invitations for an event it only heard about, because that would be forging one from somebody else's organiser.

Acting when the meeting starts

calendar.event.starting and calendar.event.ending fire from the clock, within about a minute of the time, once per date. Subscribe a webhook to them and the agent can send the agenda as a meeting opens or write up the follow-up as it closes, without a scheduler of its own.

To find a time, GET /v1/calendar/free-time merges the agendas of up to 10 Pidgeon addresses the key can read, within working hours you set, over a window of up to 31 days.

Over MCP the same calls are create_calendar_event, get_agenda, respond_to_invitation and find_free_time.

In a calendar app

The agent's calendar is also a CalDAV calendar at https://dav.pidgeon.ai, signed in with an app password for that one address. Add it to Apple Calendar, Thunderbird or Cal.com, and a person sees what the agent has booked beside their own week, without giving the agent anything of theirs.

Limits

  • One calendar per address, holding events only. Tasks and reminder lists are not supported.
  • Free time covers Pidgeon addresses. It does not read a calendar at another provider.
  • The agenda has no cursor. A window holding more than 1,000 dates is refused, and you ask for a smaller one.
  • No agent loop. Pidgeon keeps the calendar and fires the events. Deciding what to accept is your agent's job.

Start

Sign up and create an address for the agent. Calendar explains wall-clock time, events and recurring events cover the writes, invitations covers both directions, and mail clients has the CalDAV settings for each app.

01

Asked often

Does every Pidgeon inbox have a calendar?

Yes. The calendar exists because the address does, with nothing to create; GET /v1/identities/{id}/calendar returns it.

Can the agent send real meeting invitations?

Yes, with send_invites on an event it created. Pidgeon sends an iCalendar REQUEST from the agent's address, and answers come back to its inbox and update the attendee list.

Can a forged email put a meeting on the agent's calendar?

No. An invitation, update or cancellation changes the calendar only when it comes from the organiser and passes DMARC; anything else stays a message.

Can I see the agent's calendar in Apple Calendar?

Yes. It is a CalDAV calendar at https://dav.pidgeon.ai, signed in with an app password for that address, and Thunderbird and Cal.com connect the same way.

02

Keep reading

All posts

Give your agents an identity

Pidgeon is building the trust layer of the agentic web.

Register your agents, it’s free