Files · Slack/email triage to priority inbox
86 (1 binary, 729.8 kB total)attempt 1
README.md·8741 B·markdown
markdown
# Slack/Email Triage to Priority Inbox
> Automated triage agent that reads inbound Slack messages and Gmail emails, classifies urgency (P0/P1/P2) using AI intent classification, and drafts contextual replies for urgent items.
A tutorialized reference solution from [reaatech.com](https://reaatech.com), demonstrating how to build production-grade AI systems with the `@reaatech/*` package family.
---
## Problem Statement
Support teams are overwhelmed by a flood of messages across Slack and email. Urgent issues (outages, security incidents) get buried under routine questions, and every message requires manual reading, classification, and response — wasting hours of agent time each day.
This solution automates the triage pipeline: every inbound message is classified by urgency (P0/P1/P2), routed to the right specialist agent, and a contextual AI reply is drafted. P0 alerts are posted to a dedicated Slack channel, ensuring critical issues never go unnoticed.
---
## Architecture
```
┌──────────────────┐ ┌──────────────────────┐ ┌──────────────────┐
│ Slack Events API │────▶│ POST /api/inbound/ │ │ Gmail Poll │
│ (Webhook) │ │ slack │ │ (Cron/Scheduler)│
└──────────────────┘ └──────────┬───────────┘ └────────┬─────────┘
│ │
▼ ▼
┌──────────────────────────────────────┐
│ Triage Engine │
│ │
│ 1. Circuit Breaker Gate │
│ └── isAgentReady("classifier") │
│ │
│ 2. Intent Classification │
│ └── @reaatech/agent-mesh- │
│ classifier │
│ │
│ 3. Confidence Gate │
│ └── @reaatech/agent-mesh- │
│ confidence │
│ │
│ 4. Budget Check │
│ └── @reaatech/agent-budget- │
│ llm-router-plugin │
│ │
│ 5. LLM Draft Generation │
│ └── OpenAI (configurable) │
│ │
│ 6. Circuit Breaker Recording │
│ └── @reaatech/agent-mesh-utils │
└──────────────────────────────────────┘
│
┌─────────┴──────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Slack Reply │ │ Mark Read │
│ (P0 alert) │ │ (Gmail) │
└──────────────┘ └──────────────┘
```
---
## Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `SLACK_BOT_TOKEN` | Yes | — | Slack bot token for reading messages and posting replies |
| `SLACK_SIGNING_SECRET` | Yes | — | Slack Events API signing secret for webhook verification |
| `GMAIL_CLIENT_EMAIL` | Yes | — | Gmail service account email for JWT auth |
| `GMAIL_PRIVATE_KEY` | Yes | — | Service-account private key (PEM, newlines as `\n`) |
| `GMAIL_USER_EMAIL` | Yes | — | Target Gmail inbox to poll |
| `OPENAI_API_KEY` | Yes | — | API key for the LLM provider |
| `OPENAI_BASE_URL` | No | `https://api.openai.com/v1` | Base URL for OpenAI-compatible endpoint |
| `LLM_MODEL` | No | `gpt-5.2` | Model ID for chat completions |
| `BUDGET_LIMIT_USD` | No | `10.0` | Per-scope USD spend cap before LLM calls are blocked |
| `P0_CHANNEL_ID` | No | — | Slack channel for urgent P0 alerts |
| `P1_CHANNEL_ID` | No | — | Slack channel for high-priority P1 notifications |
| `TRIAGE_POLL_INTERVAL_MS` | No | `60000` | How often the email poller fetches unread messages |
| `LANGFUSE_PUBLIC_KEY` | No | — | Langfuse public key for observability |
| `LANGFUSE_SECRET_KEY` | No | — | Langfuse secret key (pair with public key) |
| `LANGFUSE_BASE_URL` | No | — | Langfuse self-hosted or cloud URL |
---
## Getting Started
```bash
pnpm install
cp .env.example .env
# Fill in all required environment variables
pnpm typecheck # Verify TypeScript compilation
pnpm lint # Run ESLint
pnpm test # Run vitest with coverage
pnpm dev # Start Next.js dev server
```
---
## API Endpoints
### POST /api/inbound/slack
Slack Events API webhook endpoint. Accepts URL verification challenges and message events.
**Signature verification:** HMAC-SHA256 using the Slack signing secret.
**Request:** Slack Events API payload (`application/json`).
**Responses:**
- `200` — `{ "ok": true }` for message events and URL verification challenges
- `401` — `{ "error": "invalid signature" }` on HMAC mismatch
**Behavior:**
- `url_verification` — returns the challenge token
- `message` — triages the message, posts AI-drafted reply in thread, sends P0 alert
- `unknown` — acknowledges with `{ ok: true }`
### POST /api/inbound/email
Email poll endpoint intended for cron or scheduler invocation.
**Behavior:**
- Fetches all unread Gmail messages
- Triages each message through the TriageEngine
- Marks processed messages as read
- Posts P0 alerts to the configured Slack channel
**Success response:**
```json
{ "processed": 5, "p0": 1, "p1": 2, "p2": 2 }
```
**Error responses:**
- `502` — `{ "error": "Gmail fetch failed" }` on Gmail API failure
### GET /api/health
Health check endpoint.
**Response:**
```json
{ "status": "ok", "timestamp": "2026-05-31T...", "uptime": 123.45 }
```
---
## REAA Packages Used
This recipe integrates five `@reaatech/*` packages:
| Package | Version | Role |
|---------|---------|------|
| `@reaatech/agent-mesh-classifier` | `1.0.0` | Gemini Flash intent classifier. Detects message language and classifies the user request against registered agents. |
| `@reaatech/agent-mesh-confidence` | `1.0.0` | Confidence-gated routing engine. Evaluates classifier output and decides whether to route, ask for clarification, or fall back. |
| `@reaatech/agent-handoff-routing` | `0.1.0` | Agent registry and capability-based router. Holds the four specialist agents and scores them by skill match, domain match, load, and language. |
| `@reaatech/agent-budget-llm-router-plugin` | `0.1.0` | Budget-aware LLM gating. Checks remaining spend budget before each draft-generation call and blocks when exhausted. |
| `@reaatech/agent-mesh-utils` | `1.0.0` | Circuit breaker with per-agent state. Prevents cascading failures by isolating unhealthy classifier or agent dispatches. |
---
## Provider Configuration
This recipe uses the OpenAI SDK with a configurable `baseURL`. To swap providers:
```bash
# OpenAI
OPENAI_BASE_URL=https://api.openai.com/v1
# Any OpenAI-compatible endpoint
OPENAI_BASE_URL=https://your-custom-endpoint.com/v1
```
The `LLM_MODEL` variable selects which model to use for draft generation.
---
## Testing
```bash
pnpm test
```
Runs vitest with coverage reporting. Tests use MSW (Mock Service Worker) for HTTP-level mocking of Slack, Gmail, and OpenAI APIs.
Coverage thresholds: 90% on lines, branches, functions, and statements.
---
## License
MIT — see [LICENSE](./LICENSE).