foldrun.docs
Browse docs

Docs/Running it

Notifications

An agent that runs while the laptop is closed needs a way to say “I finished”, “I failed”, and above all “I am waiting for you”. A run parked at an approval nobody hears about is a run that never happens. Notifications are one destination — an email address or a webhook URL — declared once in AGENTS.md, and a short list of the events that should reach it.

Declaring one

notify:
  email: [email protected]
  events: [failed, awaiting-approval, completed]

or, for people who live in a channel rather than an inbox:

notify:
  url: ${SLACK_WEBHOOK_URL}        # a secret name, or a literal URL
  events: [failed, awaiting-approval]

A bare string is whichever destination it looks like: notify: [email protected].

The default events are failed and awaiting-approval. completed is opt-in on purpose: a schedule that works is the quiet kind of good news, and a channel that pings on every success gets muted — which un-pings the failures too. Turn it on when the run’s headline is the thing you want to read each morning, which for a scheduled desk it usually is.

Where it is set, and the rule that bites

notify: lives in the account’s AGENTS.md and every workspace inherits it. A workspace may declare its own — and when it does, its block replaces the account’s whole, it does not merge. A workspace that wants the account’s destination and events simply says nothing.

What arrives

The subject is the run’s headline — the first line of the last step’s reply — followed by its summary. Ids and costs are in the body. The subject is meant to be read on a phone: “BAD — 3 targets fell out of the top 20” is the whole message; “run-mtmv20up-oote completed” is not.

The body, and the webhook’s JSON:

{
  "text": "BAD — 3 targets fell out of the top 20 · rank-desk/run-… · $1.01",
  "workspace": "rank-desk", "runId": "run-…", "flow": "rankings",
  "status": "completed", "summary": "…", "costUsd": 1.01,
  "startedAt": "…", "finishedAt": "…",
  "approveUrl": "…", "rejectUrl": "…"
}

text is what Slack, Discord and ntfy render as-is; the rest is for anything that wants the data. A webhook URL is the one integration: those services, and every phone-push relay, all accept a POST of that shape.

A run parked on a person sends its notification with two links. Clicking one opens a page that shows what is waiting and asks for the decision — it never decides on the GET, because inbox link-checkers follow links. The token in the link is derived from the run, never stored, so a key rotation kills every old link at once.

The links exist only when the install knows its own public address (FOLDRUN_PUBLIC_URL). Without it the notification goes out without them and the run is approved from the dashboard.

Email

Email goes through the account’s Resend connection (RESEND_API_KEY), the same one the platform’s own email tool uses. There is nothing to configure beyond the address.