Skip to content

Latest commit

Β 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Squad on AKS β€” AI Agent Teams on Kubernetes

License: MIT AKS Helm

Deploy AI agent teams to Azure Kubernetes Service using Helm, with Azure-native security (Workload Identity, Key Vault), KEDA autoscaling, and GitHub Actions CI/CD.

What is Squad? An AI team framework where specialized agents (Lead, Frontend, Backend, Tester, Monitor) collaborate on GitHub issues. Ralph is the work monitor that polls for new issues and dispatches work. Learn more β†’

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   AKS Cluster                    β”‚
β”‚                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Ralph        β”‚    β”‚  Agent Pods            β”‚  β”‚
β”‚  β”‚  (CronJob)    │───▢│  (spawned on demand)   β”‚  β”‚
β”‚  β”‚  */5 * * * *  β”‚    β”‚  Picard, Data, Worf... β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚         β”‚                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  K8s Secrets  │◀───│  Key Vault CSI Driver  β”‚  β”‚
β”‚  β”‚  (GH_TOKEN)   β”‚    β”‚  (Workload Identity)   β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  KEDA         β”‚    β”‚  Prometheus Metrics    β”‚  β”‚
β”‚  β”‚  (autoscaler) │◀───│  (optional)            β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                        β”‚
         β–Ό                        β–Ό
   GitHub Issues            Azure Key Vault
   (work queue)             (secrets store)

Key design decisions:

  • Ralph = CronJob β€” polls every 5 min, no always-on pod, concurrencyPolicy: Forbid replaces mutex
  • Agents = Jobs β€” spawned on demand, terminated when done (cost efficient)
  • Secrets via Key Vault β€” Workload Identity federation, no PATs in cluster
  • KEDA scaling β€” scale-to-zero when no work, burst on demand

⚑ Quick Start

Prerequisites

  • Azure CLI (az) with an active subscription
  • kubectl and helm v3
  • A GitHub PAT with repo, issues, workflow scopes

1. Create Azure Resources

# Set your variables
RESOURCE_GROUP="myapp-rg"
LOCATION="eastus"
CLUSTER_NAME="squad-aks"
ACR_NAME="myappsquadacr"  # must be globally unique

# Create resource group
az group create --name $RESOURCE_GROUP --location $LOCATION

# Create AKS cluster (with security features)
az aks create \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --node-count 1 \
  --node-vm-size Standard_D2s_v5 \
  --enable-managed-identity \
  --enable-addons azure-keyvault-secrets-provider \
  --enable-oidc-issuer \
  --enable-workload-identity \
  --no-ssh-key

# Create container registry
az acr create --resource-group $RESOURCE_GROUP --name $ACR_NAME --sku Basic

# Attach ACR to AKS (so AKS can pull images)
az aks update --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --attach-acr $ACR_NAME

# Get cluster credentials
az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME

2. Build and Push the Docker Image

# Option A: Build in the cloud (no local Docker needed!)
az acr build --registry $ACR_NAME --image squad-ralph:latest --file docker/Dockerfile .

# Option B: Build locally
docker build -f docker/Dockerfile -t $ACR_NAME.azurecr.io/squad-ralph:latest .
docker push $ACR_NAME.azurecr.io/squad-ralph:latest

3. Create Secrets

# For development: plain K8s Secret
kubectl create namespace squad
kubectl create secret generic squad-runtime-secrets \
  --namespace squad \
  --from-literal=GH_TOKEN=ghp_your_token_here

# For production: use Azure Key Vault (see docs/key-vault-setup.md)

πŸ’‘ Copilot CLI Auth: The GH_TOKEN must belong to a user with an active GitHub Copilot license. The Agency CLI uses this token for both GitHub API access and Copilot model calls. See docs/copilot-cli-auth.md for details.

4. Deploy with Helm

