For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Helm reference
Look up the configurable values in the kagent Helm chart, including their defaults and types.
A Helm chart for kagent, built with Google ADK
Requirements
| Repository | Name | Version |
|---|---|---|
${SUBSTRATE_REPO} | substrate | ${SUBSTRATE_VERSION} |
| file://../tools/grafana-mcp | grafana-mcp | 1.0.0-alpha2 |
| https://oauth2-proxy.github.io/manifests | oauth2-proxy | ~10.7.0 |
| oci://ghcr.io/kagent-dev/kmcp/helm | kmcp | ${KMCP_VERSION} |
| oci://ghcr.io/kagent-dev/tools/helm | kagent-tools | 0.2.1 |
Values
| Key | Type | Default | Description |
|---|---|---|---|
| annotations | object | {} | Additional annotations to add to all Kubernetes deployment resources |
| controller.a2aClientTimeout | string | "" (no timeout) | HTTP client timeout for A2A requests from the controller to agent pods. 0 (the default) means no timeout, which is correct for SSE-based streaming agents that can run for an arbitrarily long time. The previous implicit default was 3m (inherited from the a2a-go SDK), which caused context deadline exceeded errors for agents that take longer than 3 minutes to complete. Set a positive Go duration string (e.g. “30m”, “1h”) only if you need a hard upper bound on individual A2A calls. |
| controller.a2aGatewayUrl | string | http://<fullname>-controller.<namespace>.svc:<grpc-port> | Public gRPC URL advertised by AgentInstance Agent Cards. |
| controller.affinity | object | {} | Affinity rules for the controller pod. |
| controller.agentImage | object | {"registry":"","repository":"kagent-dev/kagent/golang-adk","tag":""} | The image used for declarative agents. |
| controller.annotations | object | {} | Additional annotations to add to the controller Deployment metadata |
| controller.auth.mode | string | "unsecure" | |
| controller.auth.userIdClaim | string | "" | |
| controller.env | list | [] | |
| controller.envFrom | list | [] | |
| controller.grpc | object | {"maxMessageBytes":16777216,"reflection":false,"tlsCertFile":"","tlsKeyFile":""} | gRPC application API settings. Native gRPC, gRPC-Web, MCP, and health share the controller service port. |
| controller.image.pullPolicy | string | "" | |
| controller.image.registry | string | "" | |
| controller.image.repository | string | "kagent-dev/kagent/controller" | |
| controller.image.tag | string | "" | |
| controller.loglevel | string | "info" | |
| controller.mcpEgressPlaintext | bool | false | Rewrite RemoteMCPServer tool URLs and the controller’s tool-discovery dial from https://host[:port] to http://host:<port-or-443> so MCP traffic egresses in plaintext to a proxy that originates TLS upstream off by default. |
| controller.metrics | object | disabled | Prometheus-style /metrics endpoint for the controller manager. When enabled, provisions a dedicated metrics Service plus the ClusterRoles required for authenticated scrapes. Bind <fullname>-metrics-reader to your Prometheus ServiceAccount to grant scrape access. Use bindAddress for any port change: the Service targetPort and the pod containerPort are derived from it at template time, so overriding METRICS_BIND_ADDRESS via controller.env shifts only the runtime listener and leaves the rendered Service pointing at the chart-time port. Setting bindAddress: "0" (or empty) is treated as a disable signal — equivalent to enabled: false — to keep faith with the controller binary’s documented contract for --metrics-bind-address. |
| controller.metrics.serviceMonitor | object | disabled | Prometheus Operator ServiceMonitor for the metrics Service. Requires controller.metrics.enabled and the monitoring.coreos.com/v1 CRDs; the chart only renders it when the target cluster serves that API, so enabling it on a cluster without the Prometheus Operator is a no-op rather than a failed install (helm template needs --api-versions monitoring.coreos.com/v1). The endpoint follows secureServing: port name, scheme, bearer token and TLS settings are all derived from it, so flipping secureServing alone keeps the scrape working. With secureServing enabled the scrape is also authorized only once <fullname>-metrics-reader is bound to the Prometheus ServiceAccount; set prometheusServiceAccount below and the chart renders that binding for you. |
| controller.metrics.serviceMonitor.annotations | object | {} | Annotations for the ServiceMonitor. |
| controller.metrics.serviceMonitor.bearerTokenFile | string | "/var/run/secrets/kubernetes.io/serviceaccount/token" | Token presented to the authenticated metrics endpoint. Only used when secureServing is enabled; set to "" to omit it. |
| controller.metrics.serviceMonitor.honorLabels | bool | false | Keep the scraped labels when they collide with server-side ones. |
| controller.metrics.serviceMonitor.interval | string | "" | Scrape interval. Prometheus’ global default when empty. |
| controller.metrics.serviceMonitor.labels | object | {} | Extra labels for the ServiceMonitor (merged with the chart labels). Set whatever label your Prometheus serviceMonitorSelector matches on. |
| controller.metrics.serviceMonitor.metricRelabelings | list | [] | metricRelabelings applied to the scraped samples. |
| controller.metrics.serviceMonitor.namespace | string | the release namespace | Namespace to create the ServiceMonitor in. The scrape target stays the release namespace either way. |
| controller.metrics.serviceMonitor.prometheusServiceAccount | object | {"name":"","namespace":""} | ServiceAccount Prometheus scrapes with. When name is set and secureServing is enabled, the chart binds <fullname>-metrics-reader to it with a ClusterRoleBinding so the scrape does not fail with 403. Leave name empty to manage the binding yourself. |
| controller.metrics.serviceMonitor.prometheusServiceAccount.namespace | string | serviceMonitor.namespace, then the release namespace | Namespace of the Prometheus ServiceAccount. |
| controller.metrics.serviceMonitor.relabelings | list | [] | relabelings applied to the scrape targets. |
| controller.metrics.serviceMonitor.scrapeTimeout | string | "" | Scrape timeout. Prometheus’ global default when empty. |
| controller.metrics.serviceMonitor.tlsConfig | object | insecureSkipVerify: true | tlsConfig for the scrape. Only used when secureServing is enabled, where the controller serves a self-signed certificate. |
| controller.nodeSelector | object | {} | Node labels to match for Pod scheduling. |
| controller.pdb | object | {"annotations":{},"enabled":false,"labels":{},"maxUnavailable":1,"minAvailable":null,"unhealthyPodEvictionPolicy":""} | PodDisruptionBudget for the controller pods. Disabled by default: controller.replicas is 1, and a minAvailable: 1 budget on a single-replica Deployment blocks every voluntary eviction, so node drains and cluster upgrades hang indefinitely. Raise controller.replicas before switching to minAvailable. |
| controller.pdb.annotations | object | {} | Annotations for the controller PodDisruptionBudget. |
| controller.pdb.enabled | bool | false | Set to true to create the PodDisruptionBudget. |
| controller.pdb.labels | object | {} | Additional labels for the controller PodDisruptionBudget. |
| controller.pdb.maxUnavailable | int | 1 | Maximum number of pods that may be unavailable. Int or percentage string (e.g. 1 or "50%"). Mutually exclusive with minAvailable. |
| controller.pdb.minAvailable | string | unset (maxUnavailable is used instead) | Minimum number of pods that must remain available. Int or percentage string (e.g. 1 or "50%"). Mutually exclusive with maxUnavailable. |
| controller.pdb.unhealthyPodEvictionPolicy | string | "" (defer to the Kubernetes default) | spec.unhealthyPodEvictionPolicy, one of IfHealthyBudget (the Kubernetes default) or AlwaysAllow. AlwaysAllow lets unhealthy pods be evicted even when the budget is exhausted, which avoids drains wedging on a crash-looping pod. Requires Kubernetes >= 1.27. Omitted from the manifest when empty. |
| controller.podAnnotations | object | {} | |
| controller.podLabels | object | {} | Additional labels for the controller pod template, merged over the global podLabels (per-key; component keys win). Selector labels can never be overridden. |
| controller.readinessProbe | object | httpGet /health on port http, periodSeconds=30 | Custom readiness probe for the controller container. Setting a value replaces the default probe entirely — include a handler (httpGet / exec / tcpSocket / grpc) when overriding. |
| controller.replicas | int | 1 | |
| controller.resources.limits.cpu | int | 2 | |
| controller.resources.limits.memory | string | "512Mi" | |
| controller.resources.requests.cpu | string | "100m" | |
| controller.resources.requests.memory | string | "128Mi" | |
| controller.service.annotations | object | {} | |
| controller.service.ports.port | int | 8083 | |
| controller.service.ports.targetPort | int | 8083 | |
| controller.service.type | string | "ClusterIP" | |
| controller.serviceAccount | object | {"annotations":{}} | ServiceAccount settings for the controller pod |
| controller.serviceAccount.annotations | object | {} (no extra annotations) | Annotations to add to the controller ServiceAccount. Useful for GCP Workload Identity, AWS IRSA, or Azure Workload Identity. |
| controller.startupProbe | object | httpGet /health on port http, periodSeconds=15, initialDelaySeconds=15 | Custom startup probe for the controller container. Setting a value replaces the default probe entirely — include a handler (httpGet / exec / tcpSocket / grpc) when overriding. |
| controller.streaming | string | nil | @deprecated Removed in 0.10.0. The A2A SDK now handles SSE buffering and timeouts internally. These values have no effect and will be removed in a future release. |
| controller.substrate.ateApiEndpoint | string | "" | |
| controller.substrate.atenetRouterURL | string | "" | |
| controller.substrate.defaultWorkerPool.name | string | "" | |
| controller.substrate.defaultWorkerPool.namespace | string | "" | |
| controller.substrate.enabled | bool | false | |
| controller.tolerations | list | [] | Node taints which will be tolerated for Pod scheduling. |
| controller.topologySpreadConstraints | list | [] | Topology spread constraints for the controller pod. |
| controller.volumeMounts | list | [] | |
| controller.volumes | list | [] | |
| controller.watchNamespaces | list | [] (watches all available namespaces) | Namespaces the controller should watch. If empty, the controller will watch ALL available namespaces. |
| database.postgres.bundled | object | {"affinity":{},"enabled":true,"image":{"name":"postgres","pullPolicy":"","registry":"docker.io","repository":"library","tag":"18.6-alpine3.23"},"nodeSelector":{},"podLabels":{},"podSecurityContext":{"fsGroup":999,"runAsGroup":999,"runAsNonRoot":true,"runAsUser":999,"seccompProfile":{"type":"RuntimeDefault"}},"resources":{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"256Mi"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}},"storage":"500Mi","storageClassName":"","tolerations":[]} | Bundled PostgreSQL instance — for development and evaluation only. Not suitable for production. Deployed when enabled is true and url/urlFile are not set. |
| database.postgres.bundled.affinity | object | {} | Affinity rules for the bundled PostgreSQL pod. |
| database.postgres.bundled.enabled | bool | true | Set to false to disable the bundled database and provide your own via url or urlFile. |
| database.postgres.bundled.image.name | string | "postgres" | Bundled PostgreSQL image name |
| database.postgres.bundled.image.pullPolicy | string | "" | Bundled PostgreSQL image pull policy. Empty falls back to the top-level imagePullPolicy, then global.imagePullPolicy, then IfNotPresent. A declared default here would shadow both fallbacks. |
| database.postgres.bundled.image.registry | string | "docker.io" | Bundled PostgreSQL image registry |
| database.postgres.bundled.image.repository | string | "library" | Bundled PostgreSQL image repository (org/namespace) |
| database.postgres.bundled.image.tag | string | "18.6-alpine3.23" | Bundled PostgreSQL image tag |
| database.postgres.bundled.nodeSelector | object | {} | Node labels to match for Pod scheduling. |
| database.postgres.bundled.podLabels | object | {} | Additional labels for the bundled PostgreSQL pod template, merged over the global podLabels (per-key; component keys win). Selector labels can never be overridden. |
| database.postgres.bundled.podSecurityContext | object | {"fsGroup":999,"runAsGroup":999,"runAsNonRoot":true,"runAsUser":999,"seccompProfile":{"type":"RuntimeDefault"}} | Pod-level security context for the bundled PostgreSQL deployment. |
| database.postgres.bundled.resources | object | {"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"256Mi"}} | Resource requests/limits for the demo PostgreSQL container |
| database.postgres.bundled.securityContext | object | {"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}} | Container-level security context for the bundled PostgreSQL container. |
| database.postgres.bundled.storage | string | "500Mi" | PersistentVolumeClaim size for demo PostgreSQL data |
| database.postgres.bundled.storageClassName | string | "" | StorageClass for the PostgreSQL PVC. Defaults to the cluster default when empty. |
| database.postgres.bundled.tolerations | list | [] | Node taints which will be tolerated for Pod scheduling. |
| database.postgres.pool | object | {"maxConnIdleTime":"","maxConnLifetime":"","maxConns":null,"minConns":null} | Optional pgxpool settings. Leave unset/null to keep pgx library defaults (MaxConns≈max(4,NumCPU), MinConns=0, MaxConnIdleTime=30m, MaxConnLifetime=1h). |
| database.postgres.skipMigrations | bool | false | Skip running database migrations at controller startup. The controller instead verifies the database is already migrated and fails if it is not. Migrations must be applied out-of-band (e.g. from a CI/CD pipeline) before install/upgrade. |
| database.postgres.url | string | "" | External PostgreSQL connection string. Is always used if set regardless of the .bundled.enabled field. |
| database.postgres.urlFile | string | "" | Path to a file containing the database URL. Takes precedence over url when set. Is always used if set regardless of the .bundled.enabled field. |
| database.postgres.vectorEnabled | bool | false | Enable the pgvector migration Required to use features that depend on database vector capability. (e.g. long-term memory) Set to true when using an external PostgreSQL that has the pgvector extension installed. |
| extraObjects | list | [] | Additional arbitrary Kubernetes manifests to deploy alongside the chart. Each list entry is rendered through tpl, so values may reference the release context (e.g. {{ include "kagent.fullname" . }}, {{ .Release.Namespace }}). Both map and multi-line string entries are supported. Use this to manage resources such as ExternalSecret, HTTPRoute, or NetworkPolicy within the same chart lifecycle without maintaining a separate chart. To use, replace the empty list below with your manifests, e.g.: extraObjects: - apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: ‘{{ include "kagent.fullname" . }}-openai’ namespace: ‘{{ .Release.Namespace }}’ spec: secretStoreRef: name: aws-secretsmanager kind: ClusterSecretStore target: name: kagent-openai data: - secretKey: OPENAI_API_KEY remoteRef: key: prod/kagent/openai property: api_key |
| fullnameOverride | string | "" | |
| global.imagePullPolicy | string | "" | Fallback imagePullPolicy where neither a component nor the top-level imagePullPolicy sets one. |
| global.imagePullSecrets | list | [] | Pull secrets for every pod. The chart merges this list (union) into each pod’s own imagePullSecrets, so a local secret is never removed. Coverage matches imageRegistry above. |
| global.imageRegistry | string | "" | Registry that overrides every per-image registry when set. This is the air-gap mirror knob: one value redirects all images. Repository and tag stay per-image. For per-image control, leave this unset and set the per-image registry keys. Covers this chart’s own images: controller, ui, bundled postgres, grafana-mcp, and substrateWorkerPool.workerImage. The vendored subcharts (kagent-tools, kmcp, substrate) adopt it when their pinned versions bump. |
| global.watchNamespaces | list | [] | Namespace scope for the whole install. A non-empty list replaces ClusterRoles with Roles and scopes the controller’s watch. Both derive from this one value, so they cannot disagree. Prefer this value over the per-surface keys. rbac.namespaces overrides it when the key is present. An explicit empty rbac.namespaces restores cluster-scoped RBAC. Mixing in controller.watchNamespaces is validated: the watch must stay inside the RBAC scope. A watched namespace without a Role is a permanent Forbidden loop at runtime. |
| grafana-mcp.enabled | bool | true | |
| grafana-mcp.grafana.serviceAccountToken | string | "" | |
| grafana-mcp.grafana.url | string | "grafana.kagent:3000/api" | |
| grafana-mcp.resources.limits.cpu | string | "500m" | |
| grafana-mcp.resources.limits.memory | string | "512Mi" | |
| grafana-mcp.resources.requests.cpu | string | "100m" | |
| grafana-mcp.resources.requests.memory | string | "128Mi" | |
| imagePullPolicy | string | "" | Pull policy for all containers. Empty falls back to global.imagePullPolicy, then IfNotPresent. |
| imagePullSecrets | list | [] | |
| ipv6 | object | false | Enable IPv6/dual-stack support. When true, configures all components for dual-stack (IPv4+IPv6) networking: - nginx listens on both IPv4 and IPv6 (adds listen [::]:8080) - Next.js binds to :: instead of 0.0.0.0 - Agent pods bind to :: for dual-stack reachability Leave disabled on clusters where IPv6 is disabled at the kernel level. |
| kagent-tools.enabled | bool | true | |
| kagent-tools.nameOverride | string | "tools" | |
| kagent-tools.nodeSelector | object | {} | Node labels to match for Pod scheduling. |
| kagent-tools.podSecurityContext.runAsNonRoot | bool | true | |
| kagent-tools.podSecurityContext.seccompProfile.type | string | "RuntimeDefault" | |
| kagent-tools.replicaCount | int | 1 | |
| kagent-tools.resources.limits.memory | string | "256Mi" | |
| kagent-tools.resources.requests.cpu | string | "50m" | |
| kagent-tools.resources.requests.memory | string | "128Mi" | |
| kagent-tools.securityContext.allowPrivilegeEscalation | bool | false | |
| kagent-tools.securityContext.capabilities.drop[0] | string | "ALL" | |
| kagent-tools.securityContext.readOnlyRootFilesystem | bool | true | |
| kagent-tools.tolerations | list | [] | Node taints which will be tolerated for Pod scheduling. |
| kagent-tools.tools.loglevel | string | "debug" | |
| kagent-tools.tools.metrics.port | int | 8085 | |
| kmcp.enabled | bool | true | |
| kmcp.fullnameOverride | string | "" | |
| kmcp.nameOverride | string | "kmcp" | |
| kmcp.namespaceOverride | string | "" | |
| labels | object | {} | Additional labels to add to all Kubernetes resources |
| nameOverride | string | "" | |
| namespaceOverride | string | .Release.Namespace | Override the namespace |
| nodeSelector | object | {} | Node labels to match for Pod scheduling. |
| oauth2-proxy.config.clientID | string | "" | |
| oauth2-proxy.config.clientSecret | string | "" | |
| oauth2-proxy.config.cookieSecret | string | "" | |
| oauth2-proxy.config.existingSecret | string | "" | |
| oauth2-proxy.enabled | bool | false | |
| oauth2-proxy.extraArgs.approval-prompt | string | "auto" | |
| oauth2-proxy.extraArgs.cookie-samesite | string | "lax" | |
| oauth2-proxy.extraArgs.cookie-secure | bool | true | |
| oauth2-proxy.extraArgs.custom-templates-dir | string | "/templates" | |
| oauth2-proxy.extraArgs.email-domain | string | "*" | |
| oauth2-proxy.extraArgs.oidc-issuer-url | string | "$(OIDC_ISSUER_URL)" | |
| oauth2-proxy.extraArgs.pass-authorization-header | bool | true | |
| oauth2-proxy.extraArgs.provider | string | "oidc" | |
| oauth2-proxy.extraArgs.redirect-url | string | "$(OIDC_REDIRECT_URL)" | |
| oauth2-proxy.extraArgs.scope | string | "openid profile email groups" | |
| oauth2-proxy.extraArgs.set-authorization-header | bool | true | |
| oauth2-proxy.extraArgs.skip-auth-regex | string | `"^/(login | assets/ |
| oauth2-proxy.extraArgs.skip-auth-route | string | `"^/(health | login)$"` |
| oauth2-proxy.extraArgs.skip-jwt-bearer-tokens | bool | true | |
| oauth2-proxy.extraArgs.upstream | string | "$(UPSTREAM_URL)" | |
| oauth2-proxy.extraEnv[0].name | string | "KAGENT_OAUTH2_PROXY_SIGNIN_TEMPLATE_CHECKSUM" | |
| oauth2-proxy.extraEnv[0].value | string | `"{{ include "kagent.oauth2ProxySignInHTML" . | sha256sum }}"` |
| oauth2-proxy.extraEnv[1].name | string | "OIDC_ISSUER_URL" | |
| oauth2-proxy.extraEnv[1].value | string | "" | |
| oauth2-proxy.extraEnv[2].name | string | "OIDC_REDIRECT_URL" | |
| oauth2-proxy.extraEnv[2].value | string | "" | |
| oauth2-proxy.extraEnv[3].name | string | "UPSTREAM_URL" | |
| oauth2-proxy.extraEnv[3].value | string | "http://kagent-ui:8080" | |
| oauth2-proxy.extraVolumeMounts[0].mountPath | string | "/templates" | |
| oauth2-proxy.extraVolumeMounts[0].name | string | "custom-templates" | |
| oauth2-proxy.extraVolumeMounts[0].readOnly | bool | true | |
| oauth2-proxy.extraVolumes[0].configMap.name | string | "kagent-oauth2-proxy-templates" | |
| oauth2-proxy.extraVolumes[0].name | string | "custom-templates" | |
| oauth2-proxy.service.portNumber | int | 4180 | |
| oauth2-proxy.service.type | string | "ClusterIP" | |
| oauth2-proxy.sessionStorage.type | string | "cookie" | |
| otel.captureSensitiveContent | bool | false | Include prompts, tool details, and assistant responses in agent telemetry. This may expose sensitive user or model content. |
| otel.logging.captureRawApiBodies | bool | false | Include complete provider API request and response bodies in Claude logs. This is more verbose than captureSensitiveContent. |
| otel.logging.enabled | bool | false | |
| otel.logging.exporter.otlp.endpoint | string | "" | |
| otel.logging.exporter.otlp.insecure | bool | true | |
| otel.logging.exporter.otlp.protocol | string | "grpc" | |
| otel.logging.exporter.otlp.timeout | int | 15000 | |
| otel.tracing.enabled | bool | false | |
| otel.tracing.exporter.otlp.endpoint | string | "" | |
| otel.tracing.exporter.otlp.insecure | bool | true | |
| otel.tracing.exporter.otlp.protocol | string | "grpc" | |
| otel.tracing.exporter.otlp.timeout | int | 15000 | |
| podAnnotations | object | {} | |
| podLabels | object | {} | Additional labels to add to all pod templates (merged into pod labels of the controller and UI Deployments; can be overridden per component). Useful for admission policies that require specific labels on pods. |
| podSecurityContext | object | {"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}} | Security context for all pods |
| providers.annotations | object | {} | Annotations added to the metadata of the generated default ModelConfig (the one derived from providers.default). Omitted from the resource when empty. |
| providers.anthropic.apiKeySecretKey | string | "ANTHROPIC_API_KEY" | |
| providers.anthropic.apiKeySecretRef | string | "kagent-anthropic" | |
| providers.anthropic.model | string | "claude-haiku-4-5" | |
| providers.anthropic.provider | string | "Anthropic" | |
| providers.azureOpenAI.apiKeySecretKey | string | "AZUREOPENAI_API_KEY" | |
| providers.azureOpenAI.apiKeySecretRef | string | "kagent-azure-openai" | |
| providers.azureOpenAI.config.apiVersion | string | "2023-05-15" | |
| providers.azureOpenAI.config.azureAdToken | string | "" | |
| providers.azureOpenAI.config.azureDeployment | string | "" | |
| providers.azureOpenAI.config.azureEndpoint | string | "" | |
| providers.azureOpenAI.model | string | "gpt-4.1-mini" | |
| providers.azureOpenAI.provider | string | "AzureOpenAI" | |
| providers.default | string | "openAI" | |
| providers.gemini.apiKeySecretKey | string | "GOOGLE_API_KEY" | |
| providers.gemini.apiKeySecretRef | string | "kagent-gemini" | |
| providers.gemini.model | string | "gemini-2.5-flash-lite" | |
| providers.gemini.provider | string | "Gemini" | |
| providers.ollama.config.host | string | "host.docker.internal:11434" | |
| providers.ollama.config.options.num_ctx | string | "64000" | |
| providers.ollama.model | string | "llama3.2" | |
| providers.ollama.provider | string | "Ollama" | |
| providers.openAI.apiKeySecretKey | string | "OPENAI_API_KEY" | |
| providers.openAI.apiKeySecretRef | string | "kagent-openai" | |
| providers.openAI.model | string | "gpt-4.1-mini" | |
| providers.openAI.provider | string | "OpenAI" | |
| proxy.url | string | "" | |
| rbac | object | {} | |
| registry | string | "ghcr.io" | |
| securityContext | object | {"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true} | Security context for all containers |
| substrate.ateApi.extraArgs[0] | string | "--template-resync-interval=250ms" | |
| substrate.credentialProvider.namespacePolicies | list | [] | |
| substrate.enabled | bool | false | |
| substrateWorkerPool | object | {"create":false,"labels":{},"name":"kagent-default","replicas":1,"sandboxClass":"gvisor","template":{},"workerImage":""} | Optional Agent Substrate WorkerPool installed by this chart. This is platform capacity and is not owned by individual agents. |
| tag | string | "" | |
| tolerations | list | [] | Node taints which will be tolerated for Pod scheduling. |
| ui.additionalForwardedHeaders | list | [] | Identity headers the UI’s nginx proxy will forward to the backend on /api/ and /a2a/. Names are case-insensitive. Authorization is always forwarded; the auth-proxy identity headers (x-auth-request-*, x-forwarded-user, x-forwarded-email, x-forwarded-groups, x-forwarded-preferred-username) are stripped from client requests unless listed here, so a caller cannot spoof an identity the backend trusts. Headers outside that set are forwarded by nginx as normal. |
| ui.affinity | object | {} | Affinity rules for the UI pod. |
| ui.annotations | object | {} | Additional annotations to add to the UI Deployment metadata |
| ui.auth.ssoRedirectPath | string | "/oauth2/start" | |
| ui.env | list | [] | Extra environment variables for the UI container: a list of {name, value} entries, spliced into its env: verbatim. An installed app extension’s own settings go here, named EXTENSION_*; the container’s startup script copies those onto window.environmentVariables for the browser to read. |
| ui.externalUrl | string | "" (share tools return paths only) | Public-facing base URL of the UI (e.g. https://kagent.example.com). When set, the controller injects KAGENT_UI_URL into agent pods so that share link tools return full clickable URLs instead of relative paths. |
| ui.httpRoute | object | {"annotations":{},"enabled":false,"hostnames":[],"labels":{},"parentRefs":[],"rules":[]} | Gateway API HTTPRoute for the UI. Requires the Gateway API CRDs (gateway.networking.k8s.io/v1) and an existing Gateway to attach to via parentRefs. Disabled by default; enable to front the UI with a Gateway API implementation (kgateway, Istio, Envoy Gateway, etc.) instead of the OpenShift Route or bundled oauth2-proxy. |
| ui.httpRoute.annotations | object | {} | Annotations to add to the HTTPRoute. |
| ui.httpRoute.hostnames | list | [] | Hostnames matched by the route. |
| ui.httpRoute.labels | object | {} | Extra labels to add to the HTTPRoute (merged with the chart labels). |
| ui.httpRoute.parentRefs | list | [] | Gateways this route attaches to. Required when enabled is true. |
| ui.httpRoute.rules | list | [] | Routing rules. When a rule omits backendRefs, it defaults to the UI Service on ui.service.ports.port. Each rule may also set matches, filters, and timeouts. |
| ui.image.pullPolicy | string | "" | |
| ui.image.registry | string | "" | |
| ui.image.repository | string | "kagent-dev/kagent/ui" | |
| ui.image.tag | string | "" | |
| ui.nginx | object | {"proxyReadTimeout":"1800s","proxySendTimeout":"1800s"} | Nginx proxy timeout configuration for the UI sidecar (values are passed directly to the corresponding nginx directives, e.g. “1800s”). |
| ui.nginx.proxyReadTimeout | string | "1800s" | proxy_read_timeout: max time between two successive reads from the upstream. |
| ui.nginx.proxySendTimeout | string | "1800s" | proxy_send_timeout: max time between two successive writes to the upstream. |
| ui.nodeSelector | object | {} | Node labels to match for Pod scheduling. |
| ui.openshiftRoute.annotations.“haproxy.router.openshift.io/timeout” | string | "120m" | |
| ui.pdb | object | {"annotations":{},"enabled":false,"labels":{},"maxUnavailable":1,"minAvailable":null,"unhealthyPodEvictionPolicy":""} | PodDisruptionBudget for the UI pods. Disabled by default: ui.replicas is 1, and a minAvailable: 1 budget on a single-replica Deployment blocks every voluntary eviction, so node drains and cluster upgrades hang indefinitely. Raise ui.replicas before switching to minAvailable. |
| ui.pdb.annotations | object | {} | Annotations for the UI PodDisruptionBudget. |
| ui.pdb.enabled | bool | false | Set to true to create the PodDisruptionBudget. |
| ui.pdb.labels | object | {} | Additional labels for the UI PodDisruptionBudget. |
| ui.pdb.maxUnavailable | int | 1 | Maximum number of pods that may be unavailable. Int or percentage string (e.g. 1 or "50%"). Mutually exclusive with minAvailable. |
| ui.pdb.minAvailable | string | unset (maxUnavailable is used instead) | Minimum number of pods that must remain available. Int or percentage string (e.g. 1 or "50%"). Mutually exclusive with maxUnavailable. |
| ui.pdb.unhealthyPodEvictionPolicy | string | "" (defer to the Kubernetes default) | spec.unhealthyPodEvictionPolicy, one of IfHealthyBudget (the Kubernetes default) or AlwaysAllow. AlwaysAllow lets unhealthy pods be evicted even when the budget is exhausted, which avoids drains wedging on a crash-looping pod. Requires Kubernetes >= 1.27. Omitted from the manifest when empty. |
| ui.podAnnotations | object | {} | |
| ui.podLabels | object | {} | Additional labels for the UI pod template, merged over the global podLabels (per-key; component keys win). Selector labels can never be overridden. |
| ui.podSecurityContext | object | (uses global podSecurityContext) | Pod-level security context for the UI pod. Overrides the global podSecurityContext. |
| ui.publicBackendUrl | string | "/api" | Base URL the browser calls the controller API on. Reaches the browser at runtime as the apiBaseUrl key of /config.json, which the app fetches on startup — it is deliberately not baked into the bundle, so changing it here takes effect on pod restart rather than requiring an image rebuild. The default is a path on the UI’s own hostname, which nginx proxies to the controller; set an absolute URL only if the browser must reach the API somewhere other than the UI origin. |
| ui.readinessProbe | object | httpGet /health on port http, periodSeconds=30 | Custom readiness probe for the UI container. Override to adjust thresholds, use exec-based probes, or change the health path. |
| ui.replicas | int | 1 | |
| ui.resources.limits.cpu | string | "1000m" | |
| ui.resources.limits.memory | string | "1Gi" | |
| ui.resources.requests.cpu | string | "100m" | |
| ui.resources.requests.memory | string | "256Mi" | |
| ui.route | object | {"enabled":true} | Gates the OpenShift Route for the UI. Additionally conditional on the route.openshift.io/v1 API being present, so it is a no-op off-OpenShift. Set to false to front the UI with your own Route/ingress or the bundled oauth2-proxy instead of the chart’s edge-terminated Route. |
| ui.securityContext | object | (uses global securityContext) | Container-level security context for the UI container. Overrides the global securityContext. |
| ui.service.annotations | object | {} | |
| ui.service.ports.port | int | 8080 | |
| ui.service.ports.targetPort | int | 8080 | |
| ui.service.type | string | "ClusterIP" | |
| ui.serviceAccount | object | {"annotations":{}} | ServiceAccount settings for the UI pod |
| ui.serviceAccount.annotations | object | {} (no extra annotations) | Annotations to add to the UI ServiceAccount. Useful for GCP Workload Identity, AWS IRSA, or Azure Workload Identity. |
| ui.startupProbe | object | httpGet /health on port http, periodSeconds=1, initialDelaySeconds=1 | Custom startup probe for the UI container. Override to adjust thresholds, use exec-based probes, or change the health path. |
| ui.streamTimeoutSeconds | int | 1800 | Client-side chat stream inactivity timeout (seconds). The browser aborts a streaming response if no event is received within this window. Should be >= ui.nginx.proxyReadTimeout so nginx isn’t the silent limit. Default 1800 (30m). |
| ui.tolerations | list | [] | Node taints which will be tolerated for Pod scheduling. |
| ui.topologySpreadConstraints | list | [] | Topology spread constraints for the UI pod. |
| ui.volumes | object | {"tmp":"50Mi"} | EmptyDir volume sizes for the UI workload (typically used when enabling readOnlyRootFilesystem) |
| ui.volumes.tmp | string | "50Mi" | Size limit for temporary files (/tmp). Holds the nginx temp directories and the generated config.json. Default 50Mi is ample for both. |