Skip to content

Operator Helm Values Reference

Complete reference for packages/operator/helm/agentspec-operator/values.yaml.

Install or upgrade:

bash
helm install agentspec agentspec/operator -f my-values.yaml
helm upgrade  agentspec agentspec/operator -f my-values.yaml

operator

Controls the operator pod itself.

KeyDefaultDescription
operator.image.repositoryghcr.io/agentspec/operatorOperator container image
operator.image.tag"" (Chart.appVersion)Image tag. Leave empty to track the chart version.
operator.image.pullPolicyIfNotPresentImage pull policy
operator.replicas1Replica count. Keep at 1 unless you have leader election configured.
operator.resources.requests.cpu50mCPU request
operator.resources.requests.memory64MiMemory request
operator.resources.limits.cpu200mCPU limit
operator.resources.limits.memory128MiMemory limit
operator.livenessPort8080Kopf built-in liveness probe port
operator.env[]Extra environment variables for the operator pod

rbac

KeyDefaultDescription
rbac.createtrueCreate ClusterRole, ClusterRoleBinding, and ServiceAccount. Set false if you manage RBAC separately.
rbac.serviceAccountNameagentspec-operatorServiceAccount name

installCRD

KeyDefaultDescription
installCRDtrueInstall the AgentObservation CRD automatically. Set false if managing CRDs via GitOps or a separate pipeline.

watchNamespace

KeyDefaultDescription
watchNamespace""Namespace to watch. Empty = all namespaces (requires ClusterRole). Set to a single namespace for a scoped install.

webhook

Configures the mutating admission webhook that injects the agentspec-sidecar (and optionally OPA) into agent pods.

The webhook is disabled by default (webhook.enabled: false). Enabling it requires TLS — either via cert-manager or a manually supplied CA bundle.

Enabling the webhook

bash
helm upgrade agentspec agentspec/operator \
  --set webhook.enabled=true \
  --set webhook.certManager.enabled=true

Injection mode

Controls which pods receive sidecar injection.

KeyDefaultDescription
webhook.injectModeannotationannotation — only pods with agentspec.io/inject: "true" are injected (explicit opt-in). default — all pods in targeted namespaces are injected unless they carry agentspec.io/inject: "false" (opt-out).

Use annotation (default) when onboarding incrementally or when you want explicit opt-in per workload.

Use default when you want full-namespace coverage without annotating every Deployment. Pair with namespaceSelector and excludedNamespaces to avoid injecting into system workloads.

Namespace targeting

Two complementary layers:

webhook.namespaceSelector — Kubernetes-level filter evaluated by kube-apiserver before calling the webhook. Pods in non-matching namespaces never reach the webhook.

yaml
# Only call the webhook for namespaces explicitly opted in:
webhook:
  namespaceSelector:
    matchLabels:
      agentspec.io/enabled: "true"

# Call webhook for all namespaces except system namespaces:
webhook:
  namespaceSelector:
    matchExpressions:
      - key: kubernetes.io/metadata.name
        operator: NotIn
        values: [kube-system, kube-public, kube-node-lease]

The operator's own release namespace is always appended to any NotIn exclusion list at render time, regardless of this setting, to prevent circular dependency injection.

webhook.excludedNamespaces — Handler-level exclusion list. Even if kube-apiserver routes a request to the webhook, the handler checks this list and returns allowed: true without injecting. Acts as a defence-in-depth layer when namespaceSelector cannot express all exclusions (e.g. dynamically created system namespaces).

yaml
webhook:
  excludedNamespaces:
    - kube-system
    - kube-public
    - kube-node-lease
    - my-infra-namespace

TLS

KeyDefaultDescription
webhook.certManager.enabledtrueWhen true, a self-signed cert-manager Issuer + Certificate are created and the caBundle is injected automatically. Requires cert-manager ≥ 1.x.
webhook.caBundle""When certManager.enabled is false, supply a base64-encoded PEM CA bundle manually.
webhook.tls.secretNameagentspec-webhook-tlsKubernetes Secret name that cert-manager (or your pipeline) populates with tls.crt / tls.key.
webhook.tls.duration8760hCertificate lifetime (1 year).
webhook.tls.renewBefore720hRenewal window before expiry (30 days).

Sidecar image

KeyDefaultDescription
webhook.sidecarImageghcr.io/agentspec/sidecar:latestSidecar image injected into annotated pods. Pin to a SHA digest in production for supply-chain security.

webhook.opa

When opa.enabled is true, the webhook injects an OPA container alongside every agentspec-sidecar and wires OPA_URL + OPA_PROXY_MODE env vars on the sidecar automatically — zero agent-side code changes required.

Requires: A ConfigMap named {agent-name}-{opa.policyConfigMapSuffix} must exist in the pod's namespace before the pod starts. Generate it with agentspec generate-policy agent.yaml --out policies/ then create a ConfigMap from the output.

KeyDefaultDescription
webhook.opa.enabledfalseInject OPA alongside every agentspec-sidecar.
webhook.opa.imageopenpolicyagent/opa:0.70.0-staticOPA server image. Pin to a digest in production.
webhook.opa.proxyModetrackDefault per-request enforcement mode. See modes below. Can be overridden per pod with the agentspec.io/opa-proxy-mode annotation.
webhook.opa.policyConfigMapSuffixopa-policySuffix used to derive the OPA policy ConfigMap name: {agent-name}-{suffix}. For an agent named gymcoach the ConfigMap must be named gymcoach-opa-policy.

OPA proxy modes

