Slack
Use agents in Slack threads and review tool calls with Approve and Deny buttons. For HTTP delivery, the daemon needs a public HTTPS address. For local testing, use Socket Mode.
Set up
Section titled “Set up”-
At api.slack.com/apps, choose Create New App › From a manifest. Paste the manifest below, with
agents.example.comchanged to the daemon's address. Slack will verify the URL after you start the configured daemon in step 6. -
Choose Install to Workspace, then copy the Bot User OAuth Token (
xoxb-...). Under Basic Information › App Credentials, copy the Signing Secret. -
Store both:
echo "xoxb-..." | wardrik vault put SLACK_BOT_TOKEN --for api_keyecho "..." | wardrik vault put SLACK_SIGNING_SECRET --for signing_secret -
Add the channel to
config.yaml. Changeacme.comto your email domain, andacmeto your org:~/.config/wardrik/config.yaml channels:slack:type: slacktoken: ${SLACK_BOT_TOKEN}signing_secret: ${SLACK_SIGNING_SECRET}domains: {acme.com: acme} -
Restart the daemon, and check the channel:
wardrik stop && wardrik startwardrik doctor -
In the app's Event Subscriptions, choose Retry next to the request URL.
-
List the channel in the agent's file:
channels: [slack] -
In a Slack channel, run
/invite @Wardrik.
display_information: name: Wardrik description: Agents that answer in threads, and ask before they act.features: app_home: home_tab_enabled: false messages_tab_enabled: true messages_tab_read_only_enabled: true bot_user: display_name: Wardrik always_online: trueoauth_config: scopes: bot: - channels:history - channels:read - chat:write - chat:write.public - groups:history - groups:read - reactions:write - users:read - users:read.emailsettings: event_subscriptions: request_url: https://agents.example.com/v1/channels/slack/events bot_events: - app_uninstalled - channel_left - group_left - member_joined_channel - message.channels - message.groups - tokens_revoked interactivity: is_enabled: true request_url: https://agents.example.com/v1/channels/slack/actions org_deploy_enabled: false socket_mode_enabled: false token_rotation_enabled: falseslackin each URL is the channel's name inconfig.yaml: lower-case letters, digits and-.- See all settings in config.yaml › channels.
Members
Section titled “Members”Map Slack members to Wardrik users to control access. Each member uses the mapped user’s permissions. See built-in rules.
-
domainsmaps an email domain to an org.[email protected]acts asuser:acme/@maria. -
membersmaps one member ID to a user, and wins overdomains. Copy the ID from the member's Slack profile (Copy member ID):members: {U024BE7LH: user:admin} -
Unmapped members receive an access-denied message directing them to an admin.
-
Members of other workspaces, over Slack Connect, are matched by
membersonly.
Testing with Socket Mode
Section titled “Testing with Socket Mode”Socket Mode needs no public address. It's for testing.
-
In the manifest, set
socket_mode_enabled: trueand remove bothrequest_urllines. -
Under Basic Information › App-Level Tokens, create a token with
connections:write(xapp-...). Store it asSLACK_APP_TOKEN. -
In
config.yaml, setapp_tokenin place ofsigning_secret:channels:slack:type: slacktoken: ${SLACK_BOT_TOKEN}app_token: ${SLACK_APP_TOKEN}domains: {acme.com: acme}
Use a separate app per daemon. Slack spreads events across all of an app's connections.
In a channel
Section titled “In a channel”:wave: books answers here now.
[Answer every message][⋯]
- With one agent available, it replies when mentioned. Answer every message makes it reply to each message, in its own thread.
- With several, the bot posts a button per agent. With none, it posts how to make one available.
- ⋯ has Use another agent and Stop answering here. Removing the bot also unbinds the channel.
- A channel is available to the deployment's org, unless
orgsassigns it to another.
Threads
Section titled “Threads”maria: @Wardrik how much Barolo is left? :eyes: ↳ Wardrik: Two cases, both 2019.
- Mention the bot to start a thread. Replies in the thread need no mention.
- Each thread is a conversation, such as
conversation: "slack.T0123.C024BE91L.1696.1234". Threads share the agent's definition and files. - Every channel an agent answers in shares its files and digests. To keep a private channel's work out of a public one, give each its own agent.
- :eyes: means the agent received the message. :white_check_mark: means it replied.
- The thread's status shows the agent's current activity.
- To post notices in a channel, set
notify: "slack:#updates". See Send notifications.
Approvals
Section titled “Approvals”A pending call shows its tool, the policy message and its arguments, with Approve, Deny and a note field. Once resolved, the buttons are replaced with the result:
Denied
deployby @jon: Deploy to staging first, and show me the diff.
Who approves
Section titled “Who approves”The member who started the turn can always approve its calls. Anyone else needs a binding (see Who can approve):
roles: approver: {rules: [{verbs: [approve, deny, decide], kinds: [agent], names: [books]}]}bindings: - {org: acme, role: approver, subjects: [user:acme/@maria]}Scheduled and webhook-triggered turns have no initiating Slack member. Use a CLI admin approval or grant an approver role to the Slack users who should review them.
The app doesn't reply
Section titled “The app doesn't reply”If the app was invited while the daemon was down, /remove @Wardrik and invite it again. Then
check:
- Event Subscriptions shows the request URL as verified;
wardrik doctorverifies the tokens with Slack;wardrik logs.
If a member is denied access, check their Slack email domain or add their member ID to members.