no_change and spend zero tokens.
Quick Start
1
Watch a source
Point
monitor at a cheap source. Each tick probes it, hashes the output, and only runs the model on a change:2
Pin the model for unattended runs
An unattended job created against a cheap default should not silently follow a later, pricier one — snapshot the model and pin it:
Which Gate Should I Use?
Four distinct controls decide whether — and how — a scheduled tick runs.Run Statuses
A monitor tick records exactly one status so operators can tell “unchanged” apart from “gate said skip”.no_change is distinct from skipped on purpose: it means “the watched source did not change”, not “the gate said don’t run”.
Model-Free Delivery Action
Setcommand to run a shell command on schedule and deliver its stdout verbatim — no agent, no LLM call.
command_timeout, and that tick is recorded as failed — a hung command can never stall the ticker.
Custom Stateful Gates
ImplementJobConditionProtocol.should_run to build your own change-detection gate. A stateful gate accepts the job’s prior state and returns a GateResult that both suppresses an unchanged source and carries the next-tick hash.
no_change=True, GateResult forces run=False in __post_init__, so a gate can never fire a tick the contract defines as suppressed. Leaving state_updates=None writes nothing — an error probe leaves prior state untouched so a later recovery still suppresses.
Custom State Stores
ImplementJobStateStoreProtocol to persist a job’s per-tick scratchpad — a last-seen hash, a cursor, or a watermark.
hasattr() and treat absence as today’s stateless behaviour.
Configuration Options
Fields onScheduleJob that drive monitor mode and model pinning.
GateResult fields for stateful gates:
Best Practices
Use monitor for change-detection, pre_run for go/no-go
Use monitor for change-detection, pre_run for go/no-go
monitor carries per-job state and records no_change; pre_run is a stateless gate that records skipped. Reach for monitor when you need to compare against the last tick, and pre_run when a cheap check answers “is there anything to do right now?”.Pin the model on unattended jobs
Pin the model on unattended jobs
Unattended runs fire with no human present. Snapshot
provider and model and keep pin_model=True so a job created against gpt-4o-mini never silently inherits a later, pricier default.Bound every command with command_timeout
Bound every command with command_timeout
A model-free
command job runs a real shell command. Keep command_timeout tight so a hung command is killed (with its process group on POSIX) and recorded as failed instead of stalling the ticker.Leave state untouched on probe errors
Leave state untouched on probe errors
When a probe fails, return a
GateResult with state_updates=None so prior state is preserved. A later recovery to the same output still hashes equal and suppresses, avoiding a spurious change alert.Related
Async Scheduler
Multi-tenant, at-most-once scheduling primitives
Pre-Run Gate
Stateless go/no-go gate that skips quiet ticks

