Skip to main content
Version: Next

Slack and approvals

Orion reports into Slack and reads back exactly one thing: approvals. It runs no Slack listener, so you cannot command it from Slack.

Setting up the Slack app and its token is on Credentials.

A channel per project​

orion plan creates #orion-<slug>, sets the channel topic to the idea, posts an opening message naming the workspace and the commands to drive it, and turns on slack.enabled in the project's orion.json. For a repository you adopted, add the slack block yourself.

Every stage failure, breaker trip, quota wait, budget checkpoint, CI failure and approval request for that project then lands in that channel.

If Slack is unreachable when a workspace is created, Orion says so and carries on; the workspace is usable without a channel.

Mentions only when someone must act​

Orion @-mentions people only on messages that need action: blocked, failed, and approval requests.

A CI failure Orion will retry is posted as a heads-up with no mention ("KEY failed CI -- Orion will retry it"). Only the last one, when the retries are spent, mentions the people in slack.mention ("KEY still fails CI after N retries"). slack.mention takes Slack user IDs (U...); empty falls back to slack.invite_users.

When approval is required​

Approval is required when either of these holds:

Landing modeApproval required whenOtherwise
Batch integration (collect.batch_integration, on for every project orion plan creates)slack.merge_approvers names peoplea green batch lands unattended
One pull request per ticketslack.require_approval is trueOrion reports that checks pass and waits for a person to merge on GitHub

When approval is required, Orion posts a request in the project's channel, mentioning the approvers, and checks that message on each watch sweep.

slack.merge_approvers accepts a Slack user ID (U...), a username, a display name or an email address. An ID always works. Resolving a name needs the users:read scope and an email needs users:read.email; without them the request still sends and names the person, and the run says the mention was lost.

Empty means nobody, not everybody

With slack.merge_approvers empty, nobody can approve from Slack, and in batch mode that is also what lets a green batch land with no approval at all. Membership of the channel gives no one the right to approve.

How to approve or reject​

React to the request message, or reply in its thread.

ToReact withOr reply
Approveβœ… white_check_mark, βœ”οΈ heavy_check_mark, πŸ‘ +1, shipit, πŸš€ rocketapprove, approved, lgtm, ship it, merge it, go ahead
Reject❌ x, β›” no_entry, 🚫 no_entry_sign, πŸ‘Ž -1, βœ‹ handreject, rejected, no, hold, stop, wait, do not merge, don't merge

The rules:

  • A rejection beats every approval.
  • Only people listed in slack.merge_approvers count.
  • Only reactions and replies on the request message itself count.
  • Orion's own reactions never count.

Reading reactions needs the reactions:read scope; reading thread replies needs channels:history (public channels) or groups:history (private). After adding a scope, reinstall the app: an issued token does not gain new scopes. The design is in ADR 0033.

Without Slack​

Approve from the terminal, or from the web dashboard, once the project's orion.json sets collect.allow_local_approval:

orion approve KEY # approve
orion approve KEY --reject --reason "<why>" # reject

Rejecting always works, with or without that setting. The next collect pass acts on the decision.

What else needs approval​

The same approval vocabulary and approver list cover three things:

  • merges, as above;
  • recommendations, such as the database architect's choice of database (see Advisors and decisions);
  • releases: orion release ship asks in the project's channel and waits for a person before it merges the promotion (see Releasing a milestone).

Talking to Orion through Slack​

Orion has no Slack listener, because a socket-mode app would be a long-running process with tokens to protect. To make Orion conversational, drive it from an interactive Claude session with a Slack MCP server connected: you ask Claude, and Claude runs the orion commands and reports back into the channel. This adds no service to run or secure.

Test it​

orion slack test [KEY]

sends a real message and reports exactly what breaks.

Not documented yet​

  • How long an approval request waits before anything else happens. Orion checks it on each watch sweep; no timeout is documented.