Yesterday email_sheet_summary chained two apps — it read a Sheet, then sent an email. You got one dict back. Today the return type changes. What do you get when you do the same action for every event on a calendar?
A list, I guess. One task per event, so the result is all of them collected together. email_sheet_summary returned a single send-confirmation. This one would be a list of task confirmations.
Exactly right. GOOGLECALENDAR_FIND_EVENT hands back a dict with an items key — your upcoming events. You loop over them, call GOOGLETASKS_INSERT_TASK for each, collect the results, and return the list. Here's the shape:
events = toolset.execute_action(Action.GOOGLECALENDAR_FIND_EVENT, {"calendar_id": cal_id, "time_min": "2026-04-19T00:00:00Z"}).get("items", [])The time_min is hard-coded to today's date? If I run this next week it still filters from April 19th?
Good catch — in a real workflow you'd generate that timestamp dynamically from datetime.utcnow().isoformat() + "Z". For this lesson, a fixed string keeps the signature clean so you can focus on the loop. The point is that time_min scopes the fetch to events that haven't happened yet — you're not pulling your entire calendar history.
So every event in items is a dict with a summary key, and I use that to name the task. Prep: team sync, Prep: QBR review — all of them in one pass.
One pass. No browser. No copy-paste. The task list populates while you're still in bed. Here's the insert:
task = toolset.execute_action(Action.GOOGLETASKS_INSERT_TASK, {"tasklist": list_id, "title": f"Prep: {title}", "notes": ""})I could wire my whole Monday morning in this. Pull the week's events, create prep tasks for all of them, and the list is ready before I open my laptop.
That's exactly where this is headed. One rule before you run it against a full calendar: GOOGLETASKS_INSERT_TASK creates a real task every time — no deduplication. Run this twice and you'll have two "Prep: Team Sync" tasks sitting in your list. In production, check whether a task already exists or gate the run to once per day.
GOOGLECALENDAR_FIND_EVENT returns upcoming events; GOOGLETASKS_INSERT_TASK creates one task per event. The pattern is a fetch-then-loop.
| Action | Key args | Notes |
|---|---|---|
GOOGLECALENDAR_FIND_EVENT | calendar_id, time_min | time_min is ISO 8601 UTC; use "primary" for the default calendar |
GOOGLETASKS_INSERT_TASK | tasklist, title, notes | tasklist is "@default" for the default task list |
The function returns a list of task dicts — one per event. Events with no summary fall back to "Untitled".
No deduplication: each call creates new tasks. Gate to one run per day or check for existing tasks before inserting.
Yesterday email_sheet_summary chained two apps — it read a Sheet, then sent an email. You got one dict back. Today the return type changes. What do you get when you do the same action for every event on a calendar?
A list, I guess. One task per event, so the result is all of them collected together. email_sheet_summary returned a single send-confirmation. This one would be a list of task confirmations.
Exactly right. GOOGLECALENDAR_FIND_EVENT hands back a dict with an items key — your upcoming events. You loop over them, call GOOGLETASKS_INSERT_TASK for each, collect the results, and return the list. Here's the shape:
events = toolset.execute_action(Action.GOOGLECALENDAR_FIND_EVENT, {"calendar_id": cal_id, "time_min": "2026-04-19T00:00:00Z"}).get("items", [])The time_min is hard-coded to today's date? If I run this next week it still filters from April 19th?
Good catch — in a real workflow you'd generate that timestamp dynamically from datetime.utcnow().isoformat() + "Z". For this lesson, a fixed string keeps the signature clean so you can focus on the loop. The point is that time_min scopes the fetch to events that haven't happened yet — you're not pulling your entire calendar history.
So every event in items is a dict with a summary key, and I use that to name the task. Prep: team sync, Prep: QBR review — all of them in one pass.
One pass. No browser. No copy-paste. The task list populates while you're still in bed. Here's the insert:
task = toolset.execute_action(Action.GOOGLETASKS_INSERT_TASK, {"tasklist": list_id, "title": f"Prep: {title}", "notes": ""})I could wire my whole Monday morning in this. Pull the week's events, create prep tasks for all of them, and the list is ready before I open my laptop.
That's exactly where this is headed. One rule before you run it against a full calendar: GOOGLETASKS_INSERT_TASK creates a real task every time — no deduplication. Run this twice and you'll have two "Prep: Team Sync" tasks sitting in your list. In production, check whether a task already exists or gate the run to once per day.
GOOGLECALENDAR_FIND_EVENT returns upcoming events; GOOGLETASKS_INSERT_TASK creates one task per event. The pattern is a fetch-then-loop.
| Action | Key args | Notes |
|---|---|---|
GOOGLECALENDAR_FIND_EVENT | calendar_id, time_min | time_min is ISO 8601 UTC; use "primary" for the default calendar |
GOOGLETASKS_INSERT_TASK | tasklist, title, notes | tasklist is "@default" for the default task list |
The function returns a list of task dicts — one per event. Events with no summary fall back to "Untitled".
No deduplication: each call creates new tasks. Gate to one run per day or check for existing tasks before inserting.
Create a free account to get started. Paid plans unlock all tracks.