Skip to content

Setup

Prerequisites

  • .NET 10 SDK
  • GitHub token with repo access
  • Discord bot token (ATL-E Agent bot)

Discord Bot Setup

ATL-E uses a Discord bot (not webhooks) to read and write messages.

Bot: ATL-E Agent in Discord Developer Portal

Setting Value
Name ATL-E Agent
Public Bot No (unchecked)
Install Link None
Intents Presence, Server Members, Message Content (all 3)
Permissions Administrator
Server Dashecorp Agents (1477259107684847708)
Bitwarden "Discord Bot Token (ATL-E)"

To recreate (if token is lost):

  1. Discord Developer Portal → New Application → ATL-E Agent
  2. Installation → Install Link → None
  3. Bot → uncheck Public Bot
  4. Bot → enable all 3 Privileged Gateway Intents
  5. Bot → Reset Token → save to Bitwarden
  6. OAuth2 → URL Generator → scope: bot → permission: Administrator → open URL → add to server

Local Development

# Clone
git clone https://github.com/Stig-Johnny/atl-agent.git
cd atl-agent

# Build
dotnet build

# Test
dotnet test

# Run locally (needs env vars)
export GITHUB_TOKEN=ghp_...
export DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
export STATE_FILE=./state.json
dotnet run --project src/AtlAgent

Configuration

Config files live in config/:

File Purpose
default.yaml Timeouts and cooldown values
repos.yaml List of monitored repositories
agent-map.yaml Agent capabilities, Discord routing, performance scores

GitOps Deployment

ATL-E is deployed via ArgoCD on the Dell k3s cluster. The ArgoCD Application syncs from deploy/k8s/ in this repo.

cluster-gitops (app-of-apps)
  └── apps/atl-agent.yaml → ArgoCD Application
        └── Stig-Johnny/atl-agent.git / deploy/k8s/
              ├── namespace.yaml
              ├── deployment.yaml (CronJob)
              ├── configmap.yaml
              ├── pvc.yaml
              ├── secret.yaml (SealedSecret)
              └── ghcr-pull-sealedsecret.yaml

Changes to deploy/k8s/ on main are auto-synced by ArgoCD. No manual kubectl apply needed.

Manual deploy (first time or debugging)

kubectl apply -f deploy/k8s/namespace.yaml
kubectl apply -f deploy/k8s/pvc.yaml
kubectl apply -f deploy/k8s/configmap.yaml
kubectl apply -f deploy/k8s/secret.yaml
kubectl apply -f deploy/k8s/ghcr-pull-sealedsecret.yaml
kubectl apply -f deploy/k8s/deployment.yaml

Secrets Management

All secrets are managed via SealedSecrets (Bitnami). Encrypted secrets are committed to git in deploy/k8s/secret.yaml. The sealed-secrets-controller in kube-system decrypts them at apply time.

Current secrets

Key Source Purpose
GITHUB_TOKEN Bitwarden: "GitHub PAT (Claude)" GitHub API access for polling repos
DISCORD_WEBHOOK_URL Discord #admin channel webhook Default notification channel
DISCORD_WEBHOOK_IBUILD_E Discord #ibuild-e channel webhook iBuild-E specific notifications
DISCORD_WEBHOOK_PI_E Discord #pi-e channel webhook Pi-E specific notifications
DISCORD_WEBHOOK_VOLT_E Discord #volt-e channel webhook Volt-E specific notifications
DISCORD_WEBHOOK_REVIEW_E Discord #review-e channel webhook Review-E specific notifications

Updating secrets

# Create a temporary secret YAML with new values
kubectl create secret generic atl-agent-secrets \
  --namespace atl-agent \
  --from-literal=GITHUB_TOKEN=ghp_... \
  --from-literal=DISCORD_WEBHOOK_URL=https://... \
  --dry-run=client -o json \
  | kubeseal --format yaml \
    --controller-namespace kube-system \
    --controller-name sealed-secrets-controller \
  > deploy/k8s/secret.yaml

# Commit and push — ArgoCD syncs automatically
git add deploy/k8s/secret.yaml
git commit -m "chore: update sealed secrets"
git push

Why SealedSecrets (not SOPS)

  • SealedSecrets controller already deployed (running 290+ days)
  • Native Kubernetes resource — ArgoCD syncs it directly, no plugins needed
  • All existing secrets across the cluster already use SealedSecrets
  • Simpler than SOPS (no age/GPG key management, no decrypt step)

Docker Image

The Docker image is built on the Dell k3s node using buildah and pushed to ghcr.io/stig-johnny/atl-agent:latest.

# Cross-compile from macOS
dotnet publish src/AtlAgent/AtlAgent.csproj -c Release -r linux-x64 --self-contained -o /tmp/atl-publish

# Build on Dell (SSH)
ssh -i ~/.ssh/dell-stig-1 claude@100.95.212.93
sudo buildah build -t ghcr.io/stig-johnny/atl-agent:latest /path/to/publish
sudo buildah push ghcr.io/stig-johnny/atl-agent:latest docker://ghcr.io/stig-johnny/atl-agent:latest

Image architecture

The Dell k3s node is linux/amd64. The Docker image must be built for amd64, not arm64. Building locally on Apple Silicon creates arm64 images. Use dotnet publish -r linux-x64 + build on the Dell, or use a CI runner with amd64 architecture.

Environment Variables

Variable Required Description
GITHUB_TOKEN Yes GitHub API token with repo access
DISCORD_WEBHOOK_URL Yes Default Discord webhook for notifications
STATE_FILE No Path to state file (default: /data/state.json)
DISCORD_WEBHOOK_IBUILD_E No Agent-specific webhook for iBuild-E
DISCORD_WEBHOOK_PI_E No Agent-specific webhook for Pi-E
DISCORD_WEBHOOK_VOLT_E No Agent-specific webhook for Volt-E
DISCORD_WEBHOOK_REVIEW_E No Agent-specific webhook for Review-E