Schedule
Say when the work should run in plain terms. Use the same schedule for gates, eval monitors, and reports. Drop to cron only when you need it.
Status: Beta Companion docs: Release gates · Evals onboarding · The closed loop Source of truth: Test suites API · Evals API · Reports API.
Start with the cadence you mean
from trinitite import Schedule
nightly = Schedule.nightly()
every_six_hours = Schedule.every("6h")
monday_morning = Schedule.weekly(on="mon", at="09:00")
Schedule turns a readable cadence into the five-field cron used by the job runner. Your app does not need to build cron strings for common cases.
Use named constructors
| Constructor | Meaning |
|---|---|
Schedule.every("45m") | Every 45 minutes |
Schedule.hourly() | Every hour at minute zero |
Schedule.daily(at="02:30") | Every day at 02:30 UTC |
Schedule.nightly() | Daily off-hours preset |
Schedule.weekly(on="mon", at="09:00") | Monday at 09:00 UTC |
Schedule.monthly(on_day=1) | First day of each month |
Schedule.cron("...") | Explicit five-field cron escape hatch |
A bare duration or preset also works on schedule=:
ev.monitor(schedule="nightly", min_pass_rate=0.90)
tr.gate(
scope="refund-flow",
mode="continuous",
schedule="6h",
thresholds={"accuracy": 0.95},
)
A bare cron string does not work. Wrap it with Schedule.cron(...) so the intent is clear.
Set the local time zone
schedule = Schedule.daily(at="02:30").in_tz("America/New_York")
print(schedule.describe)
print(schedule.to_cron)
The time zone is an IANA name. It stays attached to the schedule so daylight-saving changes do not silently shift a local job.
Spread work across a fleet
schedule = Schedule.nightly().with_jitter("5m")
Jitter spreads jobs around the target time. This keeps a large fleet from starting every check at the same second.
Bound a campaign
campaign = (
Schedule.nightly()
.starting("2026-09-01")
.until("2026-11-30")
)
The start and end dates are inclusive. Use a window for a trial, launch period, or fixed audit cycle.
Attach the same type to each surface
schedule = Schedule.weekly(on="mon", at="09:00").in_tz(
"America/New_York"
)
monitor = ev.monitor(
schedule=schedule,
min_pass_rate=0.90,
)
gate = tr.gate(
scope="refund-flow",
mode="continuous",
schedule=schedule,
thresholds={"accuracy": 0.95},
persist=True,
)
The surface decides permissions and behavior. Schedule only describes when it should run.
Where to go next
- Release gates runs the same release rules on a cadence.
- Evals onboarding creates the eval a monitor can repeat.
- The closed loop connects runtime calls, evals, and release checks.