Set up the Feishu app
At the end of this page, alerts arrive as cards in a Feishu (or Lark) group. The configuration:
feishu:
app_id_file: /etc/beacon/secrets/feishu-app-id
app_secret_file: /etc/beacon/secrets/feishu-app-secret
domain: feishu # or lark
callback: websocket # or http, with verification_token_file (and encrypt_key_file)
chat_id: oc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
on_call: # only they may act on cards; they are buzzed
- {open_id: ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, name: Alex} # the name is shown on cards
monthly_budget: 10000 # the app's API calls per month (see Quota)
webhook_url_file: /etc/beacon/secrets/feishu-webhook-url # the custom bot
webhook_keyword: BeaconA card says what is wrong, since when, which locations fail and why, and what agents have noted, and it changes in place as the alert does, turning green when it resolves. The people on call acknowledge and silence it with its buttons; a critical alert nobody acknowledges buzzes them in the app after 10 minutes. A custom bot in the same group carries plain messages that cost no API quota. You need to create a self-built app in your organisation, which an administrator approves; the steps take a quarter of an hour, the approval as long as your organisation takes.
Beacon sends cards through a self-built app and receives its button clicks. A group's custom bot alone cannot do this: its messages have no callbacks and cannot be updated. It is still useful beside the app, for plain messages: alerts of severity info, alerts once the app's monthly budget runs low, and the echoes of what people and agents do.
Create two apps, one for production and one for testing (for example "Beacon" and "Beacon Dev"). Feishu hands each callback to one connection only, so a test instance using the production app would take clicks away from production.
1. Create the app
- In the Feishu open platform (or Lark's, and then
feishu.domain: lark), create a custom app for your organisation. - Under Add features, add Bot.
- Under Credentials & basic info, note the App ID and App Secret. They go into the files that
feishu.app_id_fileandfeishu.app_secret_filename (step 5).
2. Permissions
Under Permissions & scopes, enable:
| Permission | For |
|---|---|
Send messages as an app (im:message:send_as_bot) | Sending cards to the alert chat |
Read and update messages sent by the app (im:message or im:message:update) | Updating a card in place |
Send urgent messages in app (im:message.urgent) | Buzzing the people on call |
If the console names them differently, look for the permissions behind the APIs "send message", "update app message card" and "buzz a message in app".
3. Callbacks
Under Events & callbacks → Callback configuration, choose how the clicks reach Beacon:
- Long connection (recommended;
feishu.callback: websocket, the default): choose "Receive callbacks through a persistent connection". Beacon connects out to Feishu, so it needs no public URL. Then add the callback Card action (card.action.trigger). - HTTP (
feishu.callback: http): set the request URL tohttps://<your host>/hooks/feishu, and put the Verification Token (and the Encrypt Key, if you turned encryption on) in the files thatfeishu.verification_token_fileandfeishu.encrypt_key_filename. Then add Card action.
Add card.action.trigger on the callback tab, not the event tab: the old card callback does not travel over the long connection.
4. Publish
Create a version and publish it; an administrator approves it in the admin console. Permission changes take effect only in a published version, so publish again after changing them.
5. The alert chat
- Create a group (for example "Alerts") and add the people on call.
- Add the app's bot to the group (group settings → Bots → Add bot).
- Find the group's
chat_id(oc_…), for example with the API explorer's "get chat list", called as the app. - Find each on-call person's
open_id(ou_…) for this app. Only these people can act on cards, and they are the ones buzzed. - Add a custom bot to the same group. Under its security settings, choose a keyword (
Beaconunless you setfeishu.webhook_keyword) and/or a signature (its secret goes in the filefeishu.webhook_secret_filenames). Copy its webhook URL.
Put each secret in its file (in the reference deployment, under /opt/beacon/secrets/, which install.sh gives owner 65532 and mode 0400), and the rest in Beacon's configuration: the block at the top of this page, with the chat_id from step 3 and the open_ids from step 4.
beacon check-config refuses an app without chat_id or without at least one person in on_call, an open_id that does not start with ou_, and an HTTP callback without its verification token.
6. Check it
Restart Beacon so that it reads the new configuration (docker compose restart beacon in /opt/beacon for the reference deployment), then check, in this order:
docker exec beacon beacon check-config # configuration OK: Feishu app true, …
docker logs beacon 2>&1 | grep 'feishu long connection'
curl -s http://127.0.0.1:17001/readyz # on the centre: {"not_ready":null,"ready":true}
docker exec beacon beacon drill fail 15m- The log has
feishu long connection readywithin seconds of the start (withcallback: httpthere is no such line). If it is missing, or saysfeishu long connection lostorerror: check the App ID and App Secret in their files, that the app's version with the bot and the permissions is published and approved, and that the callback is set to the persistent connection. /readyzanswers 503 with the reasons when alerts cannot reach people: "the Feishu long connection is down", "a Feishu API call failed in the last 10 minutes", "the Feishu API budget for this month is used up", or that the rule engine's Watchdog has not arrived.GET /api/v1/bridge(MCPstatus_summary) says the same to a token withstatus:read, with the calls used this month.- The drill makes
/drill/healthzfail. Once your probe locations see it and the alert fires (4 to 5 minutes with two locations), a card arrives in the group. Acknowledge it, silence it, then rundocker exec beacon beacon drill offand watch it turn green. - A click that answers "Only the people on call can act on alerts" came from someone whose
open_idis not infeishu.on_call, or whoseopen_idwas taken from another app: anopen_idis per app. Clicks Beacon never hears of (the card stays as it was, and the audit log has no entry with viafeishu) are going elsewhere: to a test instance running with the production app, or nowhere, whencard.action.triggerwas added on the event tab instead of the callback tab.
Quota
On the free plan, all of an organisation's custom apps share a monthly API call limit (10,000 calls when this was written; check your console). Sending a card, updating it through the API and buzzing each cost one call; a card updated by a click costs nothing. A note left through the API or MCP, and an agent woken for the alert, each update the card through the API, until 90% of the budget is used. Set feishu.monthly_budget to your limit (the month is counted in the configuration's timezone):
- above 70% of it, only critical alerts use the app, and the rest go to the custom bot;
- from 90%, cards are no longer updated through the API, except to show that an alert resolved;
- at 100%, nothing goes through the app until the month ends, and
/readyzsays so.
Phone and SMS buzzes need a verified organisation; Beacon uses only the in-app buzz and escalates to Pushover instead. By default (escalation.critical), a critical alert nobody has acknowledged is buzzed after 10 minutes and, once Pushover is configured, sent at Pushover's emergency priority after 15.