Google Tasks
Trigger workflows on Google Tasks created, completed, or updated across one or more lists.
The Google Tasks trigger polls the Google Tasks API on a configurable cadence and fires the workflow for each changed task. It's the right trigger for to-do-driven automation — for example, sending a Slack message when a task is marked complete, or kicking off a provisioning workflow when a task is created in a specific list.
Built on the generic tasks_poller_state table, so future providers (Todoist, Microsoft To Do, Asana, Trello) slot into the same pattern without schema changes.
Setup
- Drop the Google Tasks block onto your workflow as the entry point.
- Select a Google account — OAuth scope requested is
tasks.readonly. If you've already connected a Google account for Gmail or Calendar, the same credential works. - Pick one or more lists — the dropdown populates from your Google Tasks lists (
@defaultis always available). - Choose events —
task_completed(fires only on the completion transition) andtask_updated(fires on any change, including new tasks — Google Tasks' API doesn't distinguish creation from modification). - Pick a cadence tier — 5m / 15m / 30m / 60m. Matches the Cloud Scheduler poll tiers.
- Save.
Google Tasks has no push/webhook API — this is poll-based. The 5m tier is the fastest available; typical latency from task change to workflow fire is cadence/2 + a few seconds.
Block outputs
Access via dot notation: <googletasks1.title>, <googletasks1.status>, etc.
| Output | Type | Description |
|---|---|---|
taskId | string | Google Tasks task ID |
title | string | Task title |
status | string | needsAction or completed |
due | string | null | ISO-8601 due date, or null |
notes | string | Free-form task notes |
listId | string | Source list ID — useful for routing when watching multiple lists |
listTitle | string | Human-readable list title |
event | string | Which event fired: task_completed or task_updated |
updatedAt | string | Task last-modified timestamp |
task | object | Full task resource from the Google Tasks API |
How event types are classified
Google Tasks doesn't emit typed events — it only exposes a diff-since cursor, and the API doesn't let us distinguish task creation from other modifications without maintaining our own per-task seen-set. The trigger therefore exposes two events:
task_completed— task hasstatus === 'completed'and acompletedtimestamp set. Fires on the completion transition.task_updated— everything else (new tasks, title/notes edits, due-date changes, moves between lists). "Updated" here is a superset that includes creations.
If an edit changes both completion and title, the trigger fires once classified as task_completed (completion takes priority). Use <block.event> to route between the two.
Multi-list support
Select multiple lists in the Task lists dropdown. Each list is polled independently on its own cadence — one row per (trigger, list) in the backing state table. A single workflow run handles one task at a time; if 5 tasks change across 3 lists, the workflow fires 5 times (with <block.listId> identifying the source).
Good pattern: one trigger per workflow + multi-list when you want a single downstream fan-out. Use separate triggers per list when you want per-list logic (different cadences, different events).
Cadence and cost
| Tier | Use case | API quota usage |
|---|---|---|
| 5m | Responsive automation (incidents, real-time assignment) | High — 288 polls/day per list |
| 15m (default) | Most productivity workflows | Moderate — 96 polls/day per list |
| 30m | Daily-digest, low-urgency sync | Low |
| 60m | Archival, reporting | Lowest |
Google Tasks API quota is generous (~50k reads/day default). Even at 5m × 10 lists that's ~2 880 reads/day — well under limit.
Idempotency
Cursor is the ISO-8601 updated timestamp of the latest task seen. The API returns only tasks with updated > cursor, so the platform never re-fires for an unchanged task. If a workflow run fails, the next poll picks the same task up again (the cursor advances only on successful poll-completion).
Failure handling
- Consecutive auth failures (expired OAuth + no refresh token) surface as a red health dot on the block.
- After 3 consecutive failures the block flags itself in the UI; fix by re-authorising the Google credential.
- The poll row remains in
tasks_poller_statewithconsecutive_failuresincremented andlast_errorpopulated — visible in trigger admin views.
Verifying a poller
Google Tasks is poll-based — there's no inbound webhook URL. Force-run the dispatcher per apps/sat/tests/staging/triggers/pollers/README.md:
POLL_DISPATCH_SECRET=$(gcloud secrets versions access latest \
--secret=poll-dispatch-secret --project=ystudio-core)
curl -X POST -H "x-scheduler-key: $POLL_DISPATCH_SECRET" \
'https://mybotbox.com/api/webhooks/poll/dispatch?tier=15m'Extending to other task providers
The trigger's storage (tasks_poller_state with a provider discriminator) and dispatcher (/api/webhooks/poll/dispatch) are provider-agnostic. Adding Todoist / Microsoft To Do / Asana later is a ~1-file change: drop a new adapter in apps/sat/lib/triggers/<provider>/poller-adapter.ts, register a run endpoint, and add a branch in the dispatcher's provider switch. No schema changes.
When Google Tasks isn't the right fit
- Sub-5-minute latency — use a calendar-based trigger (Calendar event start), Pub/Sub push (Gmail), or an incoming webhook from a tool that posts directly.
- Task-creation-only — not possible without extra state; filter on
events: ['task_updated']and dedupe ontaskIddownstream. - Assignee-specific logic — Google Tasks doesn't expose assignees; use a workflow with Google Calendar or a dedicated project management tool.