arizuko › components › slakd
slakd
slakd receives Slack events over the HTTP Events API, posts with the Slack Web API, and drives the assistant pane.
slakd connects Slack to arizuko
slakd connects Slack to arizuko, so the agent can read and reply in Slack channels, DMs and threads.
slakd is the Slack channel adapter. It receives workspace events over the HTTP Events API, which proxyd forwards from /slack/events, and posts with the Slack Web API. For routd, it is a normal channel adapter with the JID prefix slack:. Its JIDs have the form slack:<workspace>/<kind>/<id>, where kind is channel, dm or group.
A direct connection lets slakd drive the assistant pane
Many teams already work in Slack. It is the only platform that arizuko supports with an “Agents & AI Apps” assistant pane: a sidebar with suggested prompts and a conversation title. slakd talks to Slack directly, not through a SaaS gateway. So it can drive that pane and verify the same service:routd ES256 bearer as every other adapter.
slakd sits between Slack and routd
Slack workspace
│ HTTPS Events API webhook
▼
proxyd (forwards /slack/...)
│
▼
slakd (LISTEN_ADDR=:8080; verifies X-Slack-Signature)
│ POST /v1/messages (service:<daemon> ES256 bearer)
▼
routd
│ POST /send (callback to slakd)
▼
slakd (chat.postMessage / files.* / reactions.add)
│
▼
Slack Web API
slakd verifies the X-Slack-Signature HMAC of v0:<ts>:<body> on every webhook and refuses a clock skew of more than 5 minutes. A reaction on Slack becomes a synthetic like or dislike inbound row, classified by chanlib.ClassifyEmoji. A channel message that contains <@bot_user_id> gets verb=mention. DMs and channel messages without an address get verb=message.
The wired verbs are in slakd/bot.go and slakd/server.go: send, send_file, edit, delete, like, dislike and post, and the pane verbs pane_set_prompts and pane_set_title. forward, quote and repost return 501 with a hint.
slakd starts a pane session when the user opens the sidebar
With the assistant:write scope and the assistant_thread_started and assistant_thread_context_changed subscriptions, slakd does four things when a user opens the sidebar. It writes or updates a row in pane_sessions. It sets the title to <ASSISTANT_NAME> — chat. It sets three suggested prompts. It sends a synthetic pane_open inbound message. Prompts and titles that MCP tools set wait until the next chat.postMessage, which applies them.
The core messaging skill tells the agent to use Slack mrkdwn, including *bold*, _italic_ and <url|text>.
slakd runs alone with routd, a Slack app and a public URL
slakd is a plain Go binary. It needs a reachable routd, a Slack app with a bot token, and a public URL that forwards /slack/events to it.
export ROUTER_URL=http://routd:8080
export AUTHD_URL=http://authd:8080
export AUTHD_SERVICE_KEY=$(grep ^AUTHD_SERVICE_KEY .env | cut -d= -f2)
export LISTEN_ADDR=:8080
export SLACK_BOT_TOKEN=<xoxb bot token>
export SLACK_SIGNING_SECRET=<signing secret>
export ASSISTANT_NAME=arizuko
export DYNAMODB_URL=https://extenddb:18443 # the instance's store server
export AWS_ACCESS_KEY_ID=<key id> AWS_SECRET_ACCESS_KEY=<secret> AWS_REGION=us-east-1
./slakd
On the Slack side, create a Slack app and enable the Events API with a request URL that points at /slack/events. Subscribe to message.channels, message.im, message.groups and reaction_added, and, for the pane, to assistant_thread_started and assistant_thread_context_changed. Do not subscribe to app_mention. slakd detects mentions from <@bot_user_id> in the message text, and an app_mention subscription as well causes double processing. The scopes are chat:write, files:write, reactions:write, im:history, channels:history, groups:history and assistant:write.
GET /health returns 503 when the Slack auth fails or the workspace cache cannot load.
Three pages cover the details
- components/channels: the verb table across adapters.
- [slakd/README.md]: the full table of environment variables, the file map and the pane lifecycle.
- concepts/slack-pane: the assistant pane, its tools and the Slack app settings.