Kubernetes (Helm)
Deploy Gamut on your own Kubernetes cluster with the official Helm chart -- a long-lived host-app pod that orchestrates per-agent pods over a shared RWX volume, with built-in multi-user auth.
The Helm chart deploys Gamut as a single-tenant install on your own Kubernetes cluster. Unlike the Docker options, which run every agent as a sibling container on one host, the Kubernetes runtime schedules each agent as its own pod through the in-cluster Kubernetes API, so agents can spread across the nodes of a multi-node cluster.
The chart is published as a public repository: github.com/SkillfulAgents/k8s-runtime-helm.
When to choose this option
- You already run workloads on Kubernetes and want Gamut to live alongside them.
- You need agents to schedule across multiple nodes rather than one host.
- You want a multi-user deployment with login, managed by your cluster's ingress, TLS, and RBAC.
- You want garbage collection, network isolation, and resource limits handled by the platform.
For single-machine deployments, see Single-User Docker or Auth Mode.
Architecture
namespace
├── Deployment host-app (1 replica, SQLite single-writer)
│ └── creates/deletes ──▶ Pod agent-<id> + Service agent-<id>
├── Service + Ingress → host-app UI/API
├── PVC (shared, RWX) ← host-app data dir + agent workspaces
├── ServiceAccount + Role/RoleBinding (pods/services CRUD)
└── NetworkPolicy (agent ingress confined to host-app)
The host-app and every agent pod share one PVC: the runtime mounts each agent's
workspace subPath into the agent pod. The volume must support real POSIX semantics
(random writes, fcntl locking) because agents run SQLite, git, and npm in the
workspace -- plain object storage will not work.
On a multi-node cluster the PVC must be ReadWriteMany so host-app and agent
pods can mount it from different nodes. A single-node cluster can use ReadWriteOnce.
Prerequisites
- SuperAgent v0.3.45 or later -- the first release that ships the Kubernetes runtime. The chart defaults to these images (
0.3.45-authhost-app,0.3.45agent container); older versions do not have the runtime. - A Kubernetes cluster (1.24+) with
kubectlandhelmconfigured against it. - A
ReadWriteManyStorageClass (NFS, Longhorn, CephFS, AWS EFS, Azure Files, GCP Filestore, …) for multi-node clusters. A single-node cluster can setstorage.accessMode=ReadWriteOnce. - A way to reach host-app. By default the chart only creates a
ClusterIPService. Public exposure (ingress, load balancer, DNS, TLS) is your cluster's job -- see Exposing host-app. - An LLM provider API key. Self-host defaults to Anthropic. You can provide it at install time or add it later in the UI.
Quick start
Clone the chart and install it. The commands below use the local chart path
./k8s-runtime-helm; an OCI-published chart will come later.
git clone https://github.com/SkillfulAgents/k8s-runtime-helm.git
cd k8s-runtime-helm
helm install superagent ./k8s-runtime-helm \
--namespace superagent --create-namespace \
--set hostPublicUrl=https://superagent.example.com \
--set storage.storageClassName=<your-rwx-class> \
--set-string secrets.env.ANTHROPIC_API_KEY=sk-ant-...Then port-forward to reach host-app during setup:
kubectl -n superagent port-forward svc/superagent 8080:80
# then open http://localhost:8080The first user to sign up becomes the admin.
Providing secrets
Helm does not read a .env file. You can start without an LLM key, sign in
as the first admin, and add the key in the UI before starting agents. To make the
key available at first boot, use one of two approaches.
Option A — let the chart create the Secret. Pass keys via secrets.env; the
chart renders a Kubernetes Secret and wires it into host-app with envFrom:
helm install superagent ./k8s-runtime-helm \
--namespace superagent --create-namespace \
--set hostPublicUrl=https://superagent.example.com \
--set storage.storageClassName=<your-rwx-class> \
--set-string secrets.env.ANTHROPIC_API_KEY=sk-ant-...Avoid putting real keys in a values file you commit. Use --set-string on the
CLI, or Option B.
Option B — reference a Secret you created (keeps keys out of Helm entirely):
kubectl create namespace superagent
kubectl -n superagent create secret generic superagent-secrets \
--from-literal=ANTHROPIC_API_KEY=sk-ant-...
helm install superagent ./k8s-runtime-helm \
-n superagent \
--set hostPublicUrl=https://superagent.example.com \
--set storage.storageClassName=<your-rwx-class> \
--set secrets.existingSecret=superagent-secretsThe Secret's keys become env vars on host-app verbatim, so name them exactly as
the provider expects (e.g. ANTHROPIC_API_KEY, OPENROUTER_API_KEY,
AWS_BEARER_TOKEN_BEDROCK).
Exposing host-app
By default the chart creates a ClusterIP Service, so host-app stays reachable
inside the cluster without being exposed publicly. When you want public access,
pick whatever fits your cluster:
- Point your existing ingress controller at the
superagentService, or - Set
service.type=LoadBalancerto get a cloud load balancer, or - Enable the example Ingress and fill in settings for your controller:
ingress:
enabled: true
className: alb # or nginx / traefik / … — no default
host: superagent.example.com
annotations: # provider-specific; e.g. for AWS ALB:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
tls:
enabled: true
secretName: superagent-tlsAuthentication (multi-user login)
auth.mode defaults to true -- host-app runs as a multi-user deployment with
login. No OIDC setup is required: it uses email/password out of the box, and
the first user to sign up becomes the admin. By default further signups are
invitation-only and need admin approval (tunable in host-app's auth settings).
To add OIDC/social login, set AUTH_PROVIDERS_JSON. It carries a clientSecret,
so put it in secrets.env or your existingSecret, never in a committed values
file. See Auth Mode for the full
provider schema -- the same configuration applies here.
To run a single-user instance with no login, set auth.mode=false.
Enabling auth requires a clean data directory on first boot. Enabling it on a PVC that already holds non-auth agents is rejected at startup.
Key values
| Key | Default | Notes |
|---|---|---|
hostPublicUrl | "" | Required. External URL of the host-app. |
auth.mode | true | Multi-user login (email/password by default). false = single-user. |
storage.existingClaim | "" | Bring-your-own PVC; chart skips creating one. |
storage.subPath | "" | Host-app data subPath when sharing one backing filesystem. |
storage.storageClassName | "" | RWX-capable class; "" = cluster default. |
storage.accessMode | ReadWriteMany | ReadWriteOnce only on single-node. |
secrets.env | {} | Provider keys injected as env (e.g. ANTHROPIC_API_KEY). |
secrets.existingSecret | "" | Reference a pre-created Secret instead. |
ingress.enabled | false | Example Ingress; off by default. Expose host-app yourself. |
ingress.className | "" | Your ingress controller class (alb / nginx / …). No default. |
agent.resources | cpu: 1, memory: 2Gi | Per-agent pod resources. |
networkPolicy.enabled | true | Confine agent ingress to host-app. |
See values.yaml
in the chart repo for the full list.
Notes
hostApp.replicasis pinned to1-- host-app is a single-writer over the shared PVC.settings.jsonis seeded only on first boot; later changes tohostApp.settingswon't re-apply.- Agent pods are garbage-collected via an
ownerReferenceto the host-app pod: if host-app dies, the cluster cleans up orphaned agent pods.
Next steps
- Auth Mode (Multi-User) -- The OIDC provider schema and role model used here.
- LLM Providers -- Configure Anthropic, OpenRouter, or Bedrock.