Deploy Agent Barn and its supporting services to an existing Kubernetes cluster using the Helm charts and Helmfile configuration included with the project.
This guide uses the production namespace agent-farm. The repository and product are named Agent Barn, but the Kubernetes namespaces deliberately retain the earlier agent-farm name.
What you will deploy
By the end of this guide, you will have:
- The Agent Barn API, Ingest API, background worker, and web application
- PostgreSQL databases for Agent Barn, LiteLLM, and Firecrawl
- Redis for background processing
- LiteLLM connected to OpenRouter
- A self-hosted Firecrawl service
- Prometheus, Grafana, Alertmanager, and Agent Barn dashboards
- TLS ingress for the web application, API, and Grafana
- A Kubernetes namespace in which Agent Barn can create agent workloads
- Persistent storage for application databases, monitoring, and agents
Starting an Agent later creates a dedicated Deployment, Service, Secret, ConfigMap, PVC, and related runtime configuration inside the same namespace.
Before you begin
Kubernetes cluster
You need an existing Kubernetes cluster with:
- A working
kubectlcontext - A default StorageClass, or the name of a StorageClass you can select
- Support for dynamically provisioned
ReadWriteOncevolumes - A Traefik ingress controller with the
traefikIngressClass - cert-manager
- A cert-manager ClusterIssuer named
letsencrypt-http01 - DNS control for the web application, API, and Grafana hostnames
- Enough capacity for the platform services and the agents you plan to run
| Workload | Default storage |
|---|---|
| Agent Barn PostgreSQL | 5 GiB |
| LiteLLM PostgreSQL | 2 GiB |
| Firecrawl PostgreSQL | 2 GiB |
| Prometheus | 10 GiB |
| Each running Agent | 1 GiB |
Plan additional capacity for database growth, monitoring retention, backups, and simultaneous agent workloads.
Command-line tools
Install these tools on the machine from which you will deploy:
- kubectl
- Helm 3
- Helmfile
- The helm-diff plugin
- OpenSSL, for generating secrets
Confirm that they are available:
kubectl version --client
helm version
helmfile --version
helm plugin listIf diff is not listed as a Helm plugin, install it:
helm plugin install https://github.com/databus23/helm-diffExternal accounts and credentials
You will need:
- An OpenRouter API key
- Credentials for the container registry holding the Agent Barn images
- A Slack incoming-webhook URL for deployment alerts
- Three DNS hostnames pointing to your ingress endpoint
The following integrations are optional:
- Cloudflare Email Sending for invitations, password resets, and notifications
- A Google OAuth web client for Google Workspace authentication
Kubernetes permissions
The deployment identity must be able to manage the Helm releases and their resources in agent-farm.
The default production bootstrap also applies:
- The
agent-farmNamespace - The
agent-farm-userServiceAccount - A Role and RoleBinding used by deployment and monitoring jobs
The kubeconfig mounted into the Agent Barn API must allow it to manage agent Deployments, Services, PVCs, Secrets, ConfigMaps, and Pods in the target namespace. It also needs access to pod logs, exec, and port-forward operations used by Agent health and log features.
Verify the cluster
Confirm that kubectl is connected to the intended cluster:
kubectl config current-context
kubectl cluster-info
kubectl get nodesCheck the required cluster services:
kubectl get ingressclass traefik
kubectl get clusterissuer letsencrypt-http01
kubectl get storageclassCheck whether your deployment identity can create and manage resources:
kubectl auth can-i create namespaces
kubectl auth can-i create deployments --namespace agent-farm
kubectl auth can-i create services --namespace agent-farm
kubectl auth can-i create secrets --namespace agent-farm
kubectl auth can-i create persistentvolumeclaims --namespace agent-farm
kubectl auth can-i create ingresses --namespace agent-farmIf your identity cannot create namespaces, ask the cluster administrator to create agent-farm and provision the required namespace-scoped deployment identity before continuing.
Get the deployment files
Use a release bundle
Recommended
The recommended deployment artifact is the Agent Barn release bundle. It contains:
- The Helm charts
helmfile.yaml.gotmpl- Kubernetes bootstrap manifests
deploy.sh- A release-specific
.env.deploywith compatible image tags
Download the bundle for the release you want to deploy, then extract it:
tar -xzf agent-barn-deploy-RELEASE_TAG.tar.gz
cd agent-barn-deployReplace RELEASE_TAG with the release you downloaded.
Deploy from the source repository
You can also use the deployment files directly from the public repository:
git clone https://github.com/aai-labs/agent-barn.git
cd agent-barn
git checkout RELEASE_TAG
cp .env.deploy.spec .env.deployUse a released tag or a commit whose API, UI, Hermes, and OpenClaw image tags are available in your registry.
Configure the deployment
Open .env.deploy in a text editor and replace every required blank value.
The file is sourced as a shell environment file. Use plain KEY=value entries and avoid spaces around the equals sign.
Cluster and namespace
| Variable | Requirement | Description |
|---|---|---|
KUBECONFIG | Required | Absolute path to the kubeconfig used by kubectl, Helm, and Helmfile |
NAMESPACE | Required | Target namespace; use agent-farm for the production deployment |
POD_KUBECONFIG_B64 | Optional | Base64 kubeconfig used by the API; when omitted, deploy.sh derives it from KUBECONFIG |
STORAGE_CLASS | Optional | StorageClass for databases, Prometheus, and Agent PVCs; leave empty to use the cluster default |
Use an absolute kubeconfig path:
KUBECONFIG=/home/your-user/.kube/agent-barn-production.yaml
NAMESPACE=agent-farm
STORAGE_CLASS=REPLACE_WITH_STORAGE_CLASSContainer registry
| Variable | Requirement | Description |
|---|---|---|
REGISTRY_PREFIX | Required | Registry path prepended to all Agent Barn image repositories |
REGISTRY_SERVER | Required | Registry hostname used for authentication |
REGISTRY_USERNAME | Required | Registry username |
REGISTRY_PASSWORD | Required | Registry password or access token |
API_IMAGE_REPOSITORY | Required | API image repository |
UI_IMAGE_REPOSITORY | Required | UI image repository |
HERMES_IMAGE_REPOSITORY | Required | Hermes runtime image repository |
OPENCLAW_IMAGE_REPOSITORY | Required | OpenClaw runtime image repository |
API_IMAGE_TAG | Required | Released API image tag |
UI_IMAGE_TAG | Required | Released UI image tag |
HERMES_IMAGE_TAG | Required | Compatible Hermes image tag |
OPENCLAW_IMAGE_TAG | Required | Compatible OpenClaw image tag |
If you downloaded a release bundle, the registry paths and image tags should already be populated. Add the credentials supplied for that registry without changing the pinned versions.
A GitHub token is not required to read the public agent-barn or aai-cli repositories. Kubernetes only needs credentials for the registry from which it pulls the deployment images.
Database configuration
Agent Barn deploys three independent PostgreSQL instances:
| Variable | Requirement | Default user or database |
|---|---|---|
POSTGRES_APP_USER | Required | agentfarm |
POSTGRES_APP_PASSWORD | Required | Generate a strong password |
POSTGRES_APP_DB | Required | agentfarm |
POSTGRES_LITELLM_USER | Required | litellm |
POSTGRES_LITELLM_PASSWORD | Required | Generate a different strong password |
POSTGRES_LITELLM_DB | Required | litellm |
POSTGRES_FIRECRAWL_USER | Required | firecrawl |
POSTGRES_FIRECRAWL_PASSWORD | Required | Generate a different strong password |
POSTGRES_FIRECRAWL_DB | Required | firecrawl |
Generate independent passwords:
openssl rand -hex 24
openssl rand -hex 24
openssl rand -hex 24Store these values in your secret manager before deploying.
LiteLLM and OpenRouter
| Variable | Requirement | Description |
|---|---|---|
LITELLM_MASTER_KEY | Required | Stable LiteLLM administrative key beginning with sk- |
OPENROUTER_API_KEY | Required | API key issued by OpenRouter |
AGENT_DEFAULT_MODEL | Optional | Default in litellm/openrouter/<model> format |
AGENT_MODEL_ALLOWLIST | Optional | Comma-separated model patterns |
Generate a LiteLLM master key:
echo "sk-$(openssl rand -hex 24)"Keep this key stable. LiteLLM uses it when managing the virtual keys assigned to Agents.
Agent Barn application secrets
| Variable | Requirement | Description |
|---|---|---|
SECRET_SIGNING_KEY | Required | Signs Agent Barn authentication tokens |
AGENT_TOKEN_ENCRYPTION_KEY | Required | Fernet-compatible key used to encrypt stored credentials |
PLATFORM_ADMIN_CREDENTIALS | Required | Initial platform administrator in email:password format |
ENVIRONMENT | Required | Deployment name stamped into the application and alerts |
FIRECRAWL_API_KEY | Required | Shared key protecting the internal Firecrawl service |
Generate the signing key:
openssl rand -hex 32Generate the Fernet-compatible encryption key:
openssl rand -base64 32 | tr '+/' '-_' | tr -d '\n'Generate the Firecrawl key:
openssl rand -hex 24Configure the administrator and environment:
PLATFORM_ADMIN_CREDENTIALS=[email protected]:REPLACE_WITH_STRONG_PASSWORD
ENVIRONMENT=productionThe administrator password must contain at least eight characters, including an uppercase letter, a lowercase letter, and a digit.
Public hostnames
| Variable | Requirement | Example |
|---|---|---|
UI_HOST | Required | agentbarn.example.com |
API_HOST | Required | api.agentbarn.example.com |
WEB_APP_URL | Required | https://agentbarn.example.com |
GRAFANA_HOST | Required | grafana.agentbarn.example.com |
Configure hostnames without URL schemes in the *_HOST values:
UI_HOST=agentbarn.example.com
API_HOST=api.agentbarn.example.com
WEB_APP_URL=https://agentbarn.example.com
GRAFANA_HOST=grafana.agentbarn.example.comMonitoring
The current Helmfile requires:
| Variable | Requirement | Description |
|---|---|---|
SLACK_ALERTS_WEBHOOK_URL | Required | Slack incoming webhook used by Alertmanager |
GRAFANA_ADMIN_PASSWORD | Required | Initial Grafana administrator password |
GRAFANA_HOST | Required | Public Grafana hostname |
Add these entries to .env.deploy if they are not already present:
SLACK_ALERTS_WEBHOOK_URL=REPLACE_WITH_SLACK_WEBHOOK
GRAFANA_ADMIN_PASSWORD=REPLACE_WITH_STRONG_PASSWORD
GRAFANA_HOST=grafana.agentbarn.example.comOptional email delivery
Leave all three values empty to disable transactional email:
CLOUDFLARE_ACCOUNT_ID=
CLOUDFLARE_API_TOKEN=
SENDER_EMAIL=To enable it:
- Create or select a Cloudflare Email Sending account.
- Verify the sending domain.
- Give the API token the
Email Sending: Editpermission. - Set
SENDER_EMAILto an address on the verified domain.
Use an environment-specific mail. subdomain, such as:
SENDER_EMAIL=[email protected]All three values must be configured for delivery to be enabled.
Optional Google Workspace authentication
Leave these values empty to disable Google OAuth:
GOOGLE_CLOUD_CLIENT_ID=
GOOGLE_CLOUD_CLIENT_SECRET=To enable it, create a Google OAuth 2.0 Web application client and register this redirect URI:
https://agentbarn.example.com/api/v1/integrations/google/callbackThen set the client ID and client secret in .env.deploy.
Configure DNS and TLS
Point the following DNS records to the public address of your Traefik ingress controller:
UI_HOSTAPI_HOSTGRAFANA_HOST
Find the ingress address using the command appropriate for your cluster. For example:
kubectl get services --all-namespaces
kubectl get ingressclass traefikConfirm that DNS resolves before deploying:
dig +short agentbarn.example.com
dig +short api.agentbarn.example.com
dig +short grafana.agentbarn.example.comConfirm that the expected ClusterIssuer is ready:
kubectl get clusterissuer letsencrypt-http01
kubectl describe clusterissuer letsencrypt-http01Deploy Agent Barn
Build the pinned monitoring chart dependencies:
helm dependency build helm/monitoringReview the active Kubernetes context one final time:
kubectl config current-contextDeploy the stack:
./deploy.shThe script:
- Loads values from
.env.deploy. - Verifies that
helmfileandkubectlare available. - Derives the API pod kubeconfig when
POD_KUBECONFIG_B64is not supplied. - Applies the
agent-farmnamespace and bootstrap RBAC manifest. - Runs
helmfile sync --wait. - Applies database migrations through an API chart hook.
- Generates the LiteLLM API key used by Agent Barn.
- Waits for the Helm releases to become ready.
The releases are installed in dependency order:
| Release | Purpose |
|---|---|
postgres-app | Agent Barn application database |
postgres-litellm | LiteLLM database |
postgres-firecrawl | Firecrawl database |
redis | Background task transport |
litellm | Model proxy and per-Agent virtual keys |
firecrawl | Self-hosted web retrieval |
agentbarn-api | Product API, Ingest API, worker, migrations, and reconciliation |
agentbarn-ui | Agent Barn web application |
monitoring | Prometheus, Grafana, Alertmanager, and dashboards |
Verify the deployment
- Helm releases are installed.
- Workloads become ready.
- Persistent volume claims are bound.
- Ingress and certificate resources are ready.
- The public API and web application respond.
Check the Helm releases:
helm list --namespace agent-farmCheck the workloads:
kubectl get deployments,statefulsets,pods --namespace agent-farmCheck persistent volumes:
kubectl get pvc --namespace agent-farmCheck ingress and certificate resources:
kubectl get ingress --namespace agent-farm
kubectl get certificate --namespace agent-farm
kubectl get certificaterequest --namespace agent-farmExpected: All long-running pods eventually report Running, and their ready-container counts are complete.
Verify the public API:
curl --fail https://api.agentbarn.example.com/api/v1/healthA healthy response resembles:
{
"status": "ok",
"db": "connected"
}Verify the web application:
curl --head https://agentbarn.example.comOpen these URLs in a browser:
https://agentbarn.example.com
https://grafana.agentbarn.example.comIf a pod is not ready, inspect it before retrying the deployment:
kubectl describe pod POD_NAME --namespace agent-farm
kubectl logs POD_NAME --namespace agent-farmComplete the first-time setup
Sign in at WEB_APP_URL using the address and password from PLATFORM_ADMIN_CREDENTIALS.
A fresh Agent Barn database contains the platform administrator but no Organization. Complete the initial setup in this order:
- Sign in as the platform administrator.
- Create an Organization.
- Add or invite Organization members.
- Configure shared credentials and integrations.
- Hire an Agent from a predefined template.
- Configure its chat platform and model.
- Start the Agent.
After starting the first Agent, verify that Kubernetes created its resources:
kubectl get deployments,pods,services,pvc \
--namespace agent-farm \
--selector agentbarn.io/component=agentEach Agent receives a 1 GiB PVC by default. Its generated resources remain isolated by Agent identity within the agent-farm namespace.
Agent Barn and its supporting services are running, and the cluster is ready to host Agent workloads.
Upgrade the deployment
Before upgrading:
- Back up all three PostgreSQL databases.
- Back up the stable application and LiteLLM keys.
- Review the release notes.
- Confirm that all four Agent Barn image tags belong to the target release.
- Review chart or configuration changes.
- Plan for a brief LiteLLM interruption during replacement.
Update the pinned image tags in .env.deploy, then run:
helm dependency build helm/monitoring
./deploy.shThe API chart runs database migrations before installation or upgrade.
LiteLLM uses a non-overlapping update strategy because two 2 GiB LiteLLM pods may not fit inside the namespace quota simultaneously. Its replacement can briefly interrupt model requests.
Troubleshooting
Helm reports missing chart dependencies
helm dependency build helm/monitoring
Build the monitoring dependencies and retry:
helm dependency build helm/monitoring
./deploy.sh The namespace or RBAC bootstrap fails
kubectl auth can-i create namespaces
Check your active identity:
kubectl auth whoami
kubectl auth can-i create namespaces
kubectl auth can-i create roles --namespace agent-farm
kubectl auth can-i create rolebindings --namespace agent-farmThe default deploy.sh applies k8s/agent-farm-user.yaml, including the Namespace, Role, and RoleBinding.
If you only have namespace-scoped access, the namespace and bootstrap identity must be provisioned out of band, and the bootstrap step in deploy.sh must be adapted accordingly.
A pod is stuck in ImagePullBackOff
kubectl describe pod POD_NAME --namespace agent-farm
ImagePullBackOffInspect the pod:
kubectl describe pod POD_NAME --namespace agent-farmConfirm:
- The registry hostname is correct.
- The registry username and password are valid.
- The image repository and tag exist.
- The generated registry pull Secret contains credentials for
REGISTRY_SERVER.
Do not replace a missing release image with an unrelated latest image.
A PVC remains Pending
kubectl describe pvc PVC_NAME --namespace agent-farm
PendingCheck the claim and available StorageClasses:
kubectl describe pvc PVC_NAME --namespace agent-farm
kubectl get storageclassConfirm that STORAGE_CLASS exists and supports dynamically provisioned ReadWriteOnce volumes.
TLS certificates are not ready
kubectl get certificate,challenge,order --namespace agent-farm
Inspect the ingress, certificates, and cert-manager challenges:
kubectl describe ingress --namespace agent-farm
kubectl get certificate,certificaterequest,challenge,order --namespace agent-farmConfirm that:
- The three hostnames resolve to the ingress endpoint.
- Traefik accepts the
traefikIngressClass. - The
letsencrypt-http01ClusterIssuer exists and is ready. - Ports 80 and 443 are reachable where required by the issuer.
The migration hook fails
kubectl get jobs --namespace agent-farm
List jobs and inspect the failed migration pod:
kubectl get jobs --namespace agent-farm
kubectl get pods --namespace agent-farm
kubectl logs JOB_POD_NAME --namespace agent-farmConfirm that the application PostgreSQL pod is ready and that the configured database password still matches the initialized database.
The LiteLLM key hook fails
kubectl logs JOB_POD_NAME --namespace agent-farm
Inspect the hook job:
kubectl get jobs --namespace agent-farm
kubectl logs JOB_POD_NAME --namespace agent-farmConfirm that:
- LiteLLM is ready.
LITELLM_MASTER_KEYis correct.- The configured hook ServiceAccount can create and update Secrets.
- The ServiceAccount exists in
agent-farm.
Agent Barn loads, but an Agent cannot start
kubectl logs deployment/agentbarn-api --namespace agent-farm
Inspect the API logs:
kubectl logs deployment/agentbarn-api \
--namespace agent-farm \
--container apiConfirm that the kubeconfig mounted into the API:
- Targets the correct cluster
- Can manage resources in
agent-farm - Uses a reachable in-cluster Kubernetes API endpoint
- Has not expired
- Can create Deployments, Services, PVCs, Secrets, and ConfigMaps
- Can read Pods and pod logs
Also verify that the Hermes and OpenClaw image tags exist in the configured registry.
Grafana starts but shows no Agents
agentbarn.io/component=agent
Agent metrics appear after an Agent has been started with the current resource labels.
For an Agent that predates the monitoring deployment, stop and start it once so Agent Barn recreates its runtime resources and monitoring metadata.
Deployment constraints
Account for these current deployment-tooling constraints when preparing an environment:
.env.deploy.specdefinesINGRESS_CLUSTER_ISSUER, buthelmfile.yaml.gotmpldoes not currently pass it into the API or UI charts. The charts therefore useletsencrypt-http01.helmfile.yaml.gotmplrequiresSLACK_ALERTS_WEBHOOK_URL,GRAFANA_ADMIN_PASSWORD, andGRAFANA_HOST, but those variables are not currently listed in.env.deploy.spec. Add them manually.deploy.shdoes not currently runhelm dependency build helm/monitoring. Run it before the deployment.deploy.shalways applies the production bootstrap manifest atk8s/agent-farm-user.yaml. Changing onlyNAMESPACEis not sufficient for a staging or custom-namespace deployment.- The API-facing kubeconfig defaults to the same kubeconfig used for the deployment. Production operators should replace this with a dedicated namespace-scoped identity.
- The repository and GitHub project are named
agent-barn, while the production and staging namespaces intentionally remainagent-farmandagent-farm-staging.