send_email from last week completed the Gmail loop. Calendar is the next app. Before creating events, you need to know which calendar to use. How many Google calendars do you actually have?
My personal one, my university research calendar, and a shared one for the lab group. Three calendars — and the IDs are somewhere in the Calendar settings, but I've never needed to look them up before.
toolset.execute_action follows the same pattern — GOOGLECALENDAR_LIST_CALENDARS returns a dict with a calendars key holding a list. Each calendar has an id and a summary (display name). Same .get() reflex you used for Gmail:
result = toolset.execute_action(Action.GOOGLECALENDAR_LIST_CALENDARS, {})
calendars = result.get("calendars", [])
for cal in calendars:
print(f"{cal.get('summary')}: {cal.get('id')}")GOOGLECALENDAR_LIST_CALENDARS — different namespace than Gmail, but the same toolset.execute_action wrapper? That's all that changes?
That's the pattern. The Action enum and the params dict are the only things that change between apps. The wrapper is always toolset.execute_action(Action.X, {...}). Learn the pattern once, use it everywhere:
def list_calendars() -> list:
result = toolset.execute_action(Action.GOOGLECALENDAR_LIST_CALENDARS, {})
calendars = result.get("calendars", [])
print(f"Found {len(calendars)} calendars")
return calendarsThree calendars back — personal, research, lab group. The research calendar ID is the one I need for the deadline events.
You'll never dig through Calendar settings for an ID again. One function call.
I'm applying the same .get() reflex I learned for Gmail to Calendar — the shape of the response is just slightly different.
Calendar IDs look like email addresses (primary, user@gmail.com, or a long hash). When you call GOOGLECALENDAR_FIND_EVENT or GOOGLECALENDAR_CREATE_EVENT, always retrieve the ID programmatically with list_calendars — never hardcode it. Calendar IDs can change if the calendar is deleted and recreated.
Every Composio app follows the same shape:
result = toolset.execute_action(Action.APP_ACTION_NAME, {params})
items = result.get("key", [])GOOGLECALENDAR_LIST_CALENDARS returns {"calendars": [{"id": "...", "summary": "..."}, ...]}.
| Calendar | ID format |
|---|---|
| Primary | "primary" or email |
| Shared | Long hash string |
Always look up IDs at runtime — never hardcode them. Calendar IDs change when accounts are migrated or calendars are deleted and recreated.
send_email from last week completed the Gmail loop. Calendar is the next app. Before creating events, you need to know which calendar to use. How many Google calendars do you actually have?
My personal one, my university research calendar, and a shared one for the lab group. Three calendars — and the IDs are somewhere in the Calendar settings, but I've never needed to look them up before.
toolset.execute_action follows the same pattern — GOOGLECALENDAR_LIST_CALENDARS returns a dict with a calendars key holding a list. Each calendar has an id and a summary (display name). Same .get() reflex you used for Gmail:
result = toolset.execute_action(Action.GOOGLECALENDAR_LIST_CALENDARS, {})
calendars = result.get("calendars", [])
for cal in calendars:
print(f"{cal.get('summary')}: {cal.get('id')}")GOOGLECALENDAR_LIST_CALENDARS — different namespace than Gmail, but the same toolset.execute_action wrapper? That's all that changes?
That's the pattern. The Action enum and the params dict are the only things that change between apps. The wrapper is always toolset.execute_action(Action.X, {...}). Learn the pattern once, use it everywhere:
def list_calendars() -> list:
result = toolset.execute_action(Action.GOOGLECALENDAR_LIST_CALENDARS, {})
calendars = result.get("calendars", [])
print(f"Found {len(calendars)} calendars")
return calendarsThree calendars back — personal, research, lab group. The research calendar ID is the one I need for the deadline events.
You'll never dig through Calendar settings for an ID again. One function call.
I'm applying the same .get() reflex I learned for Gmail to Calendar — the shape of the response is just slightly different.
Calendar IDs look like email addresses (primary, user@gmail.com, or a long hash). When you call GOOGLECALENDAR_FIND_EVENT or GOOGLECALENDAR_CREATE_EVENT, always retrieve the ID programmatically with list_calendars — never hardcode it. Calendar IDs can change if the calendar is deleted and recreated.
Every Composio app follows the same shape:
result = toolset.execute_action(Action.APP_ACTION_NAME, {params})
items = result.get("key", [])GOOGLECALENDAR_LIST_CALENDARS returns {"calendars": [{"id": "...", "summary": "..."}, ...]}.
| Calendar | ID format |
|---|---|
| Primary | "primary" or email |
| Shared | Long hash string |
Always look up IDs at runtime — never hardcode them. Calendar IDs change when accounts are migrated or calendars are deleted and recreated.
Create a free account to get started. Paid plans unlock all tracks.