Skip to content

Sentinel agent

packages/sdk/examples/sentinel-bot.ts posts uptime incidents from Sentinel into a channel. It is the shape most useful integrations take: a deterministic event, formatted well, in the right room.

There is no model in it. Sentinel already knows what is down. Asking an LLM to restate that would add latency, cost, and a chance of being wrong about a fact it was handed. Add a model when you want to ask things (“what has been flapping this week?”), not to relay them.

Terminal window
SLICK_URL=https://chat.example.com SLICK_TOKEN=slk_… \
SLICK_CHANNEL=01J… \
SENTINEL_URL=https://sentinel.rootstuff.io SENTINEL_TOKEN=… \
pnpm --filter @slick/sdk exec tsx examples/sentinel-bot.ts

Without SLICK_CHANNEL it looks for #ops, #alerts, #incidents, then #general, so the common case needs no id.

sentinel
www.modwash.com is down
HTTP 504 - Could not fetch page content
started 21:53 UTC · incident 9001
└ 1 reply

The recovery goes in the thread, not the channel. One incident, one thread, so the channel stays a list of events rather than a stream of noise.

Real monitoring data is full of incidents that open and close inside a minute: a 504 that clears on the next check, one SSL handshake that times out. Posting each one turns the channel into noise, and a noisy channel gets muted, which costs you the alert that mattered.

So a new incident is held for MIN_DURATION_SECONDS (default 60) before it is announced. If it resolves first, nobody hears about it. Set it to 0 to announce everything.

Variable Default Meaning
POLL_SECONDS 30 How often to ask Sentinel for ongoing incidents
PORT unset Set it to also accept webhook POSTs
SENTINEL_WEBHOOK_SECRET unset HMAC-SHA256 over the raw body, compared in constant time
MIN_DURATION_SECONDS 60 Flap suppression, above
SENTINEL_STATE ./.sentinel-bot-state.json Which incidents have been announced

Polling is the default because it needs no inbound connectivity, and a self-hosted bot is usually behind NAT with no public URL. Webhooks are faster if you can expose a port.

The state file is what stops a restart reposting last week’s outages, and what lets a recovery find its thread. Keep it on a volume that survives restarts.

This is a template more than a product. The pattern transfers to anything with an API and events worth hearing about: poll or receive, suppress the noise, post once, reply in the thread. See Bots and agents for the API it is built on.