A generic notifications module for Viam. Each model is a generic service
that accepts a free-form payload via DoCommand and delivers it to some
destination. The module is built to grow: the Slack model ships today, and
email / SMS / other backends can be added as additional models without changing
the calling convention.
All models share one contract (see notify/notify.go):
DoCommandaccepts an optional"command"key (defaults to"send")."react"adds an emoji reaction to a previously-sent message on backends that support it.- The remaining keys are the message payload, interpreted by each backend.
- On success a non-nil result map is returned (at minimum
{"ok": true}).
cmd/module/main.go module entrypoint — registers every model
notify/notify.go shared Sender interface + DoCommand dispatcher
models/slack/slack.go viam:notifications:slack
models/<name>/<name>.go future backends (email, sms, ...)
This module provides the following model(s):
viam:notifications:slack— post a message to a Slack channel.
A generic service that posts a message to Slack. It supports two delivery modes, selected by which credential you configure:
- Bot token (
bot_token) — posts via Slack'schat.postMessageAPI. Lets eachDoCommandchoose the channel and reply in threads. - Incoming webhook (
webhook_url) — simpler, but the destination channel is fixed by the webhook.
Configure exactly one of bot_token or webhook_url.
{
"bot_token": "xoxb-your-slack-bot-token",
"default_channel_id": "C0123456789"
}or, using an incoming webhook:
{
"webhook_url": "https://hooks.slack.com/services/T000/B000/XXXX"
}| Name | Type | Inclusion | Description |
|---|---|---|---|
bot_token |
string | Required (one credential) | Slack bot OAuth token (xoxb-...). Posts via chat.postMessage. |
webhook_url |
string | Required (one credential) | Slack incoming webhook URL. Channel is fixed by the webhook. |
default_channel_id |
string | Optional | Channel ID used when a DoCommand omits channel_id (bot token only). |
Send a message by calling DoCommand. The optional command key defaults to
"send", so it can be omitted.
| Key | Type | Description |
|---|---|---|
text |
string | Message text. Required unless blocks is provided. |
blocks |
array | Slack Block Kit blocks, passed through. |
channel_id |
string | Slack channel ID. Overrides default_channel_id (bot token only). |
thread_ts |
string | Timestamp of a parent message to reply in-thread (bot token only). |
Simple text message:
{
"channel_id": "C0123456789",
"text": "Deployment finished successfully :white_check_mark:"
}Block Kit message in a thread:
{
"channel_id": "C0123456789",
"thread_ts": "1700000000.000100",
"text": "Build failed",
"blocks": [
{
"type": "section",
"text": { "type": "mrkdwn", "text": "*Build failed* on `main`" }
}
]
}On success the command returns:
{ "ok": true, "ts": "1700000000.000200", "channel": "C0123456789" }(ts and channel are populated for the bot token path; the webhook path
returns just { "ok": true }.)
Add an emoji reaction to an existing message with {"command": "react", ...}.
This requires a bot token (the webhook path cannot react). The message is
identified by the same keys send returns (ts and channel), so you can hand
the send result straight back with a name added.
| Key | Type | Description |
|---|---|---|
name |
string | Emoji name without colons, e.g. white_check_mark. Required. |
ts |
string | The target message's timestamp, as returned by send. Required. |
channel |
string | Channel ID the message is in. Defaults to default_channel_id. |
{
"command": "react",
"channel": "C0123456789",
"ts": "1700000000.000200",
"name": "white_check_mark"
}Returns { "ok": true }. An already_reacted response from Slack is treated as
success, so re-issuing the same reaction is idempotent.
The generic design means a new backend (email, SMS, etc.) is a small, isolated addition:
- Create
models/<name>/<name>.gowith aConfig, aNewconstructor, and aninit()that callsresource.RegisterService(generic.API, Model, ...). - Implement the
notify.Senderinterface (Send(ctx, payload)), and haveDoCommanddelegate tonotify.HandleDoCommand. Optionally implementnotify.Reactor(React(ctx, payload)) to support the"react"command; backends that don't report"react"as unsupported. - Register the model in
cmd/module/main.goby adding oneresource.APIModel{API: generic.API, Model: <name>.Model}line.
The notify.HandleDoCommand dispatcher and the "send" command convention are
shared automatically, so callers use every backend the same way.
make setup # go mod tidy
make # build bin/notifications
make test # go test ./...
make lint # gofmt -s -w .
make module # test + build module.tar.gz for uploadThe module is registered at https://app.viam.com/module/viam/notifications and
deployed via the GitHub Actions workflow in
.github/workflows/deploy.yml on tagged releases.