/v1/whisper to lowercase them, and emits a calmer
version. You can drop the result into a chat display, an internal feed, or a
late-night digest where everyone is too tired for shouting.
Two paths are covered:
- Batch mode. Read a Slack export (or any list of messages) from JSON, rewrite the shouty ones, write the result back. Runnable without any Slack credentials.
- Live mode. A Slack Bolt app that listens to channel messages and posts a calmed reply in-thread when shoutiness crosses a threshold.
What you will build
Given an input filemessages.json:
quiet.json:
Prerequisites
- Python 3.10 or newer.
pip install requestsfor batch mode.pip install slack-boltfor live mode (optional).- An ACAAS API key in
ACAAS_API_KEY. The demo key works. - For live mode: a Slack workspace where you can install a bot, plus a bot
token (
SLACK_BOT_TOKEN) and an app-level token (SLACK_APP_TOKEN).
Step 1: Decide what counts as shouty
Before calling the API, decide which messages deserve a whisper. A simple heuristic combines two signals: how much of the message is uppercase, and how many exclamation marks it carries.shoutiness.py
0.4 ratio also catches mixed-case yelling like “Why Are We
Doing This Again.”
A quick sanity check:
Step 2: Whisper a single message
Wrap/v1/whisper in a function. Reuse the Client pattern from the
release notes cookbook, or use this minimal
inline version:
whisperer.py
429 and 5xx as shown in
the errors reference. For this walkthrough, the bare call keeps
the focus on the use case.
Step 3: Process a batch
Wire the heuristic and the whisperer together. The function below preserves message order and metadata, only mutatingtext when shoutiness fires.
calm_batch.py
text is rewritten and a calmed boolean is added so downstream code
can highlight or count rewrites.
Step 4: Wire it to a live Slack channel
Skip this section if batch processing is enough. For real-time calming, use Slack Bolt for Python with Socket Mode so you do not need a public URL.quiet_bot.py
- Reply in-thread, do not edit. Slack’s API only lets a bot edit messages it posted itself. Posting a calmed reply in-thread keeps the original message intact and lets the author see the contrast.
- Skip subtypes and bot messages. Channel joins, edits, and the bot’s
own posts arrive as the same
messageevent. Filtering them prevents loops and noise. - Italics for the prefix.
_at conversational volume:_reads as a gentle aside in Slack, not a callout.
chat:write, channels:history,
groups:history, im:history, mpim:history, plus the corresponding
message.* event subscriptions. Install the app to a test channel before
turning it loose on #general.
Step 5: Smoke-test the heuristic
Before turning the bot on, run the heuristic against a varied corpus to make sure the threshold is tuned for your team. The included fixture covers the usual cases:smoke.py
shoutiness.py until your own corpus produces
sensible flags before connecting to a live workspace.
What you learned
- Heuristic before API call. A cheap local check (
is_shouty) keeps most messages out of the request path entirely. Only the loud ones cost a quota slot. - Preserve metadata, mutate only what you must. Carrying
user,ts, and any other fields through unchanged makes the calmed output a drop-in replacement for the original. - Reply, do not rewrite. Posting a thread reply respects authorship and Slack’s API permissions.
- Pilot before you scale. Auto-rewriting tone is a social intervention as much as a technical one. Start in a small, consenting channel.
Next steps
Release notes amplifier
The companion cookbook — uses scream and emphasize end-to-end.
Whisper reference
Full request and response schema for
/v1/whisper.Errors
Add retry handling once you move past the demo key.
Rate limiting
Pace the bot if your channel is genuinely chatty.