Scheduling
Wrap any preset in a JobSchedule and fire it on cron. Each fire runs CreateJobUsecase, which materializes a fresh Job through the preset’s server-side step resolution — so multi-step presets just work.
Create a schedule
Section titled “Create a schedule”Via the SDK:
await client.jobs.createSchedule({ slug: 'daily-triage', preset: 'gmailTriage', cron: '0 7 * * *',})Or directly: POST /api/jobs/schedules. Names are namespaced server-side as {userId}.{slug}.
Overlap policy
Section titled “Overlap policy”The policy is skip-if-previous-still-running. On each tick the worker checks IJobRepository.findInFlightBySchedule and skips the fire if the prior run hasn’t finished. This prevents two writers racing one export target.
POST /api/jobs/schedules/:name/run (SDK: runScheduleNow(slug)) is the only intentional bypass — don’t add others.
Managing schedules
Section titled “Managing schedules”await client.jobs.listSchedules()await client.jobs.getSchedule('daily-triage')await client.jobs.runScheduleNow('daily-triage')await client.jobs.deleteSchedule('daily-triage')Internally, read-based presets keep a per-source ingestion watermark so each run advances from where the last one stopped instead of re-reading a fixed window. The watermark is a server-side mechanism with no SDK/API surface.
