Schedule and distribute work
Use this when you want work to run without you watching: on a schedule, backed by a durable engine, and spread across more than one machine.
Before you begin
Section titled “Before you begin”- Build a Barry. These commands act as the
bonanzaidentity from that guide; use your own identity’s command in its place. - Have a bag you own, with the action you want to run.
- To run work on another machine, install Barry on that machine too.
Schedule an action
Section titled “Schedule an action”A schedule fires an action on a trigger. A bag declares its schedules in
bag.yaml, each naming a trigger and what to run:
schedules: nightly-triage: every: 1d action: triage-alert traits: [debug]A schedule needs exactly one trigger and exactly one thing to run. The triggers are:
| Trigger | Fires | Example |
|---|---|---|
every |
On an interval, one of 1m, 5m, 15m, 30m, 1h, 1d |
every: 1h |
cron |
On a five-field cron expression, read in UTC unless you set timezone |
cron: "0 9 * * 1" |
at |
At one ISO-8601 time with an explicit offset, or once per login with at: login |
at: "2026-11-02T09:00:00-05:00" |
What runs is one of action (a reference such as slack:weekly-digest, or an
inline action body), job (one of the bag’s jobs), or entry (a script).
A schedule receives only what it names. Set identity to choose whose keys and
default harness an agent action uses, and traits and bounds to choose what
it can do; a schedule with no identity must name its traits. You can also
set inputs, overlap (skip or queue), catch_up (once, the default,
runs a fire missed while the machine was off on return; none skips it), and
enabled: false to keep a schedule declared but off. timeout belongs to a
script entry alone; an action or a job sets its own.
See and control schedules
Section titled “See and control schedules”bonanza schedule listbonanza schedule show sessions/reaperlist shows each schedule with its next and last fire and whether the
scheduler is alive. A schedule’s ID is <bag>/<name>. To act on one:
| Command | Effect |
|---|---|
bonanza schedule run <id> |
Run its action now, outside the trigger |
bonanza schedule pause <id> |
Stop it firing until resumed |
bonanza schedule resume <id> |
Resume it; its next fire counts from now |
bonanza schedule logs <id> |
Print the latest run’s log (-f to follow) |
What makes a run durable
Section titled “What makes a run durable”Barry’s durable workflow runtime backs every scheduled run, so it survives interruptions:
- State, history, and timers commit together, so a run that a restart interrupts resumes where it left off rather than starting over.
- Wall-clock deadlines stay authoritative across restarts.
- Delivery is at least once: a step whose worker crashes or loses its lease is retried, by default up to three times with a growing delay.
You do not configure any of this per schedule; it is how the runtime executes every run.
Run work on another machine
Section titled “Run work on another machine”When your Mac is busy, link another machine as a worker and Barry hands it the jobs. The owner is also its own worker, so steps that can run locally never leave your machine.
The worker advertises what it can run (its jobs, labels, and capacity, default
four concurrent). Barry fans jobs out across connected workers and retries a
job elsewhere if a worker dies. barry workers list shows the workers you
invited and the owners you joined, and barry workers status explains why a
job is or is not offered to a machine.
Trust is one-way and revocable. The owner stores only a hashed credential; the
worker’s credential opens exactly one route and nothing else. Rotate a
worker’s credential with barry workers rotate <worker> (the old one keeps
working for five minutes), or cut it off with barry workers revoke <worker>.
Verify
Section titled “Verify”To confirm the scheduler is alive and sees your schedules, run:
bonanza schedule listWith no schedules declared, schedule list reports the scheduler’s
heartbeat. The output is similar to the following:
● scheduler running (beat 4s ago)
No schedules. Declare them under schedules: in a bag.yaml.Once you install a bag that declares schedules, each one appears by its ID,
with its trigger, its action, and its last and next fire. For a worker, run
barry workers status on it: it lists the worker’s labels and the jobs it
can run for an owner.
If it fails
Section titled “If it fails”- The first line reads
scheduler downorscheduler degraded. The reason follows on the same line. Check the scheduler’s service, and see See what is running. - A line starts with
!. Barry could not load a bag’s schedules; the line names the error. Fix theschedules:block and install the bag again. - A schedule shows
failing. Read its latest run withbonanza schedule logs <id>. - A worker never gets a job.
barry workers statusnames the reason, such as a label the job needs that the worker does not offer.
What’s next
Section titled “What’s next”- Background work for how Barry tracks scheduled runs and jobs as work items.
- Durable workflows for the runtime behind every run.
- Distributed nodes for how owners and workers trust each other.