helm upgrade --install squad-agents ./helm/squad-agents \
  --namespace squad \
  --create-namespace \
  --set global.acrLoginServer=$ACR_NAME.azurecr.io \
  --set global.repository=your-org/your-repo \
  --set ralph.image.repository=squad-ralph \
  --set ralph.image.tag=latest

5. Verify

# Check the CronJob
kubectl get cronjobs -n squad

# Manually trigger a test run
kubectl create job ralph-test --from=cronjob/ralph -n squad

# Check logs
kubectl logs -l job-name=ralph-test -n squad --follow

πŸ“ Repository Structure

squad-on-aks/
β”œβ”€β”€ README.md                          # You are here
β”œβ”€β”€ helm/
β”‚   β”œβ”€β”€ squad/                         # Core Squad chart (coordinator + Ralph Deployment)
β”‚   β”‚   β”œβ”€β”€ Chart.yaml
β”‚   β”‚   β”œβ”€β”€ values.yaml
β”‚   β”‚   └── templates/
β”‚   β”‚       β”œβ”€β”€ _helpers.tpl
β”‚   β”‚       β”œβ”€β”€ configmap.yaml         # squad.config.ts + team/routing ConfigMap
β”‚   β”‚       β”œβ”€β”€ deployment.yaml        # Ralph Deployment (lightweight alternative)
β”‚   β”‚       β”œβ”€β”€ ralph-deployment.yaml  # Ralph Deployment (full, with emptyDir scratch)
β”‚   β”‚       β”œβ”€β”€ secret.yaml            # Optional K8s Secret (use Key Vault in prod)
β”‚   β”‚       └── service.yaml           # Ralph metrics/health Service
β”‚   └── squad-agents/                  # AKS-native chart (Ralph CronJob + Picard Deployment)
β”‚       β”œβ”€β”€ Chart.yaml
β”‚       β”œβ”€β”€ values.yaml                # ACR, Key Vault, KEDA, Workload Identity config
β”‚       └── templates/
β”‚           β”œβ”€β”€ _helpers.tpl
β”‚           β”œβ”€β”€ namespace.yaml         # Squad namespace with Workload Identity label
β”‚           β”œβ”€β”€ serviceaccount.yaml    # Workload Identity ServiceAccount
β”‚           β”œβ”€β”€ rbac.yaml              # Agent job spawning permissions
β”‚           β”œβ”€β”€ secret-provider-class.yaml  # Key Vault CSI integration
β”‚           β”œβ”€β”€ ralph-cronjob.yaml     # Ralph work monitor (CronJob)
β”‚           β”œβ”€β”€ picard-deployment.yaml # Lead agent Deployment + inline KEDA ScaledObject
β”‚           └── picard-scaledobject.yaml # Composite AND KEDA ScaledObject (Tier 2)
β”œβ”€β”€ keda/
β”‚   β”œβ”€β”€ github-rate-scaler.yaml        # TriggerAuthentication for GitHub API
β”‚   └── squad-scaledobject.yaml        # Standalone KEDA ScaledObject (3 triggers)
β”œβ”€β”€ infrastructure/
β”‚   β”œβ”€β”€ aks-automatic-squad.bicep      # AKS Automatic cluster + ACR + VNet + Log Analytics
β”‚   └── aks-automatic-squad.bicepparam # Default parameters (dev environment)
β”œβ”€β”€ docker/
β”‚   └── Dockerfile                     # Multi-stage: PowerShell 7 + Node.js + gh CLI
β”œβ”€β”€ scripts/
β”‚   └── ralph-watch.ps1                # Ralph's polling loop
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── deploy.yml                 # Build β†’ Push β†’ Deploy pipeline
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ what-is-squad.md               # Squad framework overview
β”‚   β”œβ”€β”€ deployment-timeline.md         # Real deployment log (warts and all)
β”‚   β”œβ”€β”€ key-vault-setup.md             # Production secrets guide
β”‚   β”œβ”€β”€ keda-scaling.md                # Autoscaling with KEDA
β”‚   β”œβ”€β”€ aks-automatic-vs-standard.md   # AKS SKU comparison
β”‚   └── troubleshooting.md             # Common issues and fixes
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ values-dev.yaml                # Development overrides
β”‚   └── values-prod.yaml               # Production overrides
└── LICENSE