ModeBehaviour
trackRecord violations in the sidecar audit ring and add X-AgentSpec-OPA-Violations response header. Request is always forwarded. Safe for initial rollout — never blocks traffic.
enforceBlock non-compliant requests with 403 PolicyViolation before they reach the agent. Use after verifying policies in track mode first.
offDisable per-request OPA checks on the proxy entirely. /gap still calls OPA if OPA_URL is set.

controlPlane

Deploys the AgentSpec control plane (FastAPI REST API) as a sub-component of the Helm chart and enables RemoteAgentWatcher, which polls it and upserts AgentObservation CRs for remote agents into a dedicated namespace.

When enabled, a Deployment, Service, and Secret are created alongside the operator. If controlPlane.url is left empty, the internal service URL is auto-resolved (http://<release>-control-plane.<namespace>.svc.cluster.local).

Quick enable

bash
helm upgrade agentspec agentspec/operator \
  --set controlPlane.enabled=true \
  --set controlPlane.apiKey=<your-admin-key>

This creates a Kubernetes Secret agentspec-control-plane with:

  • apiKey — the admin key for the control plane API
  • jwtSecret — used to sign agent registration JWTs (auto-derived from apiKey if not set; set explicitly in production)

Values reference

KeyDefaultDescription
controlPlane.enabledfalseDeploy the control plane and enable RemoteAgentWatcher.
controlPlane.image.repositoryghcr.io/agents-oss/agentspec-control-planeControl plane container image.
controlPlane.image.taglatestImage tag. Override with --set controlPlane.image.tag=X.Y.Z.
controlPlane.image.pullPolicyIfNotPresentImage pull policy.
controlPlane.url""Override the control plane URL. Leave empty to auto-resolve to the internal ClusterIP Service.
controlPlane.apiKey""Admin key for the control plane API (X-Admin-Key header). Stored in Secret agentspec-control-plane. Required — admin endpoints return 503 until set.
controlPlane.jwtSecret""Secret used to sign agent registration JWTs. Must be ≥ 32 characters. If empty, auto-derived from apiKey (not recommended for production).
controlPlane.databaseUrl""Database URL. Defaults to local SQLite at /data/agentspec.db. For production use PostgreSQL: postgresql+asyncpg://user:pass@host:5432/agentspec.
controlPlane.pollInterval30Seconds between RemoteAgentWatcher polls.
controlPlane.namespaceagentspec-remoteNamespace where remote AgentObservation CRs are created.
controlPlane.replicas1Replica count.
controlPlane.resourcessee values.yamlResource requests/limits for the control plane pod.
controlPlane.env[]Extra environment variables for the control plane pod.

Secret layout

The Helm chart creates Secret agentspec-control-plane with two keys:

KeySourceUsed by
apiKeycontrolPlane.apiKeyControl plane (AGENTSPEC_ADMIN_KEY), operator (CONTROL_PLANE_KEY), MCP/CLI
jwtSecretcontrolPlane.jwtSecret or auto-derivedControl plane (JWT_SECRET) — signs registration JWTs

For production, create the Secret manually instead of using Helm values:

bash
kubectl create secret generic agentspec-control-plane \
  --namespace=agentspec-system \
  --from-literal=apiKey=$(openssl rand -hex 32) \
  --from-literal=jwtSecret=$(openssl rand -hex 32)

Then install with controlPlane.enabled=true but omit controlPlane.apiKey — the chart picks up the existing Secret.

Webhook auto-injection

When both controlPlane.enabled and webhook.enabled are true, the operator webhook automatically injects AGENTSPEC_CONTROL_PLANE_URL into every sidecar container it creates. Agents using the AgentSpec SDK can then auto-register and push heartbeats without manual configuration.


Pod annotation reference

Annotations set on individual Pods (or via spec.template.metadata.annotations on a Deployment) to control injection and sidecar behaviour.

AnnotationValuesDescription
agentspec.io/inject"true" / "false"Opt-in (annotation mode) or opt-out (default mode) of sidecar injection.
agentspec.io/agent-nameany stringAgent name used to resolve the manifest ConfigMap and OPA policy ConfigMap. Defaults to the pod's app label.
agentspec.io/manifest-configmapConfigMap nameOverride the manifest ConfigMap name. Default: {agent-name}-agent-yaml.
agentspec.io/check-intervalinteger (5–3600)Health check interval in seconds for the injected sidecar.
agentspec.io/opa-proxy-modeenforce / track / offPer-pod override of webhook.opa.proxyMode. Takes precedence over the cluster default.

Example Deployment

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gymcoach
spec:
  template:
    metadata:
      annotations:
        agentspec.io/inject: "true"
        agentspec.io/agent-name: gymcoach
        agentspec.io/opa-proxy-mode: enforce   # override cluster default
    spec:
      containers:
        - name: gymcoach
          image: my-registry/gymcoach:latest

yaml
operator:
  image:
    tag: "v0.2.0"   # pin to a specific release

webhook:
  enabled: true
  injectMode: annotation    # explicit opt-in per workload
  sidecarImage: ghcr.io/agentspec/sidecar@sha256:<digest>   # pin to digest

  namespaceSelector:
    matchExpressions:
      - key: kubernetes.io/metadata.name
        operator: NotIn
        values: [kube-system, kube-public, kube-node-lease]

  excludedNamespaces:
    - kube-system
    - kube-public
    - kube-node-lease

  certManager:
    enabled: true

  opa:
    enabled: true
    image: openpolicyagent/opa@sha256:<digest>   # pin to digest
    proxyMode: track    # start with track, switch to enforce once policies are verified
    policyConfigMapSuffix: opa-policy

See also

Released under the Apache 2.0 License.