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 8b6e65bd20 Improve Slack formatting for WO/PO lookups
- Add markdown-to-Slack mrkdwn conversion in processor (** → *, ## → bold)
- Restructure lambda output with cleaner sections and date formatting
- Update agent instruction to present data concisely
2026-04-13 18:34:47 -04:00
bin Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
lambda Improve Slack formatting for WO/PO lookups 2026-04-13 18:34:47 -04:00
lib Improve Slack formatting for WO/PO lookups 2026-04-13 18:34:47 -04:00
scripts Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
.gitignore Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
cdk.context.json Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
cdk.json Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
package-lock.json feat: daily Notion → Bedrock KB sync 2026-04-12 22:21:39 -04:00
package.json feat: daily Notion → Bedrock KB sync 2026-04-12 22:21:39 -04:00
README.md docs: update README for PO and work order KB syncs 2026-04-13 15:42:27 -04:00
TODO.txt Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00
tsconfig.json Initial scaffold: Bedrock-backed Slack DM bot 2026-04-11 23:15:15 -04:00

Seahaven Slack Bot

Internal Slack DM assistant for Sea Haven Industries, powered by AWS Bedrock. Employees can ask questions about vendors, company policies, SOPs, and SA8000 compliance via direct message.

Architecture

Slack DM
   │
   ▼
API Gateway (bot.seahaven.com)
   │
   ▼
slack-webhook Lambda          ← verifies Slack signature, returns 200 immediately
   │ (async invoke)
   ▼
slack-processor Lambda        ← calls Bedrock Agent, logs to DynamoDB, posts reply
   │
   ▼
Bedrock Agent (Claude Sonnet 4.5)
   ├── Knowledge Base (AOSS + S3)    ← SA8000 docs, SOPs, employee handbook, Notion pages, POs, work orders
   ├── QBO_Lookup action group       ← QuickBooks vendor search
   └── Google_Maps_Lookup action group ← fallback vendor search

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

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)
Conversation Log DynamoDB seahaven-conversations (90-day TTL)
PO Data Source DynamoDB purchase-orders (via po-ingest)
Work Order Data Source DynamoDB WorkOrders + WorkOrderComments (via workorder-ingest)
Webhook URL https://bot.seahaven.com/slack/events

Prerequisites

  • Node.js 22+
  • AWS CDK (npm install -g aws-cdk)
  • Docker Desktop (required by @cdklabs/generative-ai-cdk-constructs for Lambda bundling)
  • AWS credentials configured locally

Secrets Manager

These secrets must exist before deploying. The Slack, QBO, and Maps secrets must be created manually before first deploy. The Notion secret is created automatically by CDK with a placeholder — update it after deploy.

Secret Name Created Structure
seahaven/slack/credentials Manual (pre-deploy) { "botToken": "xoxb-...", "signingSecret": "..." }
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 and vector index creation are the slow steps — both handled automatically.

Stack outputs after deploy:

  • KBDocsBucketName — S3 bucket to upload knowledge base documents
  • AgentId — Bedrock Agent ID
  • SlackWebhookUrl — URL to register in Slack app settings
  • NotionSecretName — Secrets Manager secret to populate with your Notion integration token

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. Supported formats: PDF, DOCX, TXT, HTML, CSV, XLSX.

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

2. Trigger KB sync

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

Or trigger from the Bedrock console: Knowledge Bases → seahaven-kb → Sync.

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 (secret_...)
  4. In AWS Console: Secrets Manager → seahaven/notion/api-key → Edit — set apiKey to your token
  5. Run a manual test:
aws lambda invoke \
  --function-name seahaven-notion-sync \
  --region us-east-1 \
  --log-type Tail \
  --query 'LogResult' \
  --output text \
  /dev/null | base64 -d

The sync runs automatically every day at 02:00 UTC via EventBridge.

4. Configure Slack app

In the Slack API dashboard:

  1. Event Subscriptions → enable → set Request URL to https://bot.seahaven.com/slack/events
  2. Subscribe to bot event: message.im
  3. OAuth & Permissions → Bot Token Scopes: chat:write, im:history
  4. App Home → Messages Tab → enable, allow users to send messages
  5. Reinstall to workspace if prompted

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          Bedrock Agent + QBO/Maps action groups
    slack-handler.ts          API Gateway + webhook/processor Lambdas
    conversation-log.ts       DynamoDB table
    notion-sync.ts            EventBridge daily cron + notion-sync Lambda + Secrets Manager
    po-sync.ts                EventBridge daily cron + po-sync Lambda
    workorder-sync.ts         EventBridge daily cron + workorder-sync Lambda
lambda/
  slack-webhook/              Verifies Slack signature, fires processor async
  slack-processor/            Calls agent, writes DynamoDB, posts Slack reply
  qbo-lookup/                 Bedrock action group — QuickBooks vendor search
  maps-lookup/                Bedrock action group — Google Maps Places search
  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 refresh token expires after 100 days of inactivity. Rotate via the Intuit OAuth Playground and update the seahaven/qbo/oauth secret.
  • Notion sync runs daily at 02:00 UTC automatically. To trigger an immediate sync, invoke seahaven-notion-sync manually via the Lambda console or CLI.
  • PO sync runs daily at 02:00 UTC. Scans the purchase-orders DynamoDB table (from po-ingest) and exports each PO as markdown to the KB. Manual trigger: invoke seahaven-po-sync.
  • Work order sync runs daily at 02:00 UTC. Scans WorkOrders and WorkOrderComments DynamoDB tables (from workorder-ingest) and exports each work order + comment history as markdown to the KB. Manual trigger: invoke seahaven-workorder-sync.
  • KB sync for manual S3 uploads (non-Notion docs) must still be triggered manually after uploading new documents to the S3 bucket.