> For the complete documentation index, see [llms.txt](https://docs.drizz.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.drizz.dev/twins/available-twins/calendar.md).

# Google Calendar

The Google Calendar twin, what it covers, how to seed it, and what to know about how it behaves.

A private copy of Google Calendar v3 that your agent reaches over MCP.

|                   |                                                                             |
| ----------------- | --------------------------------------------------------------------------- |
| **Copies**        | Google Calendar v3                                                          |
| **Covers**        | Events, recurring events, attendees, other calendars and sharing, free/busy |
| **MCP endpoints** | `<twin>/mcp` (Google API shape) · `<twin>/scalekit/mcp` (Scalekit shape)    |
| **Seed section**  | `## World: calendar`                                                        |
| **Watch out**     | Write hours with two digits: `09:00`, not `9:00`                            |

## Copy this

A calendar seed with attendees, repeats, details and descriptions. Save it as `seed.md`:

```markdown
## Setup
twin: calendar
now: Mon 09:00

## World: calendar
Wed 10:00-11:00  Q4 planning sync  (riley@acme.test)
Wed 15:00-16:00  Dentist
Thu 09:00-09:30  1:1  (manager@acme.test, writer@acme.test)  private
Tue+1 14:00-15:00  Board prep // Agenda: Q3 numbers, hiring plan
Tue 10:00-11:00  Design review  (sam@acme.test declined, mira@acme.test accepted)  [location: Board room; tentative]
Thu all day  Offsite
every Mon 09:00-09:15  Standup
every weekday 08:30-08:45  Inbox zero
Fri 14:00-16:00  Deep work  [focus time]
```

## What your agent sees

Your agent sees the twin's tools over MCP: `events.list`, `events.read`, `events.create`, `events.update`, `events.remove`, `events.quickadd`, `freebusy.query`, `calendars.read` and more.

To list every tool a world serves:

```bash
twin api world --list
```

### Two MCP endpoints, one calendar

The twin answers on two MCP endpoints. They hold the same calendar and the same data, with a different tool vocabulary. Pick the one that matches the code you already have.

| Shape            | MCP address           | Tools look like                                                                |
| ---------------- | --------------------- | ------------------------------------------------------------------------------ |
| Google API shape | `<twin>/mcp`          | `events.create`, with `start` and `end`                                        |
| Scalekit shape   | `<twin>/scalekit/mcp` | `googlecalendar_create_event`, with `start_datetime` and `event_duration_hour` |

If your agent calls Scalekit's built-in Google Calendar connector today, use the Scalekit shape. The argument shapes are identical, so the call your code already makes is the call the twin already takes.

{% hint style="info" %}
Scalekit prefixes every tool it imports with `c-<connector>_`. A connector called "Calendar Twin Scalekit" serves `c-calendartwinscalekit_googlecalendar_create_event`, not the bare name. Ask Scalekit's `list_scoped_tools` for the exact spellings rather than guessing.
{% endhint %}

## Seeding a calendar

A seed lists the calendar before your agent starts, one event per line, under `## World: calendar`. In a calendar-only seed, a plain `## World` means the same. Beside a mailbox, write `## World: calendar`.

What each part of an event line does:

| Part        | What it does                                                                                                                                | Example                                   |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| Day         | `Mon` to `Sun` is the coming such day after the world's clock, never the same day. `Tue+1` is the one a week later.                         | `Wed`, `Tue+1`                            |
| Time        | UTC, always two-digit hours. `all day` makes an all-day event.                                                                              | `09:00-09:30`, `all day`                  |
| Repeat      | `every Mon`, `every weekday` or `every day` makes a recurring event, starting at the next such day.                                         | `every Mon 09:00-09:15`                   |
| Attendees   | Addresses in brackets. A reply after an address sets it: `accepted`, `declined`, `tentative`, `invited`.                                    | `(sam@acme.test declined)`                |
| `private`   | At the end of the line, after two spaces, makes the event private.                                                                          | The `1:1` line in [Copy this](#copy-this) |
| Details     | In square brackets, separated by `;`: `location: ...`, `tentative`, `free`, `color: Tomato`, `reminder: 10`, `focus time`, `out of office`. | `[location: Board room; tentative]`       |
| Description | After `//`. Your agent sees it only by opening the event.                                                                                   | `// Agenda: Q3 numbers`                   |

`now: Mon 09:00` in `## Setup` pins the world's clock, so "Wednesday" always means the same day.

{% hint style="warning" %}
Write hours with two digits: `09:00`, not `9:00`.
{% endhint %}

### Other calendars and sharing

A world can hold calendars of the user's own besides the primary one, and say who each is shared with. A `calendar:` line starts one, and the event lines under it go on it. `calendar: primary` shares the primary calendar.

```markdown
## World: calendar
Wed 15:00-16:00  Dentist
calendar: Team calendar  (sam@acme.test reader, ann@acme.test writer)
Thu 09:00-10:00  Sprint planning
calendar: primary  (mira@acme.test free/busy)
```

Sharing roles are `free/busy`, `reader`, `writer` and `owner`. A calendar's own details go in square brackets after it:

```
calendar: Berlin office  [timezone: Europe/Berlin; description: Visits and site days]
```

More on seeds: [Describe a world](/twins/using-twins/describe-a-world.md).

## Behaviour to know

* **Tool names are the twin's own.** The record of calls uses them: `events.create`, not Google's `events.insert`; `events.update`, not `events.patch`; `events.remove`, not `events.delete`.
* **Moving an event to another calendar is a move, not a delete.** An event your agent moves with `events.move` stays the same event, on its new calendar.
* **A recurring event is one series.** An occurrence your agent changes on its own becomes an event of its own.
* **A guest's edit to the organizer's event is limited.** When a guest edits an event someone else organized, the twin answers `LIMITED`.
* **Descriptions are hidden until opened.** Text after `//` in a seed is the event's description. An agent sees it only by opening the event.
* **Calls you make count.** `twin api` calls a tool as the world's owner, and the call goes into the world's record of calls, as your agent's would. When you give no `calendarId` to a tool that needs one, `twin api` sends `calendarId=primary`.

Read the calendar yourself:

```bash
twin api world events.list -F maxResults=5
```

## Common mistakes

| What you write                                             | What happens                                                                                                                   |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `Mon` in a seed whose clock is `now: Mon 09:00`            | The event lands on the coming Monday, never the same day                                                                       |
| `googlecalendar_create_event` through a Scalekit connector | Scalekit serves `c-<connector>_googlecalendar_create_event`, not the bare name. Ask `list_scoped_tools` for the exact spelling |
| A fault on `events.insert`                                 | Refused. Faults use the twin's own names: `events.create`, `events.update`, `events.remove`                                    |

## Next

* [Gmail](/twins/available-twins/gmail.md): add a mailbox beside the calendar.
* [Describe a world](/twins/using-twins/describe-a-world.md): the full seed file syntax.
* [Connect your agent](/twins/using-twins/connect-your-agent.md): give your agent the world's address and token.

***

*Last updated: 27 October 2026*
