Internal Slack knowledge bot — answers employee questions over Notion, Confluence, and Google Drive with per-user, ACL-filtered retrieval. Every retrieval is bounded to what the asking user can already read in the source system; every answer cites its sources. The internal service handle is slack-knowledge-bot (npm package, OTel service.name, the /slack-knowledge-bot slash command, and the slack-knowledge-bot/<env>/* secret prefixes).
AI clients / agents start here: AGENTS.md. For the stack-wide view, see the Platform Reference.
A Slack bot that answers grounded questions over a company's knowledge sources. The ACL check runs after retrieval, against the asking user's own OAuth tokens — a document scoring high in the index is dropped if the user can't read it in the source system. There is no shared service-account view of company knowledge, so a query can only surface what that user could already see. Bedrock (Claude Sonnet for generation, Titan for embeddings) runs on-account via EKS Pod Identity; no source content leaves the account.
Built as a reusable subsystem: every external-IO service is a createXxx(deps) factory accepting typed ports (typeof fetch, a narrow RedisPort, a RetrievalBackend, or an AWS SDK client). src/index.ts constructs the real clients once and threads them through, so swapping Redis, the directory provider, the retrieval backend, or the LLM is a one-file change. See ARCHITECTURE.md for the bounded contexts and data flow.
npm install
cp .env.example .env # fill in values — see CLAUDE.md > Configuration
npm run dev # tsx watch on src/index.tsIn Slack: @slack-knowledge-bot what's our vacation policy?
Run the full local gate before pushing:
task ci # build + lint + typecheck + test + format:check + helm lint/template + docker buildShips as a eks-agent-platform Platform tenant. The trio:
chart/— the application Helm chart: Deployment + Service + Ingress (ALB, ACM TLS) + NetworkPolicy + ServiceAccount (Pod Identity) + ExternalSecret (ESO), plus the KEDA-scaled audit consumer, the opt-in PrometheusRule alerts, and a Grafana dashboard reconciled onto Amazon Managed Grafana. Per-env deltas inchart/values-{staging,production}.yaml.platform.yaml— three CRs declaring the tenant boundary: the cluster-scopedTenant(workplace, the owning team), theBudgetPolicythatPlatform.spec.budgetreferences, and thePlatformitself. TheBudgetPolicyandPlatformare applied into the team's CR-home namespacetenants-workplace; theTenantis cluster-scoped and takes no namespace. The operator provisions thetenants-slack-knowledge-botworkload namespace, its ResourceQuota, LimitRange, default-deny NetworkPolicy, the ArgoCD AppProject, and the<env>-slack-knowledge-bot-tenantIAM role.npm run platform:validatechecks the file against the vendored CRD schemas.gitops/applicationset-entry.yaml— the ApplicationSet entry registered intonanohype/eks-gitopsfor ArgoCD reconciliation.
The AWS substrate — the Aurora pgvector store, three DynamoDB tables, the Redis cache, the S3 audit bucket, and the FIFO audit queue — is declared in platform.yaml (spec.datastores) and provisioned by the generic tenant-substrate component in landing-zone. The operator generates the scoped datastore-access policy and binds the operator-owned tenant-runtime ServiceAccount to the <env>-slack-knowledge-bot-tenant role via a Pod Identity association. (The KMS key for per-user OAuth token envelope encryption is not declared: the same component mints one per tenant unconditionally, and the operator grants use of it through the tenant-key-access policy.) Apply platform.yaml once, wait for Ready, then ArgoCD owns the rollout: bump image.tag in the per-env values, commit, push.
This repo owns the application — the Slack pipeline, the RAG logic, the per-user ACL enforcement, and the tenant trio that deploys it. It does not own:
- AWS substrate (DynamoDB, SQS, S3, Aurora/pgvector, Redis, KMS, Secrets Manager) → the
tenant-substratecomponent inlanding-zone - Cluster addons (cert-manager, external-secrets, KEDA, the OpenTelemetry Collector, the Grafana operator, Loki, Tempo) →
eks-gitops. Rule evaluation and alert routing are cluster-side too, and are not currently deployed — see gap G-01 indocs/compliance-checklist.md
Apache-2.0.