22.15 Schedules and webhooks
- Approved by
- Panaversity ·
In everyday life. A newspaper is delivered at 6:30 every morning, whatever the weather. When the paper has a correction, the publisher mails a short note saying "page 4 changed", not a new copy of page 4. A careful subscriber checks the note is really from the publisher, ignores a second copy of the same note, and reads page 4 itself. In this concept, the delivery at 6:30 is a scheduled run, and the note is a webhook.
What you will learn. How to start a worker's runs on a timetable, how your product hears that a run stopped, and the traps in both: clocks that change, messages sent twice, and messages lost.
Why it matters. Work that runs while nobody watches must start on time and report safely. A run that starts twice, or a message that never arrives, must not post a report twice or leave one missing.
One request, start to finish. Brightline wants the worker to triage new invoices every weekday morning at 7:10, New York time, and post the result in the portal. On Sunday, November 1, 2026, clocks in New York went back an hour at 2:00 a.m. Brightline also runs a nightly overdue-invoice check at 1:30 a.m., every day.
- The scheduled run starts a session at 7:10 New York time, plus a short random delay.
- The session finishes. The platform sends the portal a webhook: "session S finished".
- The portal checks the message is really from the platform, ignores it if it has seen that message before, then fetches session S's current state and posts the worker's report. The worker only answers. The portal does the posting.
- On that fall-back Sunday, the 1:30 a.m. overdue check started twice, because that hour happened twice. The portal keeps one report per schedule, company and local date, so it posted the first and recorded the second as a repeat. The second run still cost money, up to its budget, which is why the safest fix is to avoid that hour altogether.
What does work without a person need?
Work that runs without a person needs two things: something that starts it on time, and a way for your product to hear that it stopped.
This concept has two halves: schedules start work, and webhooks tell you it stopped.
Schedules
A scheduled run starts a session on a timetable. The timetable is a cron expression, five fields for minute, hour, day of month, month and day of week. 10 7 * * 1-5 means 7:10 on Monday to Friday. Every schedule needs a named time zone, such as America/New_York, because "7:10" means nothing without one. Four behaviors catch people out:
- Jitter. Platforms add a small random delay to each start, so that thousands of schedules set for 7:00 do not all start at once. A run set for 7:10 may start three minutes late.
- Daylight saving. Many countries, including the United States, move their clocks one hour forward in spring and one hour back in autumn, to make better use of daylight. Many others do not. On the day clocks go forward, a time that does not exist (2:30 a.m.) does not run. On the day clocks go back, a time that happens twice (1:30 a.m.) runs twice. Avoid those hours, and make the run safe to repeat anyway: a worker with read-only tools cannot check what was already done, so the product that receives the result must keep one result per day and ignore a second.
- Runs that never started. A start can fail, for example when too many sessions are being made at once. The schedule records the failure, and may not retry it. Check the schedule's own record of attempts.
- Paused schedules do not catch up. If a schedule is paused and resumed, the runs it missed are not made up.
Which word has two meanings?
Some platforms call a scheduled run a deployment, and the lab's folder for schedules is deployments/. That is not the same as deploying the portal, which means publishing your own server's new code. When a task says "deployment" with a schedule, it means the platform's scheduled run.
Webhooks
Your product could ask the platform, every few seconds, whether a session has finished. A webhook turns that around: the platform sends a short web request to an address on your server when something happens. Each one is signed with a signing secret that only you and the platform know, so your server can check it really came from the platform. Four rules make a webhook receiver correct:
- Check the signature and the time. Reject a message whose signature is wrong, or whose timestamp is more than a few minutes old. An old message sent again by someone else, a replay, then fails.
- Ignore repeats. The platform may send the same message more than once, with the same event id each time. Record each id you have handled, and skip any you have seen.
- Fetch the current state. A webhook carries ids, not the whole session. Fetch the session to learn what it says now, because two messages can arrive out of order.
- Reconcile on a timer. After a few failed attempts, a platform may drop a message for good, with no further sign. So once an hour, the portal lists recent sessions and catches any it never heard about. Checking your records against the source like this is called reconciling.
Watch out: a scheduled run acts as a person. A scheduled run needs a vault like any session, so it acts with someone's access. In the lab, Brightline's morning triage uses Ana's vault, and its report is posted for everyone at Brightline. That is acceptable only because every clerk there may see the same invoices. Say in the report whose access made it. Part II's worker ran on Maria's account the same way, until it had a login of its own, and Part IV gives this worker its own identity. Where readers' rights differ, give the schedule its own sign-in, a person account made for reports with the narrowest scopes, and its own vault.
How are scheduled runs checked for people who left?
A scheduled run does not pass through the portal's session start, so the portal's hourly reconcile job checks every person whose vault a schedule uses, and archives the vault of anyone no longer a member (Lab Task 17). That leaves a gap of up to an hour, closed from the other side: removing a person withdraws their grant (22.11), so the platform's next attempt to renew their token is refused, and the run fails then at the latest (22.14).
At work. In Lab 22, Task 17, Claude Code adds a webhook receiver to the portal in staging. It sends a real webhook, then the same one again, and shows the second was skipped. It sends one with a changed body, and shows the signature check refused it. In Task 18, it writes the morning triage schedule, 10 7 * * 1-5 in America/New_York, with a budget of $0.50 a run, and the portal records a second run on the same day as a repeat.
The operating rule: give every schedule a time zone and a budget, and make every result safe to receive twice. Check each webhook, skip repeats, fetch the current state, and reconcile on a timer.

Figure 22.21. A schedule in a named time zone, and a webhook that is checked, deduplicated, fetched and reconciled.
Check yourself
Question 1 / 8
0 answered
Which cron expression means 7:10 on Monday to Friday?
- Owner
- Panaversity