Defining an organization

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:

fieldfires
everyon a fixed recurrence since it last fired — 45s, 30m, 6h, 7d, 2w (and once immediately on first evaluation)
cronwhen 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
atonce, 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

keymeaning
every / cron / atschedule (pick one — see above)
commandprocess: the shell command to run and watch
kindforce schedule, webhook, or process (usually inferred)
enabledfalse keeps a trigger defined but dormant (default true)
directivethe seeded directive, as a key instead of the prose body
namethe 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.