Today is a thinking lesson, not a code one. The pattern: imagine a script runs once at 9am, then runs again at 10am — same script, same code, no manual changes. What happens?
# Script A — read
messages = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": 5})
print(len(messages.get("messages", [])))Run A at 9am: prints 5. Run A at 10am: prints 5. Same outcome. A is idempotent — repeating doesn't compound.
# Script B — send
toolset.execute_action(Action.GMAIL_SEND_EMAIL, {
"recipient_email": "boss@co.com",
"subject": "daily report",
"body": "...",
})Run B at 9am: one email sent. Run B at 10am: another email sent. Now there are two. Different outcome. B is NOT idempotent.
So reads are safe to repeat, writes aren't?
Mostly. With nuance:
SEND, APPEND, naive CREATE): not idempotent. Re-runs duplicate.if not exists check (think: CREATE_OR_GET, UPDATE_BY_KEY): idempotent if you provide the key consistently.Why does this matter for week 2?
Because retry-on-error is a normal pattern. If your script fails halfway through, you re-run. If the script wasn't designed for that, you create the same row twice, send the same email twice, charge the same card twice. Knowing which half of your code is and isn't idempotent is the difference between safe automation and a phone call from accounting.
Formally: an operation is idempotent if applying it twice has the same effect as applying it once.
f(f(x)) == f(x) for any xFor scripts: running the script a second time should leave the world in the same state as running it once.
Fetching, listing, getting, querying — these don't change anything on the server. Run them as many times as you like.
Send an email twice → 2 emails. Append a row twice → 2 rows. Create an event twice → 2 events with the same name (different IDs).
The pattern: include a uniqueness key the API can use to recognize duplicates.
Message-ID header you control. (Most APIs don't deduplicate on send; you'd have to track sent IDs in your own state — see day 14.)iCalUID that makes create-or-update behaviour easy.Idempotency-Key header — repeated calls with the same key return the same response without re-executing.Before running a write loop, ask:
If the answer is "two" or "partial duplicate", you don't have idempotency — and you need to add it before this script runs unattended.
The full design pattern (state files, dedup keys, retry-with-backoff) lives in Auto Intermediate. For this week: just recognize whether a script you're writing is idempotent.
Today is a thinking lesson, not a code one. The pattern: imagine a script runs once at 9am, then runs again at 10am — same script, same code, no manual changes. What happens?
# Script A — read
messages = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": 5})
print(len(messages.get("messages", [])))Run A at 9am: prints 5. Run A at 10am: prints 5. Same outcome. A is idempotent — repeating doesn't compound.
# Script B — send
toolset.execute_action(Action.GMAIL_SEND_EMAIL, {
"recipient_email": "boss@co.com",
"subject": "daily report",
"body": "...",
})Run B at 9am: one email sent. Run B at 10am: another email sent. Now there are two. Different outcome. B is NOT idempotent.
So reads are safe to repeat, writes aren't?
Mostly. With nuance:
SEND, APPEND, naive CREATE): not idempotent. Re-runs duplicate.if not exists check (think: CREATE_OR_GET, UPDATE_BY_KEY): idempotent if you provide the key consistently.Why does this matter for week 2?
Because retry-on-error is a normal pattern. If your script fails halfway through, you re-run. If the script wasn't designed for that, you create the same row twice, send the same email twice, charge the same card twice. Knowing which half of your code is and isn't idempotent is the difference between safe automation and a phone call from accounting.
Formally: an operation is idempotent if applying it twice has the same effect as applying it once.
f(f(x)) == f(x) for any xFor scripts: running the script a second time should leave the world in the same state as running it once.
Fetching, listing, getting, querying — these don't change anything on the server. Run them as many times as you like.
Send an email twice → 2 emails. Append a row twice → 2 rows. Create an event twice → 2 events with the same name (different IDs).
The pattern: include a uniqueness key the API can use to recognize duplicates.
Message-ID header you control. (Most APIs don't deduplicate on send; you'd have to track sent IDs in your own state — see day 14.)iCalUID that makes create-or-update behaviour easy.Idempotency-Key header — repeated calls with the same key return the same response without re-executing.Before running a write loop, ask:
If the answer is "two" or "partial duplicate", you don't have idempotency — and you need to add it before this script runs unattended.
The full design pattern (state files, dedup keys, retry-with-backoff) lives in Auto Intermediate. For this week: just recognize whether a script you're writing is idempotent.
Create a free account to get started. Paid plans unlock all tracks.