Internal Slack DM assistant for Sea Haven Industries, powered by AWS Bedrock
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.
Find a file
Adam Moussa 94a837c08c
Enable QEMU for arm64 Docker builds (#29)
Fargate task runs ARM64 but GHA runner is x86_64 — without QEMU
the Docker image gets built for the wrong architecture, causing
exec format error at container startup.
2026-05-08 17:48:19 -04:00
.github Enable QEMU for arm64 Docker builds (#29) 2026-05-08 17:48:19 -04:00
bin Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
lambda fix: flat DM replies, clean up debug logging 2026-04-30 18:37:08 -04:00
lib feat: Alex rollout — persona, Socket Mode, payments, channels, App Home, unanswered questions 2026-04-30 16:38:54 -04:00
scripts feat: Alex rollout — persona, Socket Mode, payments, channels, App Home, unanswered questions 2026-04-30 16:38:54 -04:00
services/socket-mode fix: flat DM replies, clean up debug logging 2026-04-30 18:37:08 -04:00
.gitignore fix: flat DM replies, clean up debug logging 2026-04-30 18:37:08 -04:00
cdk.context.json Place QBO Lambdas in VPC for static outbound IP 2026-04-13 19:51:00 -04:00
cdk.json Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
package-lock.json Upgrade to TypeScript ~6.0.3 (#19) 2026-05-06 19:56:57 -04:00
package.json Upgrade to TypeScript ~6.0.3 (#19) 2026-05-06 19:56:57 -04:00
README.md feat: Alex rollout — persona, Socket Mode, payments, channels, App Home, unanswered questions 2026-04-30 16:38:54 -04:00
TODO.txt Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
tsconfig.json Upgrade to TypeScript ~6.0.3 (#19) 2026-05-06 19:56:57 -04:00

Seahaven Slack Bot — Alex

Internal Slack assistant for Sea Haven Industries, powered by AWS Bedrock. Employees can DM Alex or @mention Alex in any channel to ask about vendors, payments, work orders, purchase orders, Amazon sites, company policies, and more.

Architecture

Slack (WebSocket)
   │
   ▼
ECS Fargate (Socket Mode)                ← persistent WebSocket connection to Slack
   │
   ├── DM (message.im) ──────────────────┐
   ├── @mention (app_mention) ────────────┤
   │                              async invoke
   │                                      ▼
   │                              slack-processor Lambda    ← calls Bedrock Agent, logs to DynamoDB, posts reply
   │                                      │
   │                                      ▼
   │                              Bedrock Agent — Alex (Claude Sonnet 4.5)
   │                                      ├── Knowledge Base (AOSS + S3)
   │                                      ├── QBO_Lookup action group       ← QuickBooks vendor search (VPC, static IP)
   │                                      ├── Google_Maps_Lookup action group ← fallback vendor search
   │                                      └── WO_PO_Lookup action group     ← WO, PO, site, and payment lookups (DynamoDB direct)
   │
   └── App Home opened ──────────────────→ app-home Lambda  ← publishes Block Kit capabilities view

API Gateway (bot.seahaven.com)
   │
   └── GET /qbo/*
          ▼
       qbo-oauth Lambda (VPC, static IP)  ← OAuth 2.0 connect/callback/disconnect/launch
          Outbound IP: 52.202.83.13 (NAT Gateway in seahaven-vpc)

EventBridge (daily 02:00 UTC)
   │
   ├── notion-sync Lambda     ← exports Office Operations Notion pages → S3 → KB ingestion
   ├── po-sync Lambda         ← exports purchase-orders DynamoDB → S3 → KB ingestion
   └── workorder-sync Lambda  ← exports WorkOrders + Comments DynamoDB → S3 → KB ingestion

What Alex Can Do

  • Vendor Lookup — search QBO for existing vendors, KB for approved lists, Google Maps for new options
  • Payment & Invoice Status — check if a vendor has been paid, if an invoice is scheduled, look up by check number
  • Work Order Lookups — status, assignments, comments, and full history by WO number
  • Purchase Order Lookups — status, line items, supplier, and ship-to details by PO number
  • Site Lookups — Amazon facility address and details by site code, or list all sites in a state
  • Company Policies & SOPs — employee handbook, SA8000 compliance, and operational procedures

Vendor Query Priority

  1. QBO — existing vetted vendors in QuickBooks Online
  2. Knowledge Base — approved vendor lists in internal docs
  3. Google Maps — fallback for net-new vendor discovery

Stack

Resource Details
AWS Account 328440206208, us-east-1
CDK TypeScript, v2
LLM Claude Sonnet 4.5 (anthropic.claude-sonnet-4-5-20250929-v1:0)
Embeddings Amazon Titan Embed Text V2 (1024 dimensions)
Vector Store OpenSearch Serverless (VECTORSEARCH)
Socket Mode ECS Fargate (seahaven-socket-mode) — persistent WebSocket to Slack
Conversation Log DynamoDB seahaven-conversations (90-day TTL)
Unanswered Questions DynamoDB seahaven-unanswered-questions (180-day TTL)
Payment Data DynamoDB PaymentsDashboard (via payments-dashboard)
PO Data Source DynamoDB purchase-orders (via po-ingest)
Work Order Data Source DynamoDB WorkOrders + WorkOrderComments (via workorder-ingest)
Site Assignments DynamoDB verified-sites (auto-populated via po-ingest Streams pipeline)
VPC seahaven-vpc (vpc-0d3d4b67bd0cf8a68) — QBO Lambdas + Socket Mode
Static Outbound IP 52.202.83.13 (NAT Gateway for Intuit IP allowlist)
QBO OAuth URLs bot.seahaven.com/qbo/connect, /qbo/callback, /qbo/disconnect, /qbo/launch

Prerequisites

  • Node.js 22+
  • AWS CDK (npm install -g aws-cdk)
  • Docker Desktop (required for Lambda bundling and Socket Mode container build)
  • AWS credentials configured locally

Secrets Manager

These secrets must exist before deploying. The Slack, QBO, Maps, and app-level token secrets must be created manually before first deploy. The Notion secret is created automatically by CDK with a placeholder.

Secret Name Created Structure
seahaven/slack/credentials Manual (pre-deploy) { "botToken": "xoxb-...", "signingSecret": "..." }
seahaven/slack/app-level-token Manual (pre-deploy) Plaintext xapp-... token with connections:write scope
seahaven/qbo/oauth Manual (pre-deploy) { "clientId": "", "clientSecret": "", "refreshToken": "", "realmId": "" }
seahaven/google/maps-api-key Manual (pre-deploy) { "apiKey": "" }
seahaven/notion/api-key Auto (CDK) { "apiKey": "secret_..." }

Deployment

npm install
npx cdk bootstrap aws://328440206208/us-east-1   # first time only
npx cdk deploy

The deploy takes ~15 minutes on first run. The AOSS collection, vector index creation, and Docker image build are the slow steps.

Stack outputs after deploy:

  • KBDocsBucketName — S3 bucket to upload knowledge base documents
  • AgentId — Bedrock Agent ID (Alex)

Post-Deployment Setup

1. Upload knowledge base documents

Upload SA8000 compliance docs, SOPs, and the employee handbook to the S3 bucket printed in stack outputs.

aws s3 cp ./your-docs/ s3://<KBDocsBucketName>/ --recursive

2. Trigger KB sync

aws bedrock-agent start-ingestion-job \
  --knowledge-base-id <from Bedrock console> \
  --data-source-id <DataSourceId> \
  --region us-east-1

3. Configure Notion sync

  1. Create a Notion internal integration at Settings → Connections → Develop or manage integrations
  2. Name it seahaven-office-ops and associate it with the Office Operations teamspace
  3. Copy the integration token and update: Secrets Manager → seahaven/notion/api-key → Edit

4. Configure Slack app

In the Slack API dashboard:

  1. Basic Information → update Display Name to "Alex", upload avatar
  2. Socket Mode → enable, generate app-level token with connections:write scope
  3. Store the app-level token in Secrets Manager as seahaven/slack/app-level-token
  4. Event Subscriptions → enable (no Request URL needed with Socket Mode)
  5. Subscribe to bot events: message.im, app_mention, app_home_opened
  6. OAuth & Permissions → Bot Token Scopes: chat:write, im:history, app_mentions:read, channels:history, groups:history
  7. App Home → enable Home Tab and Messages Tab
  8. Reinstall app to workspace
  9. Invite Alex to channels: /invite @Alex

Project Structure

bin/
  seahaven-slack-bot.ts       CDK app entry point
lib/
  seahaven-slack-bot-stack.ts  Main stack
  constructs/
    knowledge-base.ts          Bedrock KB + AOSS + S3 (via @cdklabs L2 construct)
    bedrock-agent.ts           Alex — Bedrock Agent + QBO/Maps/WO-PO-Site-Payment action groups
    slack-handler.ts           Processor Lambda + App Home Lambda + QBO OAuth + API Gateway
    socket-mode.ts             ECS Fargate service running Slack Socket Mode client
    conversation-log.ts        DynamoDB conversation + unanswered questions tables
    notion-sync.ts             EventBridge daily cron + notion-sync Lambda
    po-sync.ts                 EventBridge daily cron + po-sync Lambda
    workorder-sync.ts          EventBridge daily cron + workorder-sync Lambda
services/
  socket-mode/                 Socket Mode ECS service (Dockerfile, TypeScript, @slack/socket-mode)
lambda/
  slack-processor/             Calls agent, writes DynamoDB, posts Slack reply
  app-home/                    Publishes Block Kit capabilities view to App Home tab
  qbo-oauth/                   OAuth 2.0 connect/callback/disconnect/launch for QuickBooks
  qbo-lookup/                  Bedrock action group — QuickBooks vendor search
  maps-lookup/                 Bedrock action group — Google Maps Places search
  wo-po-lookup/                Bedrock action group — WO, PO, site, and payment lookups (DynamoDB direct)
  notion-sync/                 Daily Notion → S3 export, triggers KB ingestion
  po-sync/                     Daily purchase-orders DynamoDB → S3 export, triggers KB ingestion
  workorder-sync/              Daily WorkOrders DynamoDB → S3 export, triggers KB ingestion
scripts/
  create-aoss-index.ts         Manual fallback for AOSS index creation (not needed in normal deploy)

Known Maintenance Items

  • QBO OAuth — the refresh token auto-rotates on every API call (persisted back to Secrets Manager). If the token ever expires (100 days of inactivity), reconnect via https://bot.seahaven.com/qbo/connect.
  • Notion sync runs daily at 02:00 UTC automatically. Manual trigger: invoke seahaven-notion-sync.
  • PO sync runs daily at 02:00 UTC. Scans purchase-orders DynamoDB table (from po-ingest). Manual trigger: invoke seahaven-po-sync.
  • Work order sync runs daily at 02:00 UTC. Scans WorkOrders and WorkOrderComments (from workorder-ingest). Manual trigger: invoke seahaven-workorder-sync.
  • Site assignments are auto-populated from the verified-sites DynamoDB table, maintained by the po-ingest DynamoDB Streams pipeline. No manual seeding required.
  • Unanswered questions are logged to seahaven-unanswered-questions when Alex detects it couldn't answer a question. Review via DynamoDB console — records have status: "pending" and 180-day TTL.
  • Socket Mode — the ECS Fargate task maintains a persistent WebSocket connection to Slack. Monitor via CloudWatch Logs (socket-mode log stream). The service auto-restarts on failure.