This repository has been archived on 2026-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
exec-aide/README.md
Adam Moussa e7da56270a Add SAM stack, Fargate listener, and shared modules
- 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
2026-04-30 17:40:58 -04:00

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:write scopes

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