- SAM template with DynamoDB, two Lambdas (fetch-classify, daily-digest), ECS/Fargate for Socket Mode listener, EventBridge Scheduler - Gmail API integration with OAuth refresh and History API sync - Bedrock Haiku classification (HIGH/NORMAL/LOW) - Slack DM delivery with Block Kit formatting and threading - Socket Mode listener for two-way conversation (placeholder) - Setup script for Gmail OAuth token exchange - Slack app manifest for app creation
3.2 KiB
3.2 KiB
Exec Aide
Personal AI agent that monitors Adam Moussa's Gmail inbox, classifies emails by urgency using Claude Haiku (Bedrock), and delivers Slack alerts and daily digests.
Architecture
EventBridge (15 min) → fetch-classify Lambda → Gmail API → Bedrock Haiku → DynamoDB + Slack DM
EventBridge Scheduler (5 PM ET M-F) → daily-digest Lambda → DynamoDB + Gmail API → Slack DM
- exec-aide-fetch-classify: Polls Gmail via History API, classifies each new message, sends immediate Slack DM for HIGH priority items, tracks thread state for unanswered detection.
- exec-aide-daily-digest: Summarizes the day's high-priority items, bypassed work orders (emails not CC'ing work-orders@), and unanswered threads older than 24h.
- DynamoDB table
exec-aide: Single-table design with message records, thread tracking, and sync metadata. 90-day TTL.
Classification Rules
| Category | Trigger |
|---|---|
| HIGH | VIP sender, urgency keywords, escalation language, financial/legal matters |
| NORMAL | Standard business correspondence |
| LOW | Newsletters, automated notifications, marketing |
| Bypassed WO | Email to Adam without work-orders@ in TO/CC |
| Unanswered | Thread where Adam hasn't replied in 24h+ |
Prerequisites
- AWS CLI + SAM CLI
- Python 3.12
- Gmail API enabled in Google Cloud Console
- Slack app with
chat:write+im:writescopes
One-Time Setup
1. Gmail OAuth
# Install the setup dependency (not needed in Lambda)
pip install google-auth-oauthlib
# Download OAuth client JSON from Google Cloud Console, then:
python scripts/get_gmail_token.py --client-secrets-file path/to/client_secret.json
# Authorize as adam@seahavenind.com in the browser
# Copy the output into Secrets Manager
2. Secrets Manager
# Gmail OAuth (output from step 1)
aws secretsmanager create-secret --name exec-aide/gmail-oauth --secret-string '...'
# Slack bot token
aws secretsmanager create-secret --name exec-aide/slack-bot-token --secret-string 'xoxb-...'
3. SSM Parameters
aws ssm put-parameter --name /exec-aide/adam-email --value adam@seahavenind.com --type String
aws ssm put-parameter --name /exec-aide/adam-slack-user-id --value U01XXXXXXXX --type String
aws ssm put-parameter --name /exec-aide/vip-senders --value '["ceo@example.com"]' --type String
aws ssm put-parameter --name /exec-aide/vip-domains --value '["example.com"]' --type String
aws ssm put-parameter --name /exec-aide/work-order-addresses --value '["work-orders@seahavenind.com","work-orders@seahaven.com"]' --type String
aws ssm put-parameter --name /exec-aide/unanswered-threshold-hours --value 24 --type String
Deploy
cp samconfig.toml.example samconfig.toml # edit if needed
sam build
sam deploy
Manual Testing
# Trigger a poll
aws lambda invoke --function-name exec-aide-fetch-classify /dev/stdout
# Trigger the daily digest
aws lambda invoke --function-name exec-aide-daily-digest /dev/stdout
Updating VIP List or Keywords
Edit the SSM parameters directly — changes take effect on the next Lambda cold start (or within ~15 minutes):
aws ssm put-parameter --name /exec-aide/vip-senders --value '["new@example.com"]' --type String --overwrite