Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Datalfred

A Slack-native AI assistant for your AWS data lake. Datalfred lets your team query data and investigate ingestion pipelines in plain English, directly from Slack.

Ask @datalfred what tables are in the sales database? and get an answer. Ask why did last night's ingestion fail? and get logs, root cause, and a one-click redrive — without leaving Slack, opening the AWS console, or writing SQL.

Built on Strands Agents and AWS Bedrock. Deployed as a single Lambda. Terraform included.


What it does

  • Query the data lake — explores the Glue Data Catalog, writes the SQL, runs it on Athena, returns the result.
  • Investigate pipelines — inspects Step Functions, ECS, EMR Serverless and CloudWatch logs to explain why a job failed.
  • Operate (carefully) — can redrive failed Step Function executions or toggle EventBridge schedules, but only when a user explicitly asks.
  • Stays cheap — pick between three Bedrock model tiers (Claude Opus 4.7 / Sonnet 4.6 / Haiku 4.5); the agent reports token cost after every conversation.
  • Stays safe — Slack signature validation, user allowlist, and an automatic kill-switch if the bot starts receiving a flood of invalid requests (a sign someone is probing the endpoint).

Architecture

Slack ──► Lambda URL ──► main agent ──┬─► data analyst  (Glue + Athena)
                                      └─► run guy       (Step Functions / ECS / EMR / CloudWatch)
                                            │
                                            └─► AWS Bedrock (Claude)
  • Main agent (code/chatbot/main_agent.py) — orchestrates the conversation, routes to sub-agents, keeps a 20-message sliding window, persists sessions to S3, tracks token cost.
  • Sub-agents (code/chatbot/sub_agents/) — data_analyst for SQL/catalog work, run_guy for AWS introspection. Each is a Strands @tool with its own system prompt.
  • Slack layer (code/chatbot/slack.py) — HMAC signature check, threaded replies, event filtering.
  • Failsafe Lambda (code/chatbot_failsafe/main.py) — a second, isolated Lambda that disables the main one if a CloudWatch alarm detects abuse (by setting its reserved concurrency to 0).

Quick start

You need an AWS account with Bedrock access (Claude Opus 4.7, Sonnet 4.6, Haiku 4.5 enabled in eu-west-1), Terraform, Docker, and Poetry 2.x.

1. Deploy the infrastructure

cd iac
cp terraform.tfvars.example terraform.tfvars   # then edit it
cp backend.hcl.example      backend.hcl        # then edit it

terraform init -backend-config=backend.hcl
terraform workspace new prod
terraform apply
terraform output lambda_function_url   # you'll need this for Slack

Terraform builds the Docker image, pushes it to ECR, provisions the Lambda, Bedrock inference profiles, S3 bucket, Athena workgroup, CloudWatch alarms, and the failsafe.

2. Create the Slack app

Go to api.slack.com/appsCreate New App → From manifest, paste the manifest below, replacing $APPLICATION_NAME and $AWS_LAMBDA_FUNCTION_URL:

{
  "display_information": { "name": "$APPLICATION_NAME" },
  "features": {
    "app_home": { "messages_tab_enabled": true, "messages_tab_read_only_enabled": false },
    "bot_user": { "display_name": "$APPLICATION_NAME" }
  },
  "oauth_config": {
    "scopes": { "bot": [
      "app_mentions:read", "chat:write", "chat:write.customize", "commands",
      "im:read", "im:write", "im:history", "mpim:history",
      "incoming-webhook", "reactions:read", "reactions:write"
    ]}
  },
  "settings": {
    "event_subscriptions": {
      "request_url": "$AWS_LAMBDA_FUNCTION_URL",
      "bot_events": ["app_mention", "message.im"]
    }
  }
}

Install the app, then store its credentials in Secrets Manager under the name {project_name}_slack_alerting_prod:

{
  "token":            "xoxb-...",
  "signing_secret":   "...",
  "slack_channel_id": "C01234567"
}

3. Talk to it

DM the bot or mention it in a channel where it's invited. Access is restricted to the Slack user IDs listed in authorized_slack_users — leave that variable empty to allow any Slack user.

Prefix any message with /model large|medium|small to override the model tier for that single message — e.g. @datalfred /model large explain this failure in depth. Without the prefix, the bot defaults to small (Haiku 4.5).

Running locally

cd code
poetry install --with agent

poetry run chatbot -p poc -s prod -m large                          # interactive
poetry run chatbot -p poc -s prod -m medium -up "list databases"    # one-shot
poetry run chatbot -p poc -s prod -id my-session                    # resumable session (persisted to S3)

Flags: -m large|medium|small picks the Bedrock tier (default small), -d prints sub-agent debug output.

Configuration

Var (Lambda env) Set by Purpose
PROJECT_NAME, STAGE_NAME Terraform Resource naming: {project}_chatbot_{stage}_*
SLACK_SECRET_ARN Terraform ARN of the Secrets Manager secret above
AUTHORIZED_SLACK_USERS terraform.tfvars Comma-separated Slack user IDs; empty = open to all

Three Bedrock inference profiles are provisioned per stage (*_large, *_medium, *_small); swap models in iac/bedrock_inference_profile.tf. Pricing used for cost estimation is hardcoded in main_agent.py — update it there if Bedrock prices change.

Safety model

  • Read-only by default. The run_guy agent's system prompt forbids any mutation. The only allowed writes are Step Function redrives and EventBridge schedule toggles, both requiring an explicit user request.
  • Slack signature validation on every request, with HMAC and timestamp checks.
  • User allowlist via AUTHORIZED_SLACK_USERS (optional — leave empty to allow any Slack user).
  • Kill switch. If the bot receives more than 100 invalid-signature requests in an hour (a sign someone is probing the endpoint), a CloudWatch alarm triggers a separate failsafe Lambda that disables the main bot by setting its reserved concurrency to 0. Operators get an email.
  • Timeout failsafe. The Lambda aborts when fewer than 3 minutes of its 15-minute budget remain, posting a graceful message to Slack instead of timing out mid-tool-call.
  • No retry on tool errors (except SQL syntax fixes), to prevent runaway costs from agent loops.

Repository layout

code/
├── chatbot/                # main Lambda + CLI
│   ├── main_agent.py
│   ├── lambda_entrypoint.py
│   ├── slack.py
│   └── sub_agents/{data_analyst,run_guy}.py
├── chatbot_failsafe/main.py
├── pyproject.toml
└── Dockerfile
iac/                        # Terraform (eu-west-1, S3+DynamoDB backend, workspace = stage)

Limitations

  • AWS region is eu-west-1 by default — change in iac/terraform.tf.
  • The Terraform default workspace produces stage_name=default. Always create an explicit workspace before applying.
  • Sessions are keyed by Slack user ID (one history per user, shared across threads).
  • CI is GitLab-only; the public repo is a mirror.
  • Cost numbers are estimates, not billing-grade.

License

MIT. See LICENSE.

About

Datalfred is an AI-powered chatbot designed to assist users in interacting with a data lake platform on AWS using Slack messages.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages