What Neens shares with Slack
This page is for whoever has to approve the Neens Slack app: what it can do in your Slack workspace, what leaves Neens, how credentials are stored, and how to take it all back. For setting it up, see Slack notifications.
In short
- Neens posts to Slack channels you choose. It never reads channel history, files or members.
It only receives what Slack sends it on purpose: a press of a button on a card it posted, a
/neenscommand, a message that mentions @Neens, and the Neens links in a message (to preview them). It acts on those only for a person who linked their Slack account, as that person’s Neens login. - By default a message carries metadata only: an insight’s title, severity, counts and a link back to Neens. Trace content is included only as a short, redacted excerpt, and only when both the rule and the agent’s own setting allow it.
- Slack credentials (the bot token and incoming-webhook URLs) are encrypted at rest, are never shown again after you enter them, and are never written to logs.
- A Slack message or Slack identity never grants access to anything in Neens. A button acts only for a Slack account its owner linked to their own Neens login, with that login’s permissions.
- Disconnecting removes the connection, erases the stored token and asks Slack to revoke it.
Slack permissions requested
| Permission | Why Neens needs it | What it does not allow |
|---|---|---|
chat:write | Post insight cards, and update or reply to the cards Neens itself posted | Posting in a channel Neens has not been invited to |
channels:read | Show public channel names in the channel picker | Reading messages |
groups:read | Show the private channels Neens has been invited to in the channel picker | Seeing private channels Neens is not in, or reading messages |
commands | Receive the /neens command when someone types it | Seeing anything else typed in Slack |
app_mentions:read | Receive a message that mentions @Neens, to answer it in its thread | Reading messages that don’t mention Neens, or the rest of the thread |
links:read | Receive the Neens links (only links to your Neens address) posted in a message | Reading the message itself or any other link |
links:write | Add a preview under those Neens links | Changing the message |
im:write | Open a direct message with a person who asked for one (their morning inbox, review items) | Messaging anyone who didn’t ask; reading direct messages |
When you link your Slack account, Neens also asks Slack for one sign-in permission on your behalf, separate from the app’s permissions above:
| Permission | Why Neens needs it | What it does not allow |
|---|---|---|
openid (Sign in with Slack) | Confirm which Slack user and workspace you are, once, when you link | Reading anything in your workspace; Neens keeps no Slack token for you |
Neens deliberately does not request chat:write.public (posting to public channels without an
invitation), message history, file, user-profile or email permissions. When a feature needs
another permission, an admin has to approve it again in Slack (Update permissions on the
workspace); until then that feature stays off and nothing else changes.
The app can be installed for a single workspace or, on Slack Enterprise Grid, for the whole organization at once. Either way it gets the same permissions.
Neens also asks Slack to tell it when the app is uninstalled or its access is revoked, so it can stop sending immediately. Those notifications carry no message content.
What leaves Neens
Metadata cards (the default)
| Sent | Not sent |
|---|---|
| Insight title and short summary, as shown in Neens | Prompts, model outputs, tool inputs or outputs |
| Severity, insight type, the agent name and company name | User identifiers from your traces |
| Counts and rates (for example error rate, number of affected sessions), each with its sample size | Raw traces, spans or session transcripts |
| A link back to the insight in Neens (opening it still needs a Neens login with access) | API keys, connection settings or any credential |
| The time it was detected, and later state changes (recurred, resolved) |
Redacted excerpts (opt-in, twice)
A card includes a short excerpt from an example trace only when both of these are true:
- every routing rule sending the insight to that channel has Message content set to Redacted excerpts, and
- the agent’s own setting under Settings → Integrations → Data shared with Slack is Redacted excerpts. It is Metadata only unless an admin of that agent changes it.
The most restrictive setting always wins. Before an excerpt is stored or sent it goes through the agent’s PII redaction policy and the display redactor, and each field is cut to 300 characters. If the redaction policy can’t be read for any reason, the excerpt is dropped and the card stays metadata only: Neens fails closed.
Anything posted to a Slack channel is visible to every member of that channel and is kept under your Slack workspace’s retention rules, not Neens’. Turn on excerpts only for channels whose audience may see that content.
Direct messages, previews, commands and @Neens answers
| Feature | What it contains |
|---|---|
| Morning inbox DM (opt-in per person) | The titles, severities, agent names and session counts of the items that need that person, read with their Neens permissions, plus a link. Metadata only |
Review DM (/neens review) | Why a trace was picked, the agent and a link; a redacted excerpt of the trace only when the agent’s Data shared with Slack setting is Redacted excerpts (same redaction as above). Only the person reviewing sees it |
| Link previews | For a person who linked their account and can open the page: its name, status and a count (a failure mode’s sessions, a trace’s status and duration). Never an excerpt, even when the agent allows excerpts, because a preview is visible to the whole channel. Anyone else gets only the page type, such as Neens · Failure mode |
/neens replies | Shown only to the person who typed the command: counts, titles and links they can already see in Neens |
| @Neens answers | Posted in the thread, visible to that channel. Written by your agent’s own LLM connection from Neens data the asker can read; the assistant is told never to quote trace content |
The question someone asks @Neens is sent to the LLM connection configured for that agent in Neens (your own provider account; Neens has no shared model key) and is not stored by Neens or written to the audit log.
How credentials are stored
| Credential | Storage | Shown to users |
|---|---|---|
| Slack bot token (one per connected workspace) | Encrypted at rest with your deployment’s encryption key; decrypted only for the moment of a send | Never |
| Incoming-webhook URL | Encrypted at rest | Never again after you save it; the list shows only its last characters |
| The temporary sign-in state used during Add to Slack | Single use, expires after 10 minutes, bound to the browser that started it | Never |
Tokens, webhook URLs and signing secrets are never written to Neens logs, error messages or the
audit log. Failures are recorded only as a short code, such as not_in_channel or
rate_limited.
Neens only ever talks to slack.com and hooks.slack.com. A webhook URL that points anywhere else
is refused when you enter it, and Neens does not follow redirects.
Inbound requests from Slack
Slack calls Neens to tell it the app was uninstalled or its access revoked, when someone presses
a button on a Neens card, types /neens, mentions @Neens, or posts a Neens link. Every such
request is checked against Slack’s signing secret and a five-minute timestamp window before its
body is read; anything that fails the check is rejected without a response body. Slack retries a
request it thinks was lost; Neens handles each one once.
- An uninstall or revocation notice can only switch a connection off.
- A button press is acted on only when the card’s own signed details are intact (they say which Neens account, agent and insight the card is about), that Neens account still has the app in the workspace, and the person who pressed it has linked their Slack account to a Neens login in that account. Neens then performs the action as that login, through the same permission checks as the Neens app. Anyone else only gets a private prompt to link their account.
- A
/neenscommand, an @Neens question and a link preview are acted on only for a person who linked their Slack account, and only as that person: the same permission checks as the Neens app run for every read. A question about an agent they can’t open is refused before anything is read. - Linking requires signing in to Neens and then to Slack in the same browser; the Slack identity must match the person who pressed the button. Neens never links by email address.
Connecting a workspace is protected against an attacker starting an install and tricking someone else into finishing it: the install must be completed in the same browser that started it, by a user who is still an admin of the scope at that moment.
Who can see and change what
| Role in Neens | Sees | Can change |
|---|---|---|
| Company-wide admin | Everything in the company, including who connected each workspace | Every workspace, channel, rule and agent content setting |
| Org admin | Workspaces usable by their org, and the channels and rules of their org and its agents | The channels and rules of their org and its agents; a workspace they connected |
| Admin of an agent | Workspaces usable by that agent, and its channels and rules | That agent’s channels, rules and content setting |
| Member or viewer | Channels, rules and the delivery log for the parts of the company they can access | Nothing |
| Project API key | That agent’s channels, rules and log | Nothing |
Rules from one agent can never post to another agent’s channel. Two Neens companies are fully separate: each sees only its own workspaces, channels, rules and delivery log.
One Slack workspace, several Neens accounts
Slack issues one app token per workspace. If two Neens companies (for example a vendor and its customer) both connect the same Slack workspace, they hold the same app installation but never see each other’s channels, rules or messages. When one of them disconnects, Neens removes only that company’s connection and leaves the app installed for the other; it revokes the app at Slack only when no Neens company is still using it.
Uninstalling and what Neens revokes
| You do | Neens does |
|---|---|
| Disconnect in Settings → Integrations | Erases its stored token, asks Slack to revoke the app (unless another Neens company still uses it in that workspace), stops all pending messages to that workspace, and records the change in the audit log. Channels and rules are kept so you can reconnect later |
| Remove the Neens app from Slack | Slack notifies Neens; every Neens connection to that workspace is marked Disconnected and pending messages are skipped |
| Delete an agent | Its channels, rules and delivery history are deleted. A workspace connected from that agent is disconnected and revoked if nothing else uses it |
| Close your Neens account | Every connection is disconnected and revoked at Slack (unless another Neens company still uses that workspace) before your data is deleted |
Retention
The Delivery log keeps each message’s status, the insight title and severity for 30 days after the message reached a final state, then deletes it. Messages already posted in Slack are kept by Slack under your workspace’s retention settings; Neens can’t delete them.
Audit events
Every change is recorded in the audit log with who made it and where
it came from (web for the Neens app, slack for a notification from Slack, neens when Neens
itself detected the problem). Changes made by pressing a button in Slack are recorded as the
linked person, from slack:
| Event | When |
|---|---|
chat.installation.install, chat.installation.reinstall, chat.installation.reconsent | A workspace was connected, connected again, or its permissions updated |
chat.installation.update | Who may use a workspace changed |
chat.installation.uninstall | A workspace was disconnected in Neens, or because its agent was deleted |
chat.installation.deactivate | Slack reported the app removed or revoked, or Slack rejected the app’s credentials |
chat.destination.create, chat.destination.update, chat.destination.delete | A channel or webhook was added, changed or deleted |
chat.rule.create, chat.rule.update, chat.rule.delete | A routing rule was created, changed or deleted |
chat.test_message.send | Someone sent a test message |
chat.content_level.update | An agent’s Data shared with Slack setting changed |
chat.user_link.create, chat.user_link.delete | A Slack account was linked to, or unlinked from, a Neens login |
chat.action.mute_7d, chat.action.generate_fix | Someone pressed a button on a card in Slack: recorded whether it ran, was refused (not linked, role not allowed) or failed |
chat.action.review_pass, chat.action.review_fail | Someone labelled a trace from a review DM |
chat.command.<command> (for example chat.command.subscribe) | Someone typed /neens: the command, its arguments (cut to 200 characters) and whether it ran or was refused |
chat.user_prefs.update | Someone turned their morning inbox DM on or off, or changed its hour |
chat.assistant.query | Someone asked @Neens a question: whether it was answered or refused, and for which agent. Never the question |
chat.unfurl | Neens previewed Neens links posted by a linked person: how many got a full preview |
No audit entry contains a token, a webhook URL or message content. A channel subscribed with
/neens subscribe is also recorded as the usual chat.destination.create and chat.rule.create,
from slack.