By Sagar Shankaran, Founder of CallSphere
Author a production Helm chart for an AI voice agent on Helm 4: server-side apply, kstatus readiness, library subchart, and clean values for OpenAI Realtime + LiveKit.
Key takeaways
TL;DR — Helm 4 finally fixes three-way merge hell with server-side apply and uses kstatus for accurate readiness. Author your voice-agent chart around a library subchart, never use random naming, and ship the LiveKit + agent + worker triple as one release.
A Helm 4 chart voice-agent with three Deployments (livekit, agent, worker), a HorizontalPodAutoscaler, a PodDisruptionBudget, and a values schema strict enough that bad merges fail helm install instead of producing weird pods.
flowchart TD
VAL[values.yaml] --> CHART[voice-agent chart]
CHART --> LK[LiveKit Deployment]
CHART --> AG[agent Deployment]
CHART --> WK[worker Deployment]
CHART --> HPA[HPA]
CHART --> PDB[PDB]
LIB[lib subchart] -.->|tpl helpers| CHART
HELM[Helm 4 SSA] --> APIS[K8s API server]
```bash helm create voice-agent helm create voice-agent/charts/voice-lib --type library ```
Move repeated helpers (labels, env injection, image fully-qualified name) into voice-lib/templates/_helpers.tpl. Subcharts in Helm 4 still work the same way; you just stop copy-pasting include "common.labels" between charts.
```yaml
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "required": ["image", "openai", "livekit"], "properties": { "image": { "type": "object", "required": ["repository", "tag"], "properties": { "repository": { "type": "string" }, "tag": { "type": "string", "minLength": 1 }, "pullPolicy": { "enum": ["Always", "IfNotPresent", "Never"] } } }, "openai": { "type": "object", "required": ["model"], "properties": { "model": { "enum": ["gpt-realtime", "gpt-realtime-mini"] }, "voice": { "enum": ["alloy", "echo", "shimmer", "marin"] } } } } } ```
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
helm install now refuses values where image.tag is empty — the #1 cause of "ImagePullBackOff on latest" disasters.
```yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "voice-agent.fullname" . }}-agent labels: {{- include "voice-agent.labels" . | nindent 4 }} spec: replicas: {{ .Values.agent.replicas }} selector: matchLabels: {{- include "voice-agent.selectorLabels" . | nindent 6 }} app.kubernetes.io/component: agent template: metadata: labels: {{- include "voice-agent.selectorLabels" . | nindent 8 }} app.kubernetes.io/component: agent spec: containers: - name: agent image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" env: - name: OPENAI_API_KEY valueFrom: { secretKeyRef: { name: voice-secrets, key: openai } } - name: LIVEKIT_URL value: "ws://{{ include "voice-agent.fullname" . }}-livekit:7880" readinessProbe: httpGet: { path: /healthz/realtime, port: 8080 } initialDelaySeconds: 5 periodSeconds: 10 resources: {{- toYaml .Values.agent.resources | nindent 12 }} ```
/healthz/realtime should actually attempt a Realtime handshake — readiness on a TCP port is meaningless when the OpenAI key has rotated.
```yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: { name: {{ include "voice-agent.fullname" . }}-agent } spec: scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: {{ include "voice-agent.fullname" . }}-agent } minReplicas: {{ .Values.agent.minReplicas }} maxReplicas: {{ .Values.agent.maxReplicas }} metrics: - type: Pods pods: metric: { name: active_calls } target: { type: AverageValue, averageValue: "5" }
apiVersion: policy/v1 kind: PodDisruptionBudget metadata: { name: {{ include "voice-agent.fullname" . }}-agent } spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/component: agent ```
PDB is non-negotiable for voice — node drains would otherwise drop in-flight calls.
```bash helm install voice ./voice-agent \ --namespace voice --create-namespace \ --set image.tag=$(git rev-parse --short HEAD) \ --kube-server-side ```
--kube-server-side flips Helm 4 to its default of letting the API server merge — no more "Forbidden: field is immutable" surprises after a chart refactor.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
```bash helm status voice -n voice -o json | jq '.info.status' ```
Helm 4 reports InProgress while pods are starting and Current only when kstatus says all resources have reached steady state — helm install --wait finally means what users always thought it meant.
```bash helm package voice-agent helm push voice-agent-1.0.0.tgz oci://ghcr.io/acme/charts cosign sign ghcr.io/acme/charts/voice-agent:1.0.0 ```
Helm OCI is GA; cosign signs the chart manifest just like any container.
fullname collisions — two releases of the same chart in one namespace will fight over Service names. Always use {{ .Release.Name }} somewhere in fullname.helm dependency update.--wait without --wait-for-jobs doesn't block on Job completion. Migrations may not have run when helm install returns 0.helm install accepts garbage. Lint with helm lint in CI.CallSphere ships one Helm chart callsphere-voice with subcharts per vertical (healthcare, salon, behavioral-health, multi-family, contractors, dental). Each subchart enables/disables the right tools out of our 90+ tool catalog. Helm 4 server-side apply has cut our drift incidents in half. 37 agents, 115+ DB tables, k3s + Cloudflare Tunnel. $149/$499/$1499, 14-day trial, 22% affiliate — try the salon vertical (similar pattern).
Q: Helm 4 vs Kustomize for AI agents? Helm for templated multi-tenancy (different vertical = different values). Kustomize for environment-only deltas. Many teams use both.
Q: How do I roll back a bad chart?
helm rollback voice <revision> — but always test rollback in staging; a chart that adds an immutable field can't roll back without manual deletes.
Q: Should LiveKit be in the same chart? Yes if you self-host. Co-located = lowest WebRTC latency; separation pays off only at multi-tenant scale.
Q: What about MCP servers? Treat each MCP server as another Deployment in the chart with its own probe and PDB. The agent talks to them via in-cluster Service.
Written by
Sagar Shankaran· Founder, CallSphere
Sagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
A founder's guide to texto a voz (text-to-speech in Spanish): LATAM vs Castilian voices, free options, and how CallSphere ships Spanish agents.
A founder's guide to the female voice generator landscape: AI female voices, Japanese voices, robot voices, and how CallSphere ships 57+ voices live.
A founder's guide to the Siri voice generator landscape: how AI voice cloning works, what is legal, and how CallSphere uses 57+ voices in production.
A founder's guide to AI voice assistants for ecommerce: customer service, order lookup, and how CallSphere fits in versus virtual receptionists.
Robot text to speech in 2026: how I pick TTS APIs, when robotic voices help, and how CallSphere ships 57+ language voice agents. Hands-on guide.
The customer support specialist role in 2026 is half human, half AI. Here is what the job looks like, the AI tools that pair with it, and how we ship it.
© 2026 CallSphere LLC. All rights reserved.
Watch how CallSphere handles real customer calls, schedules appointments, and processes payments — live.
Try Live DemoBook a DemoCalculate Your ROI