Slack app setup
kube-agents talks to Slack through one Slack app that you create in your workspace. The app connects over Socket Mode (an outbound websocket), so nothing on the cluster needs an inbound endpoint. Which process holds the connection depends on the install’s spec.mode:
today: the credential broker (theplatform-agent-credential-proxyDeployment) holds the connection and relays each event to the Planning Agent’s Hermes Slack listener in theplatform-agent-gatewayDeployment.next(a first install’s default): the A2A gateway, in theplatform-agent-a2a-gatewayDeployment. This needs release 0.9.0 or later: earlier operators keep Slack on thetodaypath even undernext. If Google Chat is also enabled, Google Chat holds the A2A gateway and Slack stays on thetodaypath.
The two need different app settings, so follow the section for your mode. The tokens and the allowlist work the same way in both.
A first install runs next unless you pass --mode=today (./install.sh --mode=today, with the Slack flags below) or mirror the third-party images (quickstart); a cluster that already runs kube-agents keeps the mode it runs unless --mode or install.env names another. An install whose Slack bot token is a list for several workspaces must stay on today. The --mode flag is in releases after 0.9.0 and on main. On 0.9.0 itself, patch the resource instead: kubectl patch platformagent platform-agent -n kubeagents-system --type merge -p '{"spec":{"mode":"next"}}'; that patched mode survives later upgrades, because a release that renders no mode sends Helm no change; to have the installer record it, set PLATFORM_AGENT_MODE=next in install.env. The installer records the mode in install.env as PLATFORM_AGENT_MODE; to switch a running install later, edit that key and re-run the installer (Switching spec.mode).
Before you start
Section titled “Before you start”- A Slack workspace where you may install apps. Many workspaces require a workspace admin to approve a new app; if yours does, ask before you start, or the install waits on the approval.
- One workspace per install under
next: the A2A gateway takes a single bot token and refuses members of other workspaces.
Create the app
Section titled “Create the app”For spec.mode: next (the A2A gateway)
Section titled “For spec.mode: next (the A2A gateway)”-
Open https://api.slack.com/apps, choose Create New App → From a manifest, and pick your workspace.
-
Paste this manifest (YAML), changing only
nameanddisplay_name:display_information:name: kube-agentsfeatures:app_home:home_tab_enabled: truemessages_tab_enabled: truemessages_tab_read_only_enabled: falsebot_user:display_name: kube-agentsalways_online: trueassistant_view:assistant_description: Ask kube-agents about your clusters.oauth_config:scopes:bot:- assistant:write- channels:history- channels:read- chat:write- groups:history- groups:read- im:history- im:read- mpim:history- mpim:read- reactions:write- users:readsettings:event_subscriptions:bot_events:- app_home_opened- assistant_thread_started- message.channels- message.groups- message.im- message.mpiminteractivity:is_enabled: truesocket_mode_enabled: truetoken_rotation_enabled: false -
Choose Create.
What the manifest covers, so you can check an existing app instead:
- Events. The gateway reads messages only:
message.imfor DMs, andmessage.channels,message.groupsandmessage.mpimfor public, private and group channels. Each event needs its history scope (im:history,channels:history,groups:history,mpim:history); without it the app connects normally and is never sent the message. In a channel the gateway answers only a message that mentions the app, or a reply in a thread it is already answering; it finds mentions in the message text, soapp_mentionis not needed. - Scopes.
chat:writecovers every post and edit the gateway makes.channels:read,groups:read,im:readandmpim:readread who is in a conversation. A reply goes into the conversation or thread the message came from, so no other scope is needed for it, in a DM either.reactions:writeputs the reactions on your message,users:readnames who answered a question, andassistant:writeshows Working… on a thread, titles it and sets the suggested prompts; without them the answers still arrive and only those go missing (ChatOps). - Interactivity, the assistant view and
assistant_thread_started. The gateway answers a click on a question’s buttons, so interactivity is on, and it offers suggested prompts when a member opens a new assistant thread. On an app using agent view the gateway also answersapp_home_openedon the Messages tab with the prompts. - Messages tab. Without it, members cannot DM the app.
- Home tab and
app_home_opened. The gateway draws the fleet dashboard (the Slack Home tab) when a member opens the tab. Without either, the tab is absent or blank and nothing else changes; neither needs a scope. WithallowedUsersleft empty, the gateway checks each member’s workspace withusers.info, so the tab also needsusers:read; without it the tab stays blank. - No slash commands. The gateway does not acknowledge them, so a member who used one would see Slack’s timeout error.
Moving an existing app to next
Section titled “Moving an existing app to next”An app made for today from the hermes slack manifest output already has every scope and event the gateway needs to answer messages (the Home tab needs the two settings in step 3), unless it was generated with --no-assistant, so it keeps its tokens and needs no new install. A --no-assistant app lacks assistant:write, the assistant view and assistant_thread_started: add them as in the manifest above and reinstall, or Working…, the thread titles and the suggested prompts do not appear. Edit it rather than pasting the manifest above, which would rename the app and drop the scopes today needs if you switch back:
- After the switch, open the app’s App Manifest page.
- Delete the
features.slash_commandsblock. Leave interactivity on: the gateway answers button clicks. - For the Home tab, set
features.app_home.home_tab_enabledtotrueand addapp_home_openedtosettings.event_subscriptions.bot_events. - Save. The edit changes no scopes; if Slack still asks you to reinstall, do so.
Do it after the switch rather than before, because the today listener answers slash commands until then. Until you do, a slash command under next shows the member Slack’s timeout error. Switching back to today means putting the block back, which the full manifest from hermes slack manifest does.
For spec.mode: today (the Hermes listener)
Section titled “For spec.mode: today (the Hermes listener)”The Hermes listener needs more than the gateway: slash commands and files on top of the reactions and assistant surface both use. Its manifest is the one hermes slack manifest prints. INSTALL.md Step 5 owns the procedure: create the app from that manifest (Create New App → From a manifest), which the command prints on an install where Slack is not configured yet, and its options (--no-assistant, --slashes-only). A manifest that turns on Slack’s agent view cannot be undone, so read that section before you apply one.
Get the tokens
Section titled “Get the tokens”- App-level token (
xapp-…): Basic Information → App-Level Tokens → Generate Token and Scopes, add the scopeconnections:write, and generate it. Socket Mode needs this scope. - Bot token (
xoxb-…): OAuth & Permissions → Install to Workspace (or Request to Install where an admin approves apps), then copy Bot User OAuth Token. Reinstall the app whenever you change its scopes; Slack only grants new scopes on install.
Pass them to the installer as --slack-bot-token and --slack-app-token. Under next, give exactly one bot token: the gateway cannot use a comma-separated list.
Once the app is installed, invite it to any channel it should answer in, using the bot’s display name from the manifest (/invite @kube-agents for the manifest above). It receives a channel’s messages only once it is a member; DMs need no invite.
Home channel
Section titled “Home channel”The home channel is where the agent posts unprompted: alerts, scheduled reports, and the fleet audit’s report card. Under next, set one: without it, every one of those posts is dropped while conversations keep working, so nothing else shows it.
next: only the resource field counts,spec.integration.slack.homeChannel, which the installer sets fromSLACK_HOME_CHANNEL(--slack-home-channel). It must be a channel ID (C0123ABCD, orG…for a private channel), not a name: open the channel’s details and copy the Channel ID at the bottom. Invite the app to that channel, or its posts are refused. With the field unset, the agent posts nothing to Slack unprompted, though a delegated task’s report still reaches the conversation that asked for it; the installer warns before it applies that (andinstall.sh’s setup interview asks you to confirm), the gateway logs a warning at start, and the PlatformAgent carries theHomeChannelUnsetcondition until the field is set. Set to something that is not a channel ID, it turns off both./sethomedoes not reach it.today: the field, or/sethome(/hermes sethome) run in the channel you want, which writes the Planning Agent’s profile.INSTALL.mdStep 5 has the detail.
A home channel set with /sethome under today does not carry over to next. Before or at the switch, set SLACK_HOME_CHANNEL in install.env to that channel’s ID and re-run the installer.
Allowed users
Section titled “Allowed users”The allowlist decides who may talk to the agent. It takes Slack member IDs, not emails or display names, and matches them exactly:
- Find a member ID: in Slack, open the person’s profile, choose the ⋮ (more) menu, then Copy member ID. It looks like
U0123ABCD. - Set it: pass
--slack-allowed-users=U0123ABCD,U0456EFGHon the first installer run. To change it later, editSLACK_ALLOWED_USERSininstall.envand re-run the installer: a re-run refuses a--slack-allowed-usersthat disagrees withinstall.env, and an upgrade renders thePlatformAgentresource frominstall.env, so a hand edit of the resource does not last. - An email never matches. An entry like
alice@example.comadmits nobody; if every entry is an email, everyone is refused. - An empty list admits every member of the workspace. In a shared or company workspace that means anyone there can drive an agent with access to your clusters, so set a list unless the workspace is yours alone.
What a member who is not on the list sees:
next: the gateway answers once per member with a notice that it cannot verify them, naming their member ID, so an admin can add them. A member of another workspace in a Slack Connect channel is not served, even with an empty list. The first time they mention the bot, send it a direct message, or click one of its buttons, the bot replies once, in that thread, that it answers only its own workspace, and names their member ID. The reply is a public post in the thread, so in a Slack Connect channel members of both organizations can read it.today: the message is ignored, with no reply.
The pairing step in INSTALL.md applies only if you set the Hermes Slack DM policy to pairing yourself. A kube-agents install configures the allowlist instead, and the A2A gateway has no pairing.
Principal map (next, optional)
Section titled “Principal map (next, optional)”Under next the gateway attributes each admitted member by their member ID (slack:U0123ABCD) in the request it sends the agent. To attribute members by an identity from your identity provider instead, create the optional Secret a2a-slack-principal-map in the install’s namespace: one key per member ID, whose value is that member’s principal.
kubectl create secret generic a2a-slack-principal-map -n kubeagents-system \ --from-literal=U0123ABCD=alice@example.com \ --from-literal=U0456EFGH=bob@example.comkubectl rollout restart deployment/platform-agent-a2a-gateway -n kubeagents-systemThe gateway reads the map when it starts, so restart it after every change. The map changes attribution only: it admits no one, and a member the allowlist refuses is refused whatever the map says. A value that starts with slack: locks that member out, even when the allowlist admits them, until the entry is corrected. The spec.integration reference has the rest of the map’s behaviour.
Verify
Section titled “Verify”-
Check that the app connected. Under
next:Terminal window kubectl logs deploy/platform-agent-a2a-gateway -c gateway -n kubeagents-system | grep 'slack connected'A line with
"msg":"slack connected"names the bot user and the workspace (team). Undertoday, the credential broker holds the connection (kubectl logs deploy/platform-agent-credential-proxy -n kubeagents-system) and the Hermes listener handles the messages (kubectl logs deploy/platform-agent-gateway -c platform-agent -n kubeagents-system). -
DM the app (Apps, then the app’s name, then Messages) with a question such as
what clusters can you see?. The answer comes back in the DM, in a thread under your question (an older release answers it top-level in the DM). -
If nothing comes back, check the gateway log for these lines:
Log line ( msg)Cause Fix none at all for your message A missing history scope or event subscription, or the messages tab is off Compare the app with the manifest above, then reinstall it dropping message from unverified senderYour member ID is not on the allowlist Add the member ID, not an email slack allowlist is empty and allow-all is off; every inbound message will be dropped at verificationThe list has only blank entries Set real member IDs, or remove the list to admit everyone slack: ignoring a message from another workspace's memberThe sender ( user) is in another workspace (userTeamormessageTeam)Use the workspace the app is installed in chat backend stopped; restarting it, the console stays upThe tokens were refused, for example a comma-separated bot token Pass one xoxb-bot token and onexapp-app token