⚠️ Warnings & Gotchas

Read this before deploying. These are real issues we hit during our first deployment.

πŸ”΄ Critical

Issue What Happens Fix
K8s label / in repo name Helm install fails with "invalid label value" Chart uses replace "/" "_" β€” already handled
CSI driver without Key Vault Pod stuck in ContainerCreating forever Set global.keyVaultName="" to skip CSI volumes
No Docker locally Can't build image on Azure DevBox/Codespace Use az acr build for cloud builds
Enterprise VM restrictions AKS create fails with "VM size not allowed" Check az vm list-skus --location <loc> first

🟑 Important

Issue What Happens Fix
AKS Automatic needs 16 vCPUs Creation fails on small/restricted subscriptions Use AKS Standard with smaller VMs
Duplicate env vars in CronJob K8s warning about hidden definitions Don't override SQUAD_AGENT_TYPE in ralph.env
ACR build uploads entire repo Build takes 30+ minutes with large repos Use minimal build context or .dockerignore
1000+ subscriptions az account list is slow, hard to find right sub Use --query filter: az account list --query "[?contains(name,'mysubname')]"

🟒 Notes

  • Node selectors are disabled by default. Uncomment in values.yaml when you add dedicated node pools.
  • KEDA is disabled by default. Enable after installing the KEDA add-on: az aks update --enable-keda
  • Picard (lead agent) is a Deployment, not a CronJob. It stays running. Disable with picard.enabled=false for cost savings.
  • GH_TOKEN needs repo, issues, workflow scopes minimum. For org repos, also needs read:org.

πŸ—οΈ Infrastructure as Code (Bicep)

The infrastructure/ directory contains Bicep templates for provisioning a complete AKS Automatic cluster:

# Create resource group + deploy AKS Automatic cluster with ACR, VNet, Log Analytics
az deployment group create \
  --resource-group squad-aks-rg \
  --template-file infrastructure/aks-automatic-squad.bicep \
  --parameters infrastructure/aks-automatic-squad.bicepparam

AKS Automatic includes KEDA built-in, managed node pools with autoscaling, and Azure RBAC integration.

Note: AKS Automatic requires 16+ vCPUs quota. If your subscription is limited, use AKS Standard instead (see docs/aks-automatic-vs-standard.md).

πŸ“Š KEDA Autoscaling

KEDA can scale Squad agents based on workload. The keda/ directory has standalone ScaledObjects, and the Helm chart includes inline KEDA support:

Tier Trigger Scaler Effort
1. Queue-based Open GitHub issues with squad labels Built-in github scaler Config only
2. Composite AND Issue count AND rate-limit headroom github + metrics-api with scalingModifiers.formula Config + metrics exporter
3. Token-based Copilot token budget remaining Custom Prometheus exporter ~30 LOC

See docs/keda-scaling.md for details.

πŸ” Security Model

Layer Mechanism
Pod identity Azure Workload Identity (OIDC federation)
Secrets Azure Key Vault via CSI driver (no secrets in YAML)
RBAC Minimal Role: batch/jobs create + pods/logs read
Container Non-root user, dropped capabilities, read-only where possible
Network Private cluster option, no public ingress needed
Image ACR with integrated vulnerability scanning

🀝 Contributing

Contributions welcome! This project came from a real deployment β€” if you hit something we didn't document, please open an issue or PR.

πŸ“„ License

MIT β€” see LICENSE.


Built by deploying AI agents to production with GitHub Copilot CLI. The deployment timeline documents every step, failure, and fix.

About

πŸš€ Deploy autonomous AI agent squads on AKS and Azure Container Apps β€” free tier first, scale later

Resources

Stars

11 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages