#Approvals in Slack
Let your reviewers approve or reject an AI action without leaving Slack. Once your org has connected Slack, Ratifia posts every decision to your approvals channel. A plain yes/no gets Approve / Reject buttons: one click decides it and resumes your workflow, no dashboard login. A yes/no with a draft gets them too, when the message can show the whole draft (see Drafts). Anything more (a choice, a typed answer) gets an Open in Ratifia button instead, because it's answered in the app. See Where people answer.
#What your reviewers see
The approval message carries the same context blocks your reviewers see everywhere else (the prompt, the tool call, the diff, the cost), rendered natively in Slack, with two buttons:
- Approve / Reject. A single click records the verdict.
- When the decision ends, the buttons are replaced with the outcome ("✅ Approved by Ada"), so nobody works on a closed decision. That happens however it ends: a click in Slack, a vote in the app or by email, expiry, or the request being withdrawn.
With a multi-approver quorum, each person's click counts as one vote; the message updates as the decision resolves.
#Drafts
A decision can carry a draft for the reviewer to check, such as a reply email. Approve sends that draft exactly as written, so Slack offers Approve / Reject only when the message shows the whole draft:
- Up to 1,500 characters, counted after Slack's escaping (
&,<and>each count as several characters), shown in one block with nothing folded away. - Plain text is shown as typed. Markdown is converted to Slack's own formatting; a draft with a table, an image or raw HTML can't be shown faithfully, so it doesn't get buttons, whatever its length.
- Your org must be on rich notifications. On the default
referencemode the draft is case content, so it stays in the app.
Otherwise the message gets Open in Ratifia. Editing the draft always happens in the app.
If someone edits the draft in the app after the message was posted, a click on the old message is refused: the clicker is told privately, the old message loses its buttons, and a new message shows the current text. Approve never acts on text the approver didn't see.
#Deliberation channels
Sometimes an approver isn't ready to answer. They want someone else's read first. Without anywhere to do that, they go and make a Slack channel themselves, and the conversation that actually decides the outcome happens somewhere Ratifia can't see or record.
A deliberation channel replaces that. Each decision can get its own private Slack channel, created when the decision is raised:
- Approvers are invited automatically. They can pull in anyone else who'd help, and those people can read and argue.
- When the decision ends, the channel is archived. Decided, expired or withdrawn. Never deleted.
- The discussion is captured onto the decision as evidence, stored as text rather than a permalink, because a Slack message can be edited or deleted afterwards and a stored snapshot can't.
Slack user ids are resolved to display names when the transcript is captured, so the record reads as a conversation rather than a log of U01EH5RSQ2Y.
#Deliberation is open, authority is closed
Anyone invited to the channel can read it and weigh in. Only the decision's approvers can answer it, from a Slack identity verified as theirs, exactly as before. Widening the conversation never widens who may decide.
#Turning it on
It's off by default, per org. A deliberation channel means case content lives in Slack, which is the thing the reference notification mode exists to avoid, so it's an explicit choice rather than a default.
In the dashboard, go to Settings → Slack and enable "Create dedicated channels for decisions". You can set a channel-name prefix there too, previewed live as you type. With the default prefix tmp, a decision gets a channel named:
#tmp-ratifia-dec_a1b2c3The separator is added for you, so the prefix is just the word.
#Extra Slack scopes
Deliberation needs four scopes beyond the ones plain approvals use:
| Scope | What it's for |
|---|---|
channels:manage | create and archive the channel |
groups:write | the same, for private channels |
groups:history | read the discussion back to capture it |
users:read.email | match approvers to Slack accounts by email |
Re-invite your Ratifia Slack app after enabling, so it picks up these scopes. Without them the feature does nothing rather than failing your decisions, which is the safer failure but a silent one: the toggle looks on and no channels appear.
users:read.email matters more than it looks. Approvers are matched by email, and without it only approvers who had separately verified a Slack identity could be invited.
#What it won't do
- No channel is created when there's nobody to invite. A private channel holding only the bot would be invisible to every human while still accumulating case content.
- A channel is never archived if its transcript wasn't captured. If the capture fails, the archive is refused and the channel stays open, so the discussion stays reachable and the capture can be retried. Sealing a channel with no record of what was said is the one outcome worth avoiding.
- Slack only. Discord threads inherit permissions from their parent channel and auto-archive on their own schedule, so they don't meet the same containment bar.
#Which decisions appear in Slack
All of them, once Slack is connected. There's nothing to set per policy or per request. Each approver still chooses how they're notified; Slack is where the channel post lives. The context.blocks you pass, and a draft, are what the reviewer sees when the org has opted into rich notifications.
#Requirements
- Slack is connected and a channel is chosen. In the dashboard under Settings, click Add to Slack to install the Ratifia app into your workspace, pick the channel approvals are posted to, and use Send sample message to confirm it's reachable. Until then nothing is posted to Slack and decisions are answered in the app and by email.
- The approver is reachable in Slack. Ratifia posts one message to the chosen channel and
@-mentions every approver with a verified Slack identity; whoever clicks casts the vote. A click only counts from a Slack identity verified as one of the decision's approvers; anyone else is told privately and nothing is recorded. Someone who answers in Slack and again in the app counts once.
#Security
Every button click is verified before it can move a decision:
- Each interaction is signed by Slack and checked against your app's signing secret, so a forged or replayed callback is rejected, never recorded.
- A decided approval is final: re-clicking a stale button does nothing, and it can't be flipped after it resolves.
The buttons are a bearer affordance in the sense that whoever can see the message can click, so post Slack approvals to the private channel you intend, the same way you'd scope any approval.