Setup¶
ATL-E runs on the Automate-E runtime. No custom code to build — just configuration.
Prerequisites¶
- Kubernetes cluster with ArgoCD
- Automate-E Helm chart deployed (via
Stig-Johnny/automate-e) - Discord bot token (ATL-E Agent app in Discord Developer Portal)
- Anthropic API key
- GitHub classic PAT with
reposcope (for cross-org access) - Discord webhook URL for #admin channel
1. Create Namespace and Secrets¶
kubectl create namespace atl-e
kubectl create secret generic atl-e-secrets -n atl-e \
--from-literal=discord-bot-token=<bot-token> \
--from-literal=anthropic-api-key=<api-key> \
--from-literal=database-url="postgresql://atl_e:<db-password>@postgres.atl-e.svc.cluster.local:5432/atl_e" \
--from-literal=github-token=<github-pat> \
--from-literal=github-webhook-secret=<webhook-secret> \
--from-literal=discord-webhook-url=<webhook-url> \
--from-literal=postgres-password=<db-password>
# Copy GHCR pull secret from another namespace
kubectl get secret ghcr-pull-secret -n automate-e -o json | \
python3 -c "import sys,json; d=json.load(sys.stdin); d['metadata']={'name':'ghcr-pull-secret','namespace':'atl-e'}; print(json.dumps(d))" | \
kubectl apply -f -
2. Create Cloudflare Tunnel (optional, for dashboard)¶
# Create tunnel via Cloudflare API
CF_TOKEN=<cloudflare-api-token>
CF_ACCOUNT=<account-id>
TUNNEL_ID=$(curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT/cfd_tunnel" \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"atl-e-dashboard","tunnel_secret":"'$(openssl rand -base64 32)'"}' | \
python3 -c "import sys,json; print(json.load(sys.stdin)['result']['id'])")
# Configure tunnel routing
curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT/cfd_tunnel/$TUNNEL_ID/configurations" \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"config":{"ingress":[{"hostname":"atl-e.dashecorp.com","service":"http://atl-e-automate-e.atl-e.svc.cluster.local:3000"},{"service":"http_status:404"}]}}'
# Get tunnel token and create K8s secret
TUNNEL_TOKEN=$(curl -s "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT/cfd_tunnel/$TUNNEL_ID/token" \
-H "Authorization: Bearer $CF_TOKEN" | python3 -c "import sys,json; print(json.load(sys.stdin)['result'])")
kubectl create secret generic cloudflared-atl-e-token -n atl-e \
--from-literal=token=$TUNNEL_TOKEN
# Add DNS CNAME record
ZONE_ID=<zone-id-for-dashecorp.com>
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"type\":\"CNAME\",\"name\":\"atl-e\",\"content\":\"$TUNNEL_ID.cfargotunnel.com\",\"proxied\":true}"
3. Create ArgoCD Application¶
Add to cluster-gitops/apps/atl-e-argocd.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: atl-e
namespace: argocd
spec:
project: default
sources:
- repoURL: https://github.com/Stig-Johnny/automate-e.git
targetRevision: HEAD
path: charts/automate-e
helm:
releaseName: atl-e
valueFiles:
- $values/deploy/automate-e/values.yaml
- repoURL: https://github.com/Stig-Johnny/atl-agent.git
targetRevision: HEAD
ref: values
destination:
server: https://kubernetes.default.svc
namespace: atl-e
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
4. Verify¶
# Check pods
kubectl get pods -n atl-e
# Expected: gateway (1), worker (2), redis (1), cloudflared (1), cron (periodic)
# Check logs
kubectl logs -n atl-e deploy/atl-e-automate-e-gateway --tail=10
# Should show: MCP connected, Discord logged in, listening on #admin
# Test dashboard
curl https://atl-e.dashecorp.com/api/health
5. Discord Bot Setup¶
The ATL-E Agent Discord app needs:
- Message Content Intent enabled
- Public Bot disabled
- Install Link set to None
- Bot added to Dashecorp Agents server with permissions: View Channels, Send Messages, Create Public Threads, Send Messages in Threads, Read Message History
6. Configure GitHub Webhooks¶
Point all monitored repos to the ATL-E webhook receiver:
WEBHOOK_SECRET=<your-webhook-secret>
for repo in nutri-e cutie star-rewards fast-e count-e drink-e heart-e claude-3; do
gh api repos/Stig-Johnny/$repo/hooks -X POST \
-f "config[url]=https://atl-e.dashecorp.com/webhook/github" \
-f "config[content_type]=json" \
-f "config[secret]=$WEBHOOK_SECRET" \
-f "events[]=pull_request" -f "events[]=pull_request_review" \
-f "events[]=check_run" -f "events[]=issues" -f "events[]=issue_comment"
done
# ios-sdk (different org)
gh api repos/cuti-e/ios-sdk/hooks -X POST \
-f "config[url]=https://atl-e.dashecorp.com/webhook/github" \
-f "config[content_type]=json" \
-f "config[secret]=$WEBHOOK_SECRET" \
-f "events[]=pull_request" -f "events[]=pull_request_review" \
-f "events[]=check_run" -f "events[]=issues" -f "events[]=issue_comment"