Skip to content
agentic-pipelines

Notifications

A pipeline says when it notifies in its notify block, and through which channel. Channels are declared once, in the data repo's pipelines.yaml, and belong to the data repo, not the engine. The only channel type today is shell: a channel is a command, usually a script in scripts/, and it does whatever that script does.

The notify block

yaml
notify:  on: [success, failed]  stale_after: 72h  channel: email
FieldTypeNotes
onlist of success, failed, skippedEvery path that closes a run notifies, including a skipped guard and a busy lock, so skipped really does fire. Beware of noise: a pipeline with throttle skips half the nights by design. For "it isn't running", stale_after is the better tool.
stale_afterduration (72h)Optional. Notifies when the pipeline has gone that long without a single successful run, whatever the status of the current run. A pipeline that has never succeeded counts as stale from its first run. It warns on every run while that holds, and switches itself off as soon as the pipeline runs green again.
channelstringMust exist as a key under channels: in pipelines.yaml. validate checks it.

Why stale_after matters

on: can't tell a routine skip from a stalled pipeline. In practice a pipeline can spend many nights skipping because of a broken guard without anyone noticing. Declaring a stale_after window somewhat larger than the pipeline's throttle turns that silence into a warning.

The linter makes it mandatory: a pipeline with triggers: and notify: but without notify.stale_after fails validate (rule R4, see Surviving the night).

stale_after can only speak when a run happens. A job that has stopped firing altogether produces no run to evaluate; for that, check the dashboard's overview.

Declaring a channel

In pipelines.yaml, at the root of the data repo:

yaml
channels:  email:    type: shell    env: [SMTP_PASSWORD]    run: scripts/notify-email.sh
Channel fieldTypeRequiredNotes
type"shell"yesThe only type supported today.
runstringyesThe command to run.
envstring listnoNames of the secrets this channel needs. They are resolved only when the channel is actually invoked, and never exposed to the pipeline that triggered the notification.

What the script receives

The channel's command runs with these environment variables, plus the secrets declared in its env::

VariableValue
PIPELINES_NOTIFY_NAMEThe pipeline's name.
PIPELINES_NOTIFY_RUN_IDThe run id.
PIPELINES_NOTIFY_STATUSThe run's status.
PIPELINES_NOTIFY_REASONThe guard that skipped the run or, if the run failed, the failed steps with their error, truncated to 500 characters.
PIPELINES_NOTIFY_STALE1 or empty.
PIPELINES_NOTIFY_LAST_SUCCESSISO timestamp of the last successful run, empty if there was none.

Like a shell step, a channel gets a narrow, fixed environment, never the whole environment of the process. It never receives your Anthropic API key.

After the run, pipelines show <name> <run-id> includes a notify entry with the channel, its exit code, the timestamp and the redacted tail of its output, also when the channel failed.

On a server

A server has no desktop notifications, so use a channel that goes out over the network: for example, a script that posts to ntfy with the topic in the data repo's .env (NTFY_TOPIC=a-long-hard-to-guess-name). The topic works like a secret: don't put it in the YAML or in a repo.

The starter's channels

pipelines-starter comes with three channels in its pipelines.yaml:

  • default, what every starter pipeline uses: a macOS notification on a Mac, and a push through ntfy on any other machine. On a Mac it works with no setup (the first time, macOS may ask you to allow notifications for Script Editor). Elsewhere it needs NTFY_TOPIC in .env; without it, the notification fails and says so.
  • macos: always a macOS notification with the first line of the report.
  • ntfy: a push notification on your phone with the full report. Install the ntfy app, subscribe to a long, hard-to-guess topic name, put it in .env as NTFY_TOPIC=..., and change channel: default to channel: ntfy in the pipelines you want on your phone (also from a Mac).

Written from agentic-pipelines at b8b4db7: README.md, docs/reference.md; pipelines-starter at 0b4f303: README.md.