Triggers & scheduling
Let an org react to the clock and the outside world — schedules, inbound webhooks, and process watchers that each seed a goal.
Without triggers an org is sealed: it advances its mission on a fixed tick
and on directives you type into the dashboard. A ## Triggers section in your
QUORUM.md opens it up — so it reacts to the clock and to inbound events, in
service of that same mission. A fired trigger seeds a goal, exactly like an
operator message, and flows through the normal cycle.
One ### heading per trigger (the heading is its name); the prose is the
directive it seeds when it fires. The kind is inferred from the fields you
give it.
## Triggers
### Weekly review
- every: 7d
Review progress against the mission and decide the single most important thing
to ship next week.
The three kinds
Schedule — react to the clock
A schedule trigger declares exactly one of:
| field | fires |
|---|---|
every | on a fixed recurrence since it last fired — 45s, 30m, 6h, 7d, 2w (and once immediately on first evaluation) |
cron | when local wall-clock time matches a standard 5-field expression min hour dom mon dow — supports *, a number, ranges a-b, lists a,b, and /n steps |
at | once, at or after a single ISO datetime — a one-shot future commitment |
### Monday planning
- cron: 0 9 * * 1
Kick off the week: re-plan the top goal and rebalance work across the team.
### Attend the 3pm call
- at: 2026-07-06T15:00:00
Join the scheduled customer call and capture the decisions and follow-ups.
The one-shot at kind is the primitive for time-bound commitments — book a
meeting for later, and the org shows up on time. Firing latency is bounded by the
cycle interval (--tick, default 10s), which is fine for schedules and meetings.
Webhook — react to an inbound event
A trigger with no schedule or command (or an explicit kind: webhook) is fired
by an external request to POST /api/trigger/<name>:
### Inbound signup
- kind: webhook
A new signup arrived. Qualify the lead, add it to the CRM, and line up a
conversation to validate pricing.
curl -X POST http://your-host:3000/api/trigger/inbound-signup \
-H "X-Quorum-Secret: $QUORUM_TRIGGER_SECRET" \
-H "content-type: application/json" \
-d '{"text": "acme.co — 40-seat team, from the pricing page"}'
The endpoint is fail-closed. It does nothing unless you set a shared secret
in the QUORUM_TRIGGER_SECRET environment variable, and every call must present
it — as an X-Quorum-Secret header or Authorization: Bearer <secret> (compared
in constant time). It’s also only reachable when you bind the dashboard beyond
loopback (--host 0.0.0.0); by default it listens on 127.0.0.1 only.
Crucially, the caller can’t inject instructions. Only the trigger’s own
configured directive is seeded; an optional {"text": "..."} body is attached as
context. So even an exposed endpoint can’t steer the org off its mission.
Process watcher — react to a job finishing
A trigger with a command runs that shell command and watches it. When the
process exits, the trigger fires — carrying the exit code and a tail of its
output as context, so the org can act on the result.
### Deploy finished
- command: ./scripts/wait-for-deploy.sh
Review the deployment that just completed and log any regressions found.
Watches are re-established on every start, so a restart re-arms them.
Agents schedule themselves
Triggers aren’t only author-declared. While working a task, an agent can book a future goal itself by adding a line to its output:
SCHEDULE[2h]: Attend the customer call and capture the decisions
<when> may be a delay (2h, 30m, 3d), an absolute time
(at 2026-07-06T15:00), or a recurrence (every 7d). It’s written as a
persisted schedule trigger, so it fires at its moment even across restarts.
This is how the org commits to real, time-bound obligations on its own — arrange
a call now, and it seeds the goal to attend when the time comes, rather than
assuming the same process is still running. It’s the same output-marker pattern
as HIRE[...] and DELEGATE[...], and it’s gated by the schedule
capability (deny it to lock self-scheduling down).
Keys
| key | meaning |
|---|---|
every / cron / at | schedule (pick one — see above) |
command | process: the shell command to run and watch |
kind | force schedule, webhook, or process (usually inferred) |
enabled | false keeps a trigger defined but dormant (default true) |
directive | the seeded directive, as a key instead of the prose body |
name | the trigger’s name (default: the heading); a webhook fires at POST /api/trigger/<name> |
Lifecycle
Triggers are persisted with their firing history, so editing ## Triggers and
restarting takes effect immediately without re-firing what already ran. Each
firing is recorded in the audit log and shown on the dashboard’s
Triggers panel — name, kind, schedule, and how many times it has fired.