Schedules
Run an agent on a cron schedule, in any time zone, without double runs.
A schedule starts a run of a host agent at each cron occurrence: a daily digest, a nightly cleanup, a weekly report.
const app = host({
store: sqlite(".threads"),
agents: { support },
schedules: [
{
id: "daily-digest",
agent: "support",
cron: "0 9 * * 1-5",
timezone: "Europe/Berlin",
input: "Summarize yesterday's open tickets.",
},
],
});Schedules start firing after ready(), which threads dev and threads start call for you.
Fields
idstringrequiredA stable name for the schedule. Keep it the same across deploys.
agentstringrequiredA key of the host's agents.
cronstringrequiredFive fields: minute, hour, day of month, month, day of week. Supports *, lists (1,15), ranges (1-5) and steps (*/15). Sunday is 0 or 7.
timezonestringdefault UTCAn IANA time zone such as America/New_York.
inputstring | InputPart[]requiredWhat each run starts with.
Guarantees
- One run per occurrence. Each occurrence is claimed in the store before its run starts, so two hosts on the same store, or a restart right at the boundary, never run it twice.
- No catch-up storms. Occurrences that fell due while the host was down are skipped, not run late.
- Daylight saving. A local time skipped by a spring-forward runs at the first valid minute after it; a time repeated by a fall-back runs once.
- A bad cron expression, an unknown time zone or an unknown agent fails
ready()with aConfigError.
Threads per schedule
The two languages differ here today. In TypeScript, a schedule keeps one thread and each occurrence continues it; an occurrence that falls due while the previous run is still going is skipped. In Python, each occurrence starts a new thread.
Scheduled runs belong to the local tenant and are recorded with the schedule as the caller, so the timeline shows which schedule started each run.