AI Gateway Helm values
Configure the AI Gateway chart with these Helm values.
This reference lists values declared in the chart's default values.yaml.
Templates can also accept optional settings and inherited global values.
Chart: ai-gateway-v2. Chart version: 0.24.0. Generated from the platform
source at v0.24.0.
Values
replicaCount
Type: int
Default: 2
Number of replicas for the deployment. Ignored when replicas.managedExternally is true.
replicas.managedExternally
Type: bool
Default: false
When true, the chart never writes replicas: on the Deployment, so an external
scaler (HPA/KEDA) is not overridden on every helm upgrade.
image.repository
Type: string
Default:
"image-proxy.stacklok.com/proxy/stacklok-enterprise/ghcr.io/stacklok/stacklok-enterprise/sprout"
Container image repository.
image.tag
Type: string
Default: ""
Image tag (defaults to appVersion if empty)
image.pullPolicy
Type: string
Default: "IfNotPresent"
Image pull policy
imagePullSecrets
Type: list
Default: []
Extra image pull Secrets for the sprout pod. On Replicated installs the SDK pull secret is added automatically; list only additional registries here.
nameOverride
Type: string
Default: ""
Override the name of the chart
fullnameOverride
Type: string
Default: ""
Override the full name of the resources
serviceAccount.create
Type: bool
Default: true
Specifies whether a service account should be created. Its identity backs the projected tokens Sprout presents to directory and budgets.
serviceAccount.automount
Type: bool
Default: false
Automatically mount API-server credentials. Keep false: every token Sprout needs is a separately projected volume.
serviceAccount.annotations
Type: object
Default: {}
Annotations to add to the service account
serviceAccount.name
Type: string
Default: ""
The name of the service account to use (if not set and create is true, a name is generated using the fullname template)
podAnnotations
Type: object
Default: {}
Annotations to add to the pod
podLabels
Type: object
Default: {}
Labels to add to the pod
podSecurityContext
Type: object
Default value
fsGroup: 65532
runAsGroup: 65532
runAsNonRoot: true
runAsUser: 65532
seccompProfile:
type: RuntimeDefault
Security context for the pod (ko/Chainguard nonroot UID = 65532)
securityContext
Type: object
Default value
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65532
Security context for the container
service.type
Type: string
Default: "ClusterIP"
Kubernetes service type
service.port
Type: int
Default: 8080
Service port
service.targetPort
Type: int
Default: 8080
Container target port. The Service never exposes the /metrics listener.
telemetry
Type: object
Default value
claimLabels: []
groupLabelAttributes: []
headerLabels: []
metrics:
port: 9464
otlp:
enabled: false
endpoint: ''
headersSecretRef:
key: headers
name: ''
insecure: false
tracesEndpoint: ''
prometheus:
enabled: false
spanAttributes: []
tracing:
enabled: false
exportTimeoutSeconds: 0
samplingRate: 0
Metrics and tracing export, all off by default. Sprout's strict decoder rejects
unknown fields, so never add a key here the binary does not declare.
otlp.endpoint falls back to global.stacklok.telemetry.otlp; enabled and
insecure are true if either the local or the global value is true.
telemetry.otlp.enabled
Type: bool
Default: false
Push metrics to an OTLP collector.
telemetry.otlp.endpoint
Type: string
Default: ""
Collector endpoint (e.g. "otel-collector.observability:4318"). Required, locally or via global, when otlp or tracing is enabled.
telemetry.otlp.insecure
Type: bool
Default: false
Disable TLS on the OTLP connection. Only for a collector reachable over a private, trusted network.
telemetry.otlp.tracesEndpoint
Type: string
Default: ""
Exact URL spans are POSTed to over OTLP/HTTP (no "/v1/traces" appended), e.g. "https://telemetry.cloudzero.com/v2/telemetry/<sink>". Traces only; its scheme decides TLS. Needs tracing.enabled; not composed with global.
telemetry.otlp.headersSecretRef
Type: object
Default: {"key":"headers","name":""}
Secret holding OTLP export headers for tracesEndpoint as
key=value,key2=value2. Needs an https tracesEndpoint and is refused while
OTLP metrics push is on, which would send this credential to the metrics
collector. key defaults to "headers".
telemetry.prometheus.enabled
Type: bool
Default: false
Expose a pull-scrapeable /metrics route on its own listener (metrics.port).
telemetry.tracing
Type: object
Default: {"enabled":false,"exportTimeoutSeconds":0,"samplingRate":0}
Push traces to the OTLP collector. Off by default.
telemetry.tracing.enabled
Type: bool
Default: false
Export spans via OTLP. Requires otlp.endpoint or otlp.tracesEndpoint.
telemetry.tracing.samplingRate
Type: int
Default: 0
Sampling ratio (0.0-1.0) for requests with no or unsampled inbound trace context; a sampled inbound traceparent is always honored. 0 samples every request.
telemetry.tracing.exportTimeoutSeconds
Type: int
Default: 0
Bound, in seconds, on one OTLP export; 0 keeps the 30s default. Set it above the destination's worst-case response time, or a slow destination can receive the same batch twice and double-count spans.
telemetry.metrics
Type: object
Default: {"port":9464}
Dedicated /metrics listener, bound whenever prometheus.enabled is true.
telemetry.headerLabels
Type: list
Default: []
Header-to-attribute mappings on the token-usage metric. Values outside
permitted fold to "other". Governance and credential headers are refused; use
claimLabels for caller identity.
Example:
headerLabels:
- header: x-stacklok-team
attribute: team
permitted: [platform, research]
telemetry.claimLabels
Type: list
Default: []
Verified token claims carried as labels on the token-usage metric, read from the
signed token (or, for a virtual key, its owner's directory record). Without
permitted the value passes through, so a per-user label is one series per user
and puts personal data in your metrics store. At most 10 entries; a claim that
changes per token or session (jti, nonce, sid) needs permitted.
Example:
claimLabels:
- claim: sub
attribute: user_id
- claim: department
attribute: department
telemetry.groupLabelAttributes
Type: list
Default: []
Stamp a directory-resolved group label onto the interaction span under a custom
attribute name instead of its bare name. Each label must be in
directory.groupLabels, or the gateway refuses to start.
Example:
groupLabelAttributes:
- label: department
attribute: cz.context.department
telemetry.spanAttributes
Type: list
Default: []
Copy a caller-sent request header onto the interaction span under a chosen attribute name. The value is client-supplied, so treat it as an attribution hint, never an identity. Credential and personal-data headers are refused; at most 20 entries. Needs telemetry.tracing.enabled.
Example:
spanAttributes:
- header: x-cz-context-project
attribute: cz.context.project
resources
Type: object
Default:
{"limits":{"memory":"256Mi"},"requests":{"cpu":"50m","memory":"128Mi"}}
Resource limits and requests for the container. No CPU limit: requests are mostly blocked on upstream I/O, so a CPU ceiling only throttles stream bursts.
readinessProbe
Type: object
Default value
failureThreshold: 2
httpGet:
path: /readyz
port: http
initialDelaySeconds: 0
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 3
Readiness probe. /readyz fails once a graceful drain has started.
livenessProbe
Type: object
Default value
failureThreshold: 32
httpGet:
path: /healthz
port: http
initialDelaySeconds: 0
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 5
Liveness probe. Must satisfy
(failureThreshold - 1) * periodSeconds > drain-deadline + 5s for
lifecycle.maxStreamDuration; the render fails otherwise.
runtime
Type: object
Default: {"drainDeadline":"","drainWindow":"","jwksWarmupTimeout":""}
Process flags passed on argv. Empty renders no flag and keeps the binary default.
runtime.drainWindow
Type: string
Default: ""
-drain-window: how long a draining pod keeps accepting connections after
SIGTERM. Go duration string. Binary default 5s.
runtime.drainDeadline
Type: string
Default: ""
-drain-deadline: overrides the deadline derived from
lifecycle.maxStreamDuration. Setting it decouples it from the rendered
terminationGracePeriodSeconds. Go duration string.
runtime.jwksWarmupTimeout
Type: string
Default: ""
-jwks-warmup-timeout: per-issuer budget for the first JWKS fetch; a miss exits
the process. Go duration string. Binary default 10s.
lifecycle.maxStreamDuration
Type: string
Default: "15m"
Upstream stream ceiling. The termination grace period, liveness guard and httpRoute timeouts all derive from it. Go duration string.
providers
Type: list
Default: []
Upstream providers. credentialSecretRef names the Secret and key holding the
provider's credential, mounted as a file; inline plaintext credentials are
refused. A provider without one uses the ambient credential chain.
Example:
providers:
- kind: openai
baseUrl: https://api.openai.com
models: ['gpt-5.5']
credentialSecretRef:
name: ai-gateway-v2-openai-credentials
key: api-key
- kind: bedrock-anthropic
baseUrl: https://bedrock-runtime.us-east-1.amazonaws.com
region: us-east-1
models: ['us.anthropic.claude-opus-4-8']
auth
Type: object
Default: {"issuers":[]}
Trusted OIDC issuers: issuer, audience, bindingClaim, tokenUse, requiredScope, jwksUri and optional caBundleRef. requiredScope is written as the token's scope claim holds it (for Entra, "LLM.Invoke"); a token without it gets 403. An issuer matching global.stacklok.primaryIdp.issuer inherits its caBundleRef.
caBundleRef:
secretRef: { name: corp-idp-ca } # or configMapRef: {name: ...}
key: ca.crt # optional, default ca.crt
directory.endpoint
Type: string
Default: ""
Directory gRPC endpoint (host:port), e.g. "enterprise-server.toolhive-system:9091". Empty with insecure: true inherits global.stacklok.directoryGrpcEndpoint; empty otherwise disables virtual-key resolution and group labels. Once one resolves, any JWT caller the directory does not resolve gets 403.
directory.insecure
Type: bool
Default: false
Dial the directory over plaintext instead of TLS. Transport only: the caller credential comes from tokenProjection. Set true for Enterprise Manager's cleartext gRPC listener, and to inherit global.stacklok.directoryGrpcEndpoint when endpoint is empty. With Enterprise Manager caller authentication on, also set tokenProjection.enabled: true.
directory.caBundle.secretName
Type: string
Default: ""
Secret holding the PEM bundle that verifies the directory's TLS certificate, added to the system roots. Required for a TLS dial to an in-cluster endpoint, whose certificate no public root vouches for. Mounted without a subPath and read at every reconnect, so a rotated certificate is picked up without restarting the gateway. Chart-local like directory.endpoint, with no global.stacklok default: the CA vouches for the address this gateway dials, which may differ from other charts'.
directory.caBundle.key
Type: string
Default: "ca.crt"
Key of the bundle in that Secret.
directory.caBundle.mountPath
Type: string
Default: "/etc/directory-tls"
Directory the bundle is mounted into.
directory.groupsResolutionIssuer
Type: string
Default: ""
The iss the virtual-key path presents to the directory to resolve the key
owner's groups. Do not add this issuer to auth.issuers only for this lookup:
the gateway would also trust its tokens.
directory.groupLabels
Type: list
Default: []
Directory group label names this gateway resolves onto the principal, its
X-<Label> governance header and the audit trail. Lower-case underscore
identifiers; a name colliding with a reserved header fails startup.
directory.tokenProjection.enabled
Type: bool
Default: false
Project a ServiceAccount token for the directory. Required when directory.endpoint is set and directory.insecure is false.
directory.tokenProjection.mountPath
Type: string
Default: "/var/run/secrets/directory"
Directory the projected token is mounted into.
directory.tokenProjection.audience
Type: string
Default: "directory-service"
Audience the directory's caller-auth gate expects.
directory.tokenProjection.expirationSeconds
Type: int
Default: 3600
Requested lifetime of the projected token. Minimum 600 — the API server REJECTS a Pod spec below that floor rather than clamping to it.
directory.workloadTrust.pollInterval
Type: string
Default: ""
Snapshot poll interval as a Go duration, e.g. "15s", at least "10s". Empty keeps the binary's 30s default.
budgets.endpoint
Type: string
Default: ""
Budget webhook receiver base URL, e.g. "https://enterprise-server.toolhive-system:443". Empty leaves the gateway UNGOVERNED (no admission, no charge) — see acknowledgeUnmetered below.
budgets.caBundle.secretName
Type: string
Default: ""
Secret holding the PEM bundle that verifies the budgets receiver. Required when endpoint is set; falls back to global.webhooks.caBundleSecret.
budgets.caBundle.key
Type: string
Default: "ca.crt"
Key within that Secret holding the PEM bundle.
budgets.mountPath
Type: string
Default: "/etc/budgets-tls"
Directory the CA bundle is mounted into.
budgets.tokenProjection.enabled
Type: bool
Default: false
Project a ServiceAccount token presented to the budgets receiver. Required when endpoint is set.
budgets.tokenProjection.mountPath
Type: string
Default: "/var/run/secrets/budgets"
Directory where the projected budgets ServiceAccount token is mounted.
budgets.tokenProjection.audience
Type: string
Default: "budgets-webhook"
Audience requested for the projected budgets ServiceAccount token. Match the audience accepted by Enterprise Manager's budgets receiver.
budgets.tokenProjection.expirationSeconds
Type: int
Default: 3600
Requested lifetime, in seconds, of the projected budgets ServiceAccount token. Kubernetes rotates the token before expiry.
budgets.capture
Type: bool
Default: false
Forward the client request body to the receiver (conversation capture). With scanning off this sends the raw, unredacted body.
budgets.sessionHeaders
Type: list
Default: []
Ordered session-correlation headers. Empty inherits
global.stacklok.sessionHeaders, then the shipped defaults.
budgets.acknowledgeUnmetered
Type: bool
Default: false
REQUIRED (true) to render without budgets.endpoint, so an unmetered gateway is never an accident.
modelAccess.enabled
Type: bool
Default: false
Enforce directory model access: inference for a model the caller is not granted gets 403, and model discovery lists only granted models. Needs directory.endpoint; reuses budgets.tokenProjection and the budgets CA.
modelAccess.endpoint
Type: string
Default: ""
Receiver base URL, e.g. "https://enterprise-server.toolhive-system:443". Defaults to budgets.endpoint, which is the same listener.
failureLogs.level
Type: string
Default: "warn"
Severity of structured operational failure records (warn, error, or debug).
failureLogs.includeMessage
Type: bool
Default: true
Include a bounded parsed failure message by default. Set false to log metadata only when stderr retention or access cannot accommodate PII.
audit.enabled
Type: bool
Default: false
Enable audit logging. On if this OR global.stacklok.audit.enabled is true; it cannot force audit off while the global is on.
capture
Type: object
Default: {}
Inline capture config, rendered verbatim into the ConfigMap. Empty by default: capture records full request and response bodies.
networkPolicy.enabled
Type: bool
Default: false
Enable a NetworkPolicy for the sprout pod.
networkPolicy.ingress.gatewayNamespaces
Type: list
Default: ["envoy-gateway-system"]
Namespaces whose pods may reach the gateway port. An empty list with allowAllSources false fails the render rather than admitting every pod.
networkPolicy.ingress.gatewayPodSelector
Type: object
Default: {"app.kubernetes.io/name":"envoy"}
Pod selector within those namespaces. Set to {} to admit the whole namespace.
networkPolicy.ingress.monitoringNamespaces
Type: list
Default: ["monitoring"]
Namespaces whose pods may scrape /metrics when telemetry.prometheus.enabled is true. The listener is unauthenticated, so this list bounds who reads it.
networkPolicy.ingress.allowAllSources
Type: bool
Default: false
Admit every source instead of the lists above. This also exposes the unauthenticated /metrics listener to every pod in the cluster.
networkPolicy.governanceEgress
Type: object
Default:
{"enabled":true,"namespaces":[],"podSelector":{"app.kubernetes.io/name":"enterprise-manager"}}
When allowExternalEgress is false, emit egress rules to the directory, budgets and enterprise-manager services this install dials. Without them a locked-down install 503s every request.
networkPolicy.governanceEgress.namespaces
Type: list
Default: []
Namespaces the governance services run in; empty means the release namespace. Must match if directory or budgets endpoints point elsewhere, or the rule admits nothing.
networkPolicy.governanceEgress.podSelector
Type: object
Default: {"app.kubernetes.io/name":"enterprise-manager"}
Pods within those namespaces. Set to {} to admit the whole namespace.
networkPolicy.allowExternalEgress
Type: bool
Default: true
Allow ALL egress traffic, overriding any cluster-wide default-deny. Set false
and populate egress to lock this pod down.
networkPolicy.egress
Type: list
Default: []
Additional egress rules (NetworkPolicyEgressRule shape) applied when
allowExternalEgress is false. Must cover DNS and every provider, directory,
budgets and OTLP destination. With directory.endpoint set, an in-cluster
workload trust needs the API server's endpoint addresses and port, often 6443;
the kubernetes.default Service address on 443 is not enough. A trust with a
public JWKS URL needs its host on 443.
extraEnv
Type: list
Default: []
Additional environment variables for the sprout container.
extraVolumes
Type: list
Default: []
Additional volumes to attach to the pod.
extraVolumeMounts
Type: list
Default: []
Additional volume mounts to attach to the sprout container.
nodeSelector
Type: object
Default: {}
Node labels for pod assignment
tolerations
Type: list
Default: []
Tolerations for pod assignment
affinity
Type: object
Default: {}
Affinity rules for pod assignment
topologySpreadConstraints
Type: list
Default:
[{"maxSkew":1,"topologyKey":"kubernetes.io/hostname","whenUnsatisfiable":"ScheduleAnyway"}]
Spread replicas across nodes. Set to [] to disable spreading.
httpRoute.enabled
Type: bool
Default: false
Render a Gateway API HTTPRoute attaching this Service to the shared Envoy Gateway. Requires parentRefs.
httpRoute.parentRefs
Type: list
Default: []
Gateway API parentRefs (name, namespace, optional sectionName) of the shared Gateway. Required when httpRoute.enabled is true.
httpRoute.hostname
Type: string
Default: ""
Hostname this route serves. Empty inherits the host of global.stacklok.aiGatewayV2.url, and with neither set the route matches every hostname the parent Gateway listener accepts.
config.mountPath
Type: string
Default: "/etc/ai-gateway-v2/config"
Directory the config ConfigMap is mounted into.
config.fileName
Type: string
Default: "config.json"
File name of the rendered config JSON within mountPath.
config.credentialsRoot
Type: string
Default: "/var/run/secrets/ai-gateway-v2"
Directory every provider credential file must resolve inside. Passed as a flag, so the ConfigMap cannot widen it.
scanning
Type: object
Default value
adapter:
image:
digest: ''
pullPolicy: IfNotPresent
repository: image-proxy.stacklok.com/proxy/stacklok-enterprise/ghcr.io/stacklok/stacklok-enterprise/ai-gateway-main-processor
tag: ''
logLevel: ''
maxReplicas: null
metrics:
enabled: null
port: 9090
nodeSelector: {}
podAnnotations: {}
replicas: 2
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 50m
memory: 64Mi
targetCPUUtilization: null
tolerations: []
topologySpreadConstraints: []
allowlist: []
allowlistMatch: exact
audience: ''
diagnostics:
includePIIInDebugLogs: false
enabled: false
entities: []
entityActions: []
extractionFailureAction: block
hook:
caMountPath: /etc/scanning-tls
failurePolicy: Fail
timeout: ''
tokenExpirationSeconds: 3600
tokenMountPath: /var/run/secrets/scanning
mutationFailureAction: block
ner:
circuitBreaker:
failureThreshold: 5
resetTimeout: 30s
failureAction: fail-closed
timeout: 5s
placeholder: ''
presidio:
autoscaling:
mode: HPA
image:
digest: ''
pullPolicy: IfNotPresent
repository: image-proxy.stacklok.com/proxy/stacklok-enterprise/ghcr.io/stacklok/stacklok-enterprise/presidio-analyzer
tag: ''
language: en
maxReplicas: null
nodeSelector: {}
podAnnotations: {}
recognizers: []
replicas: 2
resources:
limits:
cpu: '2'
memory: 3Gi
requests:
cpu: 500m
memory: 2Gi
scoreThreshold: 50
targetCPUUtilization: null
tolerations: []
topologySpreadConstraints: []
requestAction: block
resultCache:
enabled: false
macSecret:
key: mac-secret
name: ''
redis:
clusterMode: null
existingSecret: ''
existingSecretKey: ''
host: ''
port: null
tls: null
username: ''
ttl: ''
skipPaths: []
tls:
caBundleKey: ca.crt
caBundleSecret: ''
issuerRef:
kind: ''
name: ''
PII scanning with Presidio and the scanning-adapter. scanning.enabled=true
plus an issuer and a CA bundle is enough for a working scan.
scanning.enabled
Type: bool
Default: false
Render the Presidio stack and the scanning-adapter, including a cluster-scoped ClusterRoleBinding, and wire the gateway's scan hook to it.
scanning.audience
Type: string
Default: ""
Audience of the token the gateway presents to the adapter. Empty derives
https://<adapter-service>.<release-namespace>.svc.
scanning.requestAction
Type: string
Default: "block"
Global action when Presidio finds an entity: block (403), redact (replace
the match with a placeholder) or log-only.
scanning.placeholder
Type: string
Default: ""
Text substituted for a redacted match whose entity sets no placeholder of its
own, at most 64 characters. Empty uses [REDACTED-<ENTITY>], e.g.
[REDACTED-EMAIL_ADDRESS].
scanning.entityActions
Type: list
Default: []
Per-entity overrides of requestAction: entity, action
(block|redact|log-only), optional placeholder, and optional mode
(enforce, default, or shadow, which only records the detection).
scanning.extractionFailureAction
Type: string
Default: "block"
When the request body's text cannot all be extracted for scanning (invalid JSON,
an unrecognized input item, or text nested over 32 levels): block (403) or
continue, which forwards the unreachable text unscanned with any PII in it,
still scans the rest, and counts it as unscanned.
scanning.mutationFailureAction
Type: string
Default: "block"
When a match cannot be redacted safely: block (403) or continue, which
forwards the match unredacted to the provider.
scanning.skipPaths
Type: list
Default: []
Extra request fields the adapter never scans, appended to its built-in list of
protocol values and never replacing it. Each entry is
<type>.<field>[.<key>|[*]]..., e.g. computer_call.action.button or
tool_use.input.trace_id. An unknown type or field, or a path below a string
field, stops the adapter; a misspelled deeper key skips nothing. A skipped field
reaches the provider unscanned, and under tool_use.input the client picks the
keys.
scanning.diagnostics.includePIIInDebugLogs
Type: bool
Default: false
SECURITY: with adapter.logLevel: debug, writes raw matched PII into adapter
logs. Incident response only; never leave it on in production.
scanning.entities
Type: list
Default: []
Presidio entities to detect. Empty uses files/presidio/default_entities.json. Custom recognizers' entities are always added; editing this list rolls the adapter.
scanning.allowlist
Type: list
Default: []
Strings Presidio never reports as a detection.
scanning.allowlistMatch
Type: string
Default: "exact"
How allowlist entries match: exact or regex.
scanning.ner.timeout
Type: string
Default: "5s"
Budget for one Presidio call, as a single-unit Go duration. Must be positive.
scanning.ner.failureAction
Type: string
Default: "fail-closed"
What the adapter does when Presidio is unreachable or slow: fail-closed blocks
the request, fail-open admits it.
scanning.ner.circuitBreaker.failureThreshold
Type: int
Default: 5
Consecutive Presidio failures that trip the breaker.
scanning.ner.circuitBreaker.resetTimeout
Type: string
Default: "30s"
How long the breaker stays open before probing again.
scanning.hook.timeout
Type: string
Default: ""
Budget the gateway gives the adapter, as a single-unit Go duration. Empty derives ner.timeout + 2s; an explicit value must exceed ner.timeout. Raise it if large requests need several Presidio waves under load.
scanning.hook.failurePolicy
Type: string
Default: "Fail"
When the adapter call fails: Fail refuses the request, Ignore forwards it
unscanned. Under Ignore, an outage or an oversized request lets PII through.
scanning.hook.tokenExpirationSeconds
Type: int
Default: 3600
Requested lifetime of the projected token, minimum 600.
scanning.hook.tokenMountPath
Type: string
Default: "/var/run/secrets/scanning"
Directory the projected token is mounted into on the gateway pod.
scanning.hook.caMountPath
Type: string
Default: "/etc/scanning-tls"
Directory the adapter CA bundle is mounted into on the gateway pod.
scanning.tls.issuerRef
Type: object
Default: {"kind":"","name":""}
cert-manager issuer for the adapter's serving certificate. Empty name falls back to global.webhooks.issuerRef; one of the two must name an issuer.
scanning.tls.caBundleSecret
Type: string
Default: ""
Secret holding the PEM CA that verifies the adapter's serving certificate, in the release namespace. Empty falls back to global.webhooks.caBundleSecret; one of the two is required.
scanning.tls.caBundleKey
Type: string
Default: "ca.crt"
Key within that Secret holding the PEM bundle.
scanning.adapter.image.repository
Type: string
Default value
image-proxy.stacklok.com/proxy/stacklok-enterprise/ghcr.io/stacklok/stacklok-enterprise/ai-gateway-main-processor
Scanning-adapter image (the ai-gateway main-processor).
scanning.adapter.image.tag
Type: string
Default: ""
Image tag (defaults to appVersion if empty).
scanning.adapter.image.digest
Type: string
Default: ""
Optional image digest, appended as @<digest> after the tag.
scanning.adapter.image.pullPolicy
Type: string
Default: "IfNotPresent"
Image pull policy.
scanning.adapter.replicas
Type: int
Default: 2
Replica count, and the HPA's minReplicas. The scan hook is fail-closed, so a single adapter is a single point of failure for every request.
scanning.adapter.maxReplicas
Type: string
Default: nil
Upper bound for the HPA. Unset means no HPA, and replicas is written on the
Deployment.
scanning.adapter.targetCPUUtilization
Type: string
Default: nil
HPA target average CPU utilization, 1-100. Defaults to 75 when unset.
scanning.adapter.podAnnotations
Type: object
Default: {}
Annotations added to the adapter pods. The chart's own checksum and scrape annotations win over a same-named entry.
scanning.adapter.nodeSelector
Type: object
Default: {}
Node labels for adapter pod assignment.
scanning.adapter.tolerations
Type: list
Default: []
Tolerations for adapter pod assignment.
scanning.adapter.topologySpreadConstraints
Type: list
Default: []
Topology spread constraints for the adapter pods. Entries without a labelSelector get the adapter's selector labels.
scanning.adapter.resources
Type: object
Default:
{"limits":{"cpu":"500m","memory":"256Mi"},"requests":{"cpu":"50m","memory":"64Mi"}}
Adapter container resources.
scanning.adapter.logLevel
Type: string
Default: ""
Adapter log level (debug|info|warn|error). Empty keeps the binary default.
scanning.adapter.metrics.enabled
Type: string
Default: nil
Serve the adapter's scan metrics. Unset follows the gateway's telemetry
settings; false turns them off; true always serves port.
scanning.resultCache.enabled
Type: bool
Default: false
Cache Presidio results in Redis/Valkey. Requires a Redis host here or in global.redis. Writes pause while Presidio is mid-rollout.
scanning.resultCache.ttl
Type: string
Default: ""
Entry lifetime as a Go duration. Empty keeps the runtime default (24h).
scanning.resultCache.redis.host
Type: string
Default: ""
Redis host. Empty falls back to global.redis.host.
scanning.resultCache.redis.port
Type: string
Default: nil
Redis port. Empty falls back to global.redis.port.
scanning.resultCache.redis.clusterMode
Type: string
Default: nil
Speak the Redis Cluster protocol. Unset falls back to global.redis.clusterMode.
scanning.resultCache.redis.username
Type: string
Default: ""
ACL username. Empty falls back to global.redis.username.
scanning.resultCache.redis.existingSecret
Type: string
Default: ""
Secret holding the Redis password, in the release namespace. Empty falls back to global.redis.existingSecret.
scanning.resultCache.redis.existingSecretKey
Type: string
Default: ""
Key within that Secret. Empty falls back to global.redis.existingSecretKey.
scanning.resultCache.redis.tls
Type: string
Default: nil
Dial Redis over TLS. Unset falls back to global.redis.tls.enabled.
scanning.resultCache.macSecret.name
Type: string
Default: ""
Your own Secret holding the cache's HMAC key (at least 32 printable bytes).
Empty makes the adapter create <fullname>-ner-cache-mac if absent. Never point
this at a Secret another controller also writes.
scanning.resultCache.macSecret.key
Type: string
Default: "mac-secret"
Key within that Secret.
scanning.presidio.image.repository
Type: string
Default value
image-proxy.stacklok.com/proxy/stacklok-enterprise/ghcr.io/stacklok/stacklok-enterprise/presidio-analyzer
Presidio Analyzer image.
scanning.presidio.image.tag
Type: string
Default: ""
Image tag (defaults to appVersion if empty).
scanning.presidio.image.digest
Type: string
Default: ""
Optional image digest, appended as @<digest> after the tag.
scanning.presidio.image.pullPolicy
Type: string
Default: "IfNotPresent"
Image pull policy.
scanning.presidio.replicas
Type: int
Default: 2
Replica count, and the HPA's minReplicas. With autoscaling.mode External, set it to the scaler's minimum: it sizes per-request Presidio fan-out.
scanning.presidio.maxReplicas
Type: string
Default: nil
Upper bound for the HPA. Unset means no HPA.
scanning.presidio.targetCPUUtilization
Type: string
Default: nil
HPA target average CPU utilization, 1-100. Defaults to 75 when unset.
scanning.presidio.autoscaling.mode
Type: string
Default: "HPA"
Who owns the replica count: HPA, External (e.g. KEDA) or None. The first
upgrade that omits replicas drops to 1 analyzer until the scaler acts; do it
in a low-traffic window.
scanning.presidio.podAnnotations
Type: object
Default: {}
Annotations added to the Presidio pods. The chart's own checksum annotations win over a same-named entry.
scanning.presidio.nodeSelector
Type: object
Default: {}
Node labels for Presidio pod assignment.
scanning.presidio.tolerations
Type: list
Default: []
Tolerations for Presidio pod assignment.
scanning.presidio.topologySpreadConstraints
Type: list
Default: []
Topology spread constraints for the Presidio pods. Entries without a labelSelector get the Presidio selector labels.
scanning.presidio.resources
Type: object
Default:
{"limits":{"cpu":"2","memory":"3Gi"},"requests":{"cpu":"500m","memory":"2Gi"}}
Analyzer container resources. One worker runs per whole core of limits.cpu; allow about 1Gi of limits.memory per worker or the render fails.
scanning.presidio.language
Type: string
Default: "en"
Analysis language. Only en is supported.
scanning.presidio.scoreThreshold
Type: int
Default: 50
Minimum Presidio confidence, 0-100, for a detection to count.
scanning.presidio.recognizers
Type: list
Default: []
Custom Pattern recognizers: name, supportedEntity (UPPER_SNAKE, not a
built-in), and patterns (name, RE2 regex, score) and/or denyList,
optional contextWords. Editing this list rolls Presidio.
guardrails.enabled
Type: bool
Default: false
Render the guardrails-adapter, including a cluster-scoped ClusterRoleBinding,
and wire the gateway's guardrails hook to it. It screens user text with Amazon
Bedrock Guardrails after scanning.
guardrails.mode
Type: string
Default: "Enforce"
Enforce blocks a request the guardrail intervenes on. Monitor never blocks
and only counts and logs what Enforce would have blocked.
guardrails.failurePolicy
Type: string
Default: "Fail"
When the adapter fails under Enforce: Fail blocks the request, Ignore admits
it.
guardrails.unscreenableContentPolicy
Type: string
Default: "Deny"
User content the adapter cannot screen: Deny blocks it, Admit lets it
through unscreened. Fallback for every class in unscreenableContentPolicies
without an entry.
guardrails.unscreenableContentPolicies
Type: object
Default: {}
Per-class overrides, each Admit or Deny: nonTextMedia (image, audio, video
or a document with no text), toolResult, unrecognizedPart and
unrecognizedShape. toolResult defaults to Admit, since agentic clients
carry tool output on most turns; the rest follow unscreenableContentPolicy. The
adapter sends Bedrock text only, so set nonTextMedia: Admit to let media
through unscreened. One Deny blocks.
guardrails.screeningWindowTurns
Type: string
Default: nil
Screen sliding windows of the last N user turns instead of the whole conversation, an integer of at least 3. Each window's verdict is cached, so on a warm cache a request costs one Bedrock call against at most N turns rather than one against every turn so far. Requires verdictCache.enabled with a resolvable Redis; without a usable cache the adapter screens the whole conversation as it does when this is unset. Only turns carrying text the user wrote count toward N: a tool-output, media-only, whitelisted or empty turn takes no slot. Trade-off: an injection split across more than N text turns is not caught.
guardrails.screeningWindowMaxLiveCalls
Type: string
Default: nil
The most live Bedrock calls one windowed request makes, an integer of at least 1. Unset keeps the adapter default of 3. A warm cache needs one. On a cold or slow cache, up to this many uncached windows are screened and cached one by one, oldest first, and any beyond that are screened together in a single call, so a long conversation stays inside hook.timeout and warms over its next requests. A cache backend that times out stops being consulted for the rest of the request, and the reads of one request share a fixed budget, so a slow backend cannot spend hook.timeout.
guardrails.verdictCache.enabled
Type: bool
Default: false
Cache each turn window's Bedrock verdict in Redis/Valkey, keyed by the window's
text digest, the guardrail and the window size. Used only when
screeningWindowTurns is set. Entries live under
aigw:guardrail:v1:val1:<release-namespace>:<fullname>: and last 24h, clamped
to 1 minute for a DRAFT guardrail, which is republished in place. Requires a
Redis host here or in global.redis.
guardrails.verdictCache.redis.host
Type: string
Default: ""
Redis host. Empty falls back to global.redis.host.
guardrails.verdictCache.redis.port
Type: string
Default: nil
Redis port. Empty falls back to global.redis.port.
guardrails.verdictCache.redis.clusterMode
Type: string
Default: nil
Speak the Redis Cluster protocol. Unset falls back to global.redis.clusterMode.
guardrails.verdictCache.redis.username
Type: string
Default: ""
ACL username. Empty falls back to global.redis.username.
guardrails.verdictCache.redis.existingSecret
Type: string
Default: ""
Secret holding the Redis password, in the release namespace. Empty falls back to global.redis.existingSecret.
guardrails.verdictCache.redis.existingSecretKey
Type: string
Default: ""
Key within that Secret. Empty falls back to global.redis.existingSecretKey.
guardrails.verdictCache.redis.tls
Type: string
Default: nil
Dial Redis over TLS. Unset falls back to global.redis.tls.enabled.
guardrails.verdictCache.macSecret.name
Type: string
Default: ""
Bring your own Secret holding the cache's HMAC key, in the release namespace.
The adapter only reads it. Empty makes the adapter get-or-create
<fullname>-guardrail-cache-mac at startup, through a Role the chart renders
(get pinned to that name, create in the namespace); without that grant it logs a
WARN and screens the whole conversation uncached. A supplied value must be at
least 32 bytes of printable text. Rotation is to replace the value and restart
the adapter, a cache cold start.
guardrails.verdictCache.macSecret.key
Type: string
Default: "mac-secret"
Key within that Secret. Applies to a supplied Secret and to the one the adapter provisions.
guardrails.audience
Type: string
Default: ""
Audience of the token the gateway presents to the adapter. Empty derives
https://<adapter-service>.<release-namespace>.svc.
guardrails.bedrock.guardrailId
Type: string
Default: ""
Bedrock guardrail identifier. Required.
guardrails.bedrock.guardrailVersion
Type: string
Default: ""
Guardrail version: DRAFT or a positive integer, written as a string ("1",
not 1). Required.
guardrails.bedrock.region
Type: string
Default: ""
AWS region of the guardrail, e.g. us-east-1. Required.
guardrails.bedrock.promptWhitelist
Type: object
Default: {"prompts":[],"regexes":[]}
Prompts excluded from screening: exact prompts, or RE2 regexes that match
anywhere unless anchored (^ping$, not ^ping).
guardrails.bedrock.credentialsSecretRef
Type: object
Default: {"name":""}
Secret holding an AWS credentials file under the key credentials. Empty uses
the pod's ambient AWS identity (EKS Pod Identity or IRSA).
guardrails.bedrock.endpoint
Type: string
Default: ""
Bedrock Runtime base URL override, for a PrivateLink endpoint or a test double. Empty uses the SDK's regional endpoint.
guardrails.hook.timeout
Type: string
Default: "5s"
Budget the gateway gives the adapter, as a single-unit Go duration of at most 120s. The adapter's own Bedrock call must finish inside it.
guardrails.hook.tokenExpirationSeconds
Type: int
Default: 3600
Requested lifetime of the projected token, minimum 600.
guardrails.hook.tokenMountPath
Type: string
Default: "/var/run/secrets/guardrails"
Directory the projected token is mounted into on the gateway pod.
guardrails.hook.caMountPath
Type: string
Default: "/etc/guardrails-tls"
Directory the adapter CA bundle is mounted into on the gateway pod.
guardrails.tls.issuerRef
Type: object
Default: {"kind":"","name":""}
cert-manager issuer for the adapter's serving certificate. Empty name falls back to global.webhooks.issuerRef; one of the two must name an issuer.
guardrails.tls.caBundleSecret
Type: string
Default: ""
Secret holding the PEM CA that verifies the adapter's serving certificate, in the release namespace. Empty falls back to global.webhooks.caBundleSecret; one of the two is required.
guardrails.tls.caBundleKey
Type: string
Default: "ca.crt"
Key within that Secret holding the PEM bundle.
guardrails.adapter.image.repository
Type: string
Default value
image-proxy.stacklok.com/proxy/stacklok-enterprise/ghcr.io/stacklok/stacklok-enterprise/ai-gateway-main-processor
Guardrails-adapter image (the ai-gateway main-processor).
guardrails.adapter.image.tag
Type: string
Default: ""
Image tag (defaults to appVersion if empty).
guardrails.adapter.image.digest
Type: string
Default: ""
Optional image digest, appended as @<digest> after the tag.
guardrails.adapter.image.pullPolicy
Type: string
Default: "IfNotPresent"
Image pull policy.
guardrails.adapter.replicas
Type: int
Default: 2
Replica count, and the HPA's minReplicas. Under failurePolicy: Fail a single
adapter is a single point of failure for every request.
guardrails.adapter.maxReplicas
Type: string
Default: nil
Upper bound for the HPA. Unset means no HPA, and replicas is written on the
Deployment.
guardrails.adapter.targetCPUUtilization
Type: string
Default: nil
HPA target average CPU utilization, 1-100. Defaults to 75 when unset.
guardrails.adapter.podAnnotations
Type: object
Default: {}
Annotations added to the adapter pods. The chart's own checksum annotation wins over a same-named entry.
guardrails.adapter.nodeSelector
Type: object
Default: {}
Node labels for adapter pod assignment.
guardrails.adapter.tolerations
Type: list
Default: []
Tolerations for adapter pod assignment.
guardrails.adapter.topologySpreadConstraints
Type: list
Default: []
Topology spread constraints for the adapter pods. Entries without a labelSelector get the adapter's selector labels.
guardrails.adapter.serviceAccount.annotations
Type: object
Default: {}
Annotations on the adapter's ServiceAccount, e.g. the
eks.amazonaws.com/role-arn of an IRSA role.
guardrails.adapter.resources
Type: object
Default:
{"limits":{"cpu":"500m","memory":"256Mi"},"requests":{"cpu":"50m","memory":"64Mi"}}
Adapter container resources.
guardrails.adapter.metrics.enabled
Type: string
Default: nil
Serve the adapter's screening metrics. Unset follows the gateway's telemetry
settings; false turns them off; true always serves port.
guardrails.adapter.metrics.port
Type: int
Default: 9090
Port for the guardrails adapter's Prometheus metrics listener when metrics serving is enabled.