You made task creation idempotent. Now apply the same pattern to Calendar. The API changes, but the shape — list, match, early-return or create — stays the same. What field does Calendar use for the event title?
I remember from Week 1 — events use summary, not title.
Right. So the match condition is event.get("summary") == summary. The action for reading events is GOOGLECALENDAR_FIND_EVENT; the action for creating is GOOGLECALENDAR_CREATE_EVENT. Same idempotent shape, different field names:
existing = toolset.execute_action(Action.GOOGLECALENDAR_FIND_EVENT, {"query": summary})
for event in existing.get("items", []):
if event.get("summary") == summary:
return event["id"]Passing query=summary makes the list call narrower — only candidates mentioning that string — so the match loop stays cheap?
Exactly. Narrowing at the API level saves the loop from scanning hundreds of irrelevant events. Then the exact-match check filters the few remaining candidates:
def idempotent_create_event(summary: str, start_iso: str, end_iso: str) -> str:
existing = toolset.execute_action(Action.GOOGLECALENDAR_FIND_EVENT, {"query": summary})
for event in existing.get("items", []):
if event.get("summary") == summary:
print(f"Event '{summary}' already exists with id={event['id']}")
return event["id"]
created = toolset.execute_action(
Action.GOOGLECALENDAR_CREATE_EVENT,
{"summary": summary, "start_datetime": start_iso, "end_datetime": end_iso},
)
print(f"Created event '{summary}' with id={created['id']}")
return created["id"]Is exact-match strict enough? What if a similar event with different casing exists?
For this lesson yes — production systems often normalize casing or hash a canonical key. The pattern is the same; the match function is what you tune for your dedup rules.
So I've now idempotently created both a task and an event — two different APIs, one pattern, safe to re-run every time?
The shape transfers to any write API. Gmail drafts, Sheets rows, Docs headings — list, match, create. This is the production skeleton for writes.
TL;DR: The idempotent create pattern is the same across APIs — only the field names change.
summary where Tasks uses title| API | Title field | List action | Create action |
|---|---|---|---|
| Tasks | title | GOOGLETASKS_LIST_TASKS | GOOGLETASKS_CREATE_TASK |
| Calendar | summary | GOOGLECALENDAR_FIND_EVENT | GOOGLECALENDAR_CREATE_EVENT |
You made task creation idempotent. Now apply the same pattern to Calendar. The API changes, but the shape — list, match, early-return or create — stays the same. What field does Calendar use for the event title?
I remember from Week 1 — events use summary, not title.
Right. So the match condition is event.get("summary") == summary. The action for reading events is GOOGLECALENDAR_FIND_EVENT; the action for creating is GOOGLECALENDAR_CREATE_EVENT. Same idempotent shape, different field names:
existing = toolset.execute_action(Action.GOOGLECALENDAR_FIND_EVENT, {"query": summary})
for event in existing.get("items", []):
if event.get("summary") == summary:
return event["id"]Passing query=summary makes the list call narrower — only candidates mentioning that string — so the match loop stays cheap?
Exactly. Narrowing at the API level saves the loop from scanning hundreds of irrelevant events. Then the exact-match check filters the few remaining candidates:
def idempotent_create_event(summary: str, start_iso: str, end_iso: str) -> str:
existing = toolset.execute_action(Action.GOOGLECALENDAR_FIND_EVENT, {"query": summary})
for event in existing.get("items", []):
if event.get("summary") == summary:
print(f"Event '{summary}' already exists with id={event['id']}")
return event["id"]
created = toolset.execute_action(
Action.GOOGLECALENDAR_CREATE_EVENT,
{"summary": summary, "start_datetime": start_iso, "end_datetime": end_iso},
)
print(f"Created event '{summary}' with id={created['id']}")
return created["id"]Is exact-match strict enough? What if a similar event with different casing exists?
For this lesson yes — production systems often normalize casing or hash a canonical key. The pattern is the same; the match function is what you tune for your dedup rules.
So I've now idempotently created both a task and an event — two different APIs, one pattern, safe to re-run every time?
The shape transfers to any write API. Gmail drafts, Sheets rows, Docs headings — list, match, create. This is the production skeleton for writes.
TL;DR: The idempotent create pattern is the same across APIs — only the field names change.
summary where Tasks uses title| API | Title field | List action | Create action |
|---|---|---|---|
| Tasks | title | GOOGLETASKS_LIST_TASKS | GOOGLETASKS_CREATE_TASK |
| Calendar | summary | GOOGLECALENDAR_FIND_EVENT | GOOGLECALENDAR_CREATE_EVENT |
Create a free account to get started. Paid plans unlock all tracks.