Deploy with Helm
Deploy AgentConnect OSS with the official Helm chart and run agents in isolated Kubernetes sandboxes.
The official AgentConnect Helm chart is the production-shaped OSS deployment. It installs the Web console, Control Plane, Setup Server, Relay, connector gateway, and an install-wide daemon pool. Agent runtimes run in isolated agent-sandbox pods with persistent workspaces instead of on an operator's machine.
For a local evaluation, use the Docker Compose quick start. Use this guide when the cluster should own agent execution and workspaces.
The chart is published as an OCI artifact at oci://ghcr.io/agentconnect-md/charts/agentconnect. Its version matches the AgentConnect release without the leading v, and its default image tags match that release.
Before you start
You need:
- Kubernetes 1.28 or newer;
- Helm and
kubectlaccess to the cluster; linux/amd64worker nodes for the current first-party images;- a PostgreSQL database reachable from the AgentConnect namespace;
- a dynamic volume provisioner and a StorageClass for agent workspaces;
- permission to install CRDs, cluster-scoped RBAC, and the
agent-sandboxcontroller; and - for public access, a Gateway API controller, an existing Gateway, DNS, and TLS.
The chart creates HTTPRoute resources but does not install a Gateway API controller, create the Gateway, or manage DNS and certificates. You can set route.enabled: false and provide your own ingress instead.
Choose an AgentConnect release that includes the chart (v1.44.0-rc.58 or newer) from AgentConnect releases, then verify the artifact. Do not include the release tag's leading v:
export AGENTCONNECT_CHART_VERSION=X.Y.Z
helm show chart oci://ghcr.io/agentconnect-md/charts/agentconnect \
--version "$AGENTCONNECT_CHART_VERSION"Every supported value is documented in the chart's values.yaml.
1. Create the namespace and secrets
Create the release namespace:
kubectl create namespace agentconnectThe Control Plane needs a PostgreSQL URL, a stable API-key pepper, and a shared Relay credential:
kubectl -n agentconnect create secret generic agentconnect-secrets \
--from-literal=DATABASE_URL='postgresql://control_plane:replace-me@postgres.example.test:5432/agentconnect?schema=public' \
--from-literal=API_KEY_PEPPER="$(openssl rand -hex 32)" \
--from-literal=RELAY_TOKEN="$(openssl rand -hex 24)" \
--from-literal=OPEN_CONNECTOR_ENCRYPTION_KEY="$(openssl rand -hex 32)"API_KEY_PEPPER is effectively permanent: rotating it invalidates existing daemon and personal API keys. The connector key encrypts connector OAuth credentials in its persistent volume and should exist before the first connection is created. Keep these values in your secret manager and use a URL-encoded database password.
The Kubernetes daemon pool has a separate data-plane document. It is the durable store for sessions, transcripts, queues, and other execution data shared by the pool members. Save this as data-plane.json:
{
"version": 1,
"databaseUrl": "postgresql://daemon_pool:replace-me@postgres.example.test:5432/agentconnect",
"maxConnections": 4
}Create the Secret from that file:
kubectl -n agentconnect create secret generic agentconnect-data-plane \
--from-file=config.json=./data-plane.jsonThe Control Plane and daemon pool may use the same PostgreSQL service. Keep their credentials separate so they can be scoped and rotated independently, and back up both control and execution data.
2. Create the values file
Start with a small override file rather than copying the complete chart defaults. Save this as agentconnect-values.yaml and replace the example hosts, Gateway listener, and StorageClass:
publicUrl: https://app.example.test
# Configure this before the first install so Setup uses the intended issuer and Management API.
logto:
endpoint: https://login.example.test
# Set this separately when a custom login domain does not serve the Management API.
mgmtEndpoint: https://tenant.example.test
route:
# Keep the deployment private until Logto sign-in is configured.
enabled: false
gateway:
name: public-gateway
namespace: default
sectionName: https
daemonPool:
# The chart creates this namespace with restricted Pod Security labels and default-deny networking.
sandboxNamespace: agentconnect-agents
runtime:
workspace:
storageClass: standard
size: 10Gi
# The default-on connector gateway persists its own SQLite database in a separate PVC.
openConnector:
persistence:
storageClass: standardpublicUrl is the final browser origin. In the default same-origin topology, the console is served at /, the Control Plane at /cp, and Relay paths on the same host. The chart also supports dedicated apiHost, mcpHost, and relay.host values when you need separate public origins.
The daemon pool defaults to three members and three pre-warmed runtime sandboxes. Each warm sandbox holds a running pod and a workspace PVC. Set daemonPool.runtime.warmReplicas: 0 when you prefer lower standing cost over a faster first agent launch.
The default runtime image contains Claude Code, Codex, and DeepSeek Harness. To select the published full image with Qwen Code, OpenCode, and other ACP runtimes, see Runtime authentication.
Run Logto in the cluster
The chart does not deploy Logto. Whether you run Logto Cloud or your own Logto in the same cluster, the two logto values above are the only startup topology AgentConnect needs — everything else about sign-in is Setup Server's to own.
For an in-cluster Logto, endpoint is the browser-facing origin and mgmtEndpoint is the in-cluster Service origin:
logto:
endpoint: https://login.example.test
mgmtEndpoint: http://logto.agentconnect.svc.cluster.localThree things decide whether that works:
- Front Logto's container port on a port-less Service origin. Logto builds the URLs it advertises from the request that reached it, so an in-cluster address carrying an explicit port puts that port in what discovery returns. A Service on port 80 targeting the container keeps the management origin port-less and the advertised URLs matching your public origin.
- Give Logto
TRUST_PROXY_HEADERand send itX-Forwarded-Proto: https. Where TLS ends in front of your Gateway, the hop into the cluster is plain HTTP, and without that header Logto advertises anhttp://issuer and every OIDC discovery against it fails. Gateway API expresses it as aRequestHeaderModifierfilter on the route. - Do not route Logto's admin console. Reach it the same way as Setup Server, with
kubectl port-forward, and set its admin endpoint to that local origin.
Whichever deployment you use, the Management API resource is the fixed indicator https://default.logto.app/api — it is not a URL your deployment serves.
Encrypt stored application secrets
By default, write-only provider and agent secrets are plaintext at rest in PostgreSQL. Before entering production credentials in Setup or the console, configure a Vault Transit key and a Kubernetes-auth role bound to the chart's agentconnect-control-plane ServiceAccount. Then add the cipher settings to the same values file:
controlPlane:
config:
SECRET_CIPHER: vault-transit
VAULT_ADDR: https://vault.example.test
VAULT_TRANSIT_KEY: agentconnect-cp
VAULT_JWT_ROLE: agentconnectSetup Server uses the same ServiceAccount and cipher configuration by default, so both processes seal and open the same values. See Secret storage for the Transit policy and migration behavior.
Model credentials for every agent
See Runtime authentication for API-key setup, runtime-specific Secret mappings, and gateway endpoints. The same mapping feeds the independent pool probe and agent sessions.
Agents in the pool need a model provider credential. Per agent or per organization, that is a variable or secret named for whatever the runtime reads — ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY. An install that pays for one key and wants every agent on it can set that key once, in a Secret the chart references by name:
kubectl -n agentconnect create secret generic agentconnect-model-credentials \
--from-literal=DEEPSEEK_MODEL_TOKEN='replace-me' \
--from-literal=DEEPSEEK_MODEL_BASE_URL='https://api.deepseek.com'daemonPool:
modelCredentials:
existingSecret: agentconnect-model-credentialsThe Secret's entries are the variables: <PREFIX>MODEL_TOKEN and <PREFIX>MODEL_BASE_URL, where the prefix is ANTHROPIC_ for Claude, OPENAI_ for Codex, DEEPSEEK_, or empty for the shared fallback of those recognized runtimes and OpenCode. The example uses DeepSeek's documented API root. A token with no base URL is a plain provider key on that provider's own endpoint, which needs nothing else from the cluster: the agents namespace already allows DNS and outbound 443. A base URL with no token aims a runtime at an endpoint that issues its own credential. For Qwen Code and other ACP runtimes, map their own API-key variables with daemonPool.runtimeEnvironment as shown in the runtime authentication guide.
Two rules make this predictable:
- The Secret is the install's only source for those variables. Setting one of them in
daemonPool.extraEnv, or lettingmodelEgress.clientsrender one, is refused when you install. A credential pair has to arrive whole — a Secret holding only a token, beside a base URL left by something else, would aim a real provider key at an endpoint that never issued it. - What the Secret carries outranks an agent's own variable of the same name, for the same reason. Leave
modelCredentialsunset when agents should carry their own keys.
3. Install AgentConnect
Install the version you verified:
helm upgrade --install agentconnect \
oci://ghcr.io/agentconnect-md/charts/agentconnect \
--version "$AGENTCONNECT_CHART_VERSION" \
--namespace agentconnect \
--values agentconnect-values.yaml \
--wait \
--timeout 15mOn a fresh cluster, Helm installs the four agent-sandbox CRDs before the release, and the chart installs the pinned controller stack. The chart also creates the dedicated agents namespace, the daemon pool's TokenReview RBAC, the SandboxTemplate, and the warm pool.
Check the rollout:
kubectl -n agentconnect get pods
kubectl -n agentconnect-agents get pods,pvc
kubectl -n agentconnect logs deployment/agentconnect-control-plane -c migrateThe migration container should exit successfully, application pods should become Ready, and the agents namespace should contain the pre-warmed sandbox pods and PVCs.
4. Configure sign-in before publishing the route
Setup Server intentionally has no Service or public route. Forward it to your workstation:
kubectl -n agentconnect port-forward deployment/agentconnect-setup-server 8091:8091Open http://localhost:8091, connect Logto, configure the browser application and first social provider, and claim the initial administrator. Follow Sign-in for the application, API Resource, and provider steps.
The initial values file already supplies Setup with the Logto endpoint. For Logto Cloud behind a custom login domain, keep logto.endpoint on that login origin and logto.mgmtEndpoint on the tenant's canonical Management API origin.
After saving deployment settings in Setup, restart the services that load them at startup — the Control Plane first, and the others only once it is Ready:
kubectl -n agentconnect rollout restart deployment/agentconnect-control-plane
kubectl -n agentconnect rollout status deployment/agentconnect-control-plane
kubectl -n agentconnect rollout restart \
deployment/agentconnect-web \
statefulset/agentconnect-relayThe order matters once: the console reads its sign-in configuration from the Control Plane when it starts, so a console that restarts alongside a Control Plane still serving the previous configuration caches that one and shows no sign-in button. Restarting the console again fixes it, and starting it after the Control Plane avoids it.
Wait for the rollout, change route.enabled to true in agentconnect-values.yaml, and apply the chart again:
helm upgrade agentconnect \
oci://ghcr.io/agentconnect-md/charts/agentconnect \
--version "$AGENTCONNECT_CHART_VERSION" \
--namespace agentconnect \
--values agentconnect-values.yaml \
--wait \
--timeout 15mConfirm that the route attached to the intended Gateway:
kubectl -n agentconnect get httproute
kubectl -n agentconnect describe httproute agentconnectIf the parent Gateway is in another namespace, its listener must allow routes from the AgentConnect namespace.
5. Run the first agent
Open the final Web URL and sign in. The daemon pool registers itself as Kubernetes cluster, so you do not need to copy an Add daemon command or install the host CLI.
Create an agent, choose Kubernetes cluster, and select one of the runtimes reported by the runtime-sandbox image. Give it the model credential that runtime expects — per agent or organization as a variable or secret, or once for the whole install as described in Model credentials for every agent. Then run a message in the Playground and confirm that the agent receives a sandbox and persistent workspace.
Next
- Operations for upgrades, orphan cleanup, and troubleshooting
- Runtime authentication for API keys and model endpoints
- Provider apps for GitHub, GitLab, Linear, and the other deployment apps
How is this guide?