A Slack moderation prototype that combines policy-based keyword filtering, PostgreSQL/Prisma audit records, and AI-assisted content analysis for configurable workplace moderation workflows.
Status: portfolio prototype with Docker and Railway deployment configuration. It has not been validated as a production policy engine: the repository currently has no committed automated test suite or CI workflow, and moderation policies must be reviewed for each workspace.
ClearChat Bot employs a hybrid moderation approach combining fast keyword filtering with AI-powered context analysis. The system provides immediate moderation of offensive content while maintaining low false-positive rates through intelligent severity classification.
The bot uses a staged moderation pipeline:
- Keyword filtering - A Prisma-backed keyword cache handles configured policy terms locally.
- Decision and audit persistence - Prisma records moderation results, warnings, settings, and audit history in PostgreSQL.
- AI-assisted analysis - OpenAI moderation and context analysis paths are used when keyword matching is insufficient.
- Workspace feedback - Slack messages and administrator notifications communicate warnings and decisions.
- Runtime: Node.js 18+
- Language: TypeScript
- Web Framework: Express.js
- Slack Integration: Slack Bolt SDK
- Database: PostgreSQL
- ORM: Prisma
- AI Service: OpenAI Moderation API
- Logging: Pino
- Deployment: Railway
- Real-time monitoring of all channel messages
- Multi-tier severity classification (Critical, High, Medium, Low)
- Warning and escalation decisions for critical violations
- Public warnings for high-severity content
- Private direct messages to violators
- Per-user, per-channel warning tracking
- Comprehensive audit logging
- Slack slash commands for bot management
- Keyword management (add/remove/list)
- User violation history lookup
- Moderation statistics dashboard
- Admin-only access control
- Node.js 18 or higher
- PostgreSQL database (local or managed)
- Slack workspace with admin access
- OpenAI API key
- Railway account (for production deployment)
git clone https://github.com/CalebMorse06/clearchat-bot.git
cd clearchat-bot
npm installCopy the example environment file and configure your credentials:
cp .env.example .envRequired environment variables:
| Variable | Description | Source |
|---|---|---|
SLACK_BOT_TOKEN |
Bot user OAuth token | Slack App OAuth & Permissions page |
SLACK_SIGNING_SECRET |
Request verification secret | Slack App Basic Information |
OPENAI_API_KEY |
OpenAI API key | OpenAI dashboard |
DATABASE_URL |
PostgreSQL connection string | Your database provider |
ADMIN_USER_IDS |
Comma-separated Slack user IDs | Slack workspace |
PORT |
Server port (default: 3000) | Optional |
MODERATION_MODE |
Moderation strictness (standard/strict/demo) | Optional |
Initialize the database schema and seed with default keywords:
npm run migrate
npm run seedThis creates five tables:
offensive_keywords- Keyword database with severity classificationmoderation_logs- Audit trail of all moderation actionsuser_warnings- Per-user violation trackingmoderation_results- AI analysis historymoderation_settings- Per-channel configuration
-
Navigate to Slack API Apps
-
Create a new app or select your existing app
-
Configure Event Subscriptions:
- Request URL:
https://your-deployment-url/slack/events - Enable event subscriptions
- Request URL:
-
Add Bot Token Scopes under OAuth & Permissions:
app_mentions:read- Detect @mentionschannels:history- Read channel messageschannels:read- View channel informationchat:write- Send messageschat:write.public- Send messages to channels without joiningim:history- Read direct messagesim:write- Send direct messagesusers:read- Retrieve user information
-
Subscribe to Bot Events:
app_mention- Bot @mentionsmessage.channels- Channel messagesmessage.groups- Private channel messagesmessage.im- Direct messages
-
Install the app to your workspace
Start the development server:
npm run devFor local testing with Slack, you'll need to expose your local server using a tunneling service (e.g., ngrok, localtunnel) and update your Slack app's Event Subscription URL.
- Install Railway CLI:
npm install -g @railway/cli- Login and initialize:
railway login
railway init- Provision PostgreSQL database:
railway add postgresql- Configure environment variables:
railway variables set SLACK_BOT_TOKEN=<your-token>
railway variables set SLACK_SIGNING_SECRET=<your-secret>
railway variables set OPENAI_API_KEY=<your-key>
railway variables set ADMIN_USER_IDS=<admin-user-ids>- Deploy:
railway up- Update your Slack app's Event Subscription URL to your Railway deployment URL
Build and run using Docker Compose:
docker-compose up -dThis starts both the PostgreSQL database and the bot application.
The bot automatically monitors all messages in channels where it's installed. Upon detecting offensive content, it takes action based on severity:
Critical Severity:
- Immediately deletes the message
- Posts public notification
- Sends private DM to user
- Increments warning count
- Logs to database
High Severity:
- Posts public warning
- Sends private DM to user
- Increments warning count
- Logs to database
Medium Severity:
- Sends private DM to user
- Increments warning count
- Logs to database
Low Severity:
- Logs to database
- No user notification
Mention the bot to access admin commands (admin users only):
@ClearChat Bot seed - Load default keyword list
@ClearChat Bot help - Display available commands
Stores offensive terms with severity classification.
| Column | Type | Description |
|---|---|---|
| id | String | Unique identifier |
| keyword | String | Offensive term (lowercase, unique) |
| severity | String | critical, high, medium, low |
| category | String | general, explicit, harassment, hate, spam |
| isActive | Boolean | Whether keyword is active |
| addedBy | String | User ID who added the keyword |
| source | String | manual, ai_learned, imported |
Audit trail of all moderation actions.
| Column | Type | Description |
|---|---|---|
| id | String | Unique identifier |
| channelId | String | Slack channel ID |
| userId | String | Slack user ID |
| content | String | Message content |
| action | String | Action taken (warn, delete, allow) |
| keywords | String[] | Matched keywords |
| confidence | Float | AI confidence score (0-1) |
Tracks warning counts per user per channel.
| Column | Type | Description |
|---|---|---|
| id | String | Unique identifier |
| userId | String | Slack user ID |
| channelId | String | Slack channel ID |
| count | Int | Warning count |
| lastWarned | DateTime | Last warning timestamp |
npm run dev # Start development server with hot reload
npm run build # Compile TypeScript to JavaScript
npm start # Run production build
npm run migrate # Run database migrations
npm run seed # Seed database with default keywords
npm run setup # Full setup (migrate + seed)
npm run studio # Open Prisma Studio (database GUI)clearchat-bot/
├── src/
│ ├── index.ts # Application entry point
│ ├── config.ts # Environment configuration
│ ├── database.ts # Prisma client
│ ├── logger.ts # Logging configuration
│ ├── commands/
│ │ └── admin.ts # Admin command handlers
│ ├── http/
│ │ └── routes.ts # HTTP routes
│ ├── moderate/
│ │ ├── analyzer.ts # OpenAI content analyzer
│ │ ├── keywordFilter.ts # Keyword filtering engine
│ │ ├── processor.ts # Base moderation processor
│ │ └── smartProcessor.ts # Three-tier processor
│ ├── notifications/
│ │ └── adminAlerts.ts # Notification system
│ └── slack/
│ ├── bolt.ts # Slack app configuration
│ └── handlers/
│ ├── appMention.ts # @mention handler
│ └── messageHandler.ts # Message event handler
├── prisma/
│ ├── schema.prisma # Database schema
│ ├── seed.ts # Database seeding script
│ └── migrations/ # Migration history
├── .env.example # Environment variable template
├── Dockerfile # Docker configuration
├── docker-compose.yml # Docker Compose configuration
├── railway.json # Railway deployment config
└── package.json # Dependencies and scripts
Check if the bot is running:
railway logsView live logs:
railway logs --tailVerify DATABASE_URL is correctly configured:
railway run npm run migrate
railway run npm run seedEnsure SLACK_SIGNING_SECRET matches your Slack app configuration and that the Event Subscription URL is correct.
Verify OPENAI_API_KEY is valid and has sufficient quota. The bot will fall back to keyword-only moderation if the API is unavailable.
- All secrets managed via environment variables (never committed to version control)
.envfiles excluded from git via.gitignore- Slack request signature verification enabled
- Admin commands restricted to authorized user IDs
- SQL injection protection via Prisma ORM
- Moderated message content can be persisted and logged; configure retention, access controls, and redaction before using the bot with real workplace data
- The keyword path avoids a model request when a policy term is already known.
- The application has a fallback path when the OpenAI service is unavailable.
- Structured logging and health/status endpoints support local and hosted troubleshooting.
- No repeatable benchmark, load test, or committed unit-test suite is currently included, so this repository makes no latency or throughput claim.
- Slack bots cannot delete ordinary user messages with the current implementation; a
deletedecision is surfaced as a warning rather than a message-removal action.
No license file is currently included. Treat the source as all rights reserved until a license is added.
This project demonstrates an end-to-end TypeScript moderation workflow, including:
- Slack bot development with event subscriptions and slash commands
- Database design and ORM integration
- AI API integration for content analysis
- TypeScript best practices with strong typing
- Cloud deployment and Platform-as-a-Service utilization
- Configuration-driven credential handling and administrative controls
- Real-time event processing with Node.js