Configuration

Helm values reference for the Tiphys chart. The complete default-values document, with a comment on every field, ships with the chart artifact (run helm show values oci://ghcr.io/intelligant-ai/charts/tiphys --version <version> to dump it locally); this page walks through the main blocks + the settings-to-env-var mapping the ConfigMap template wires up. Pod scheduling and security-context values are covered only there.

Capabilities

modules:
  core:
    enabled: true              # Always on: the baseline (Lynceus)
  cloud:
    enabled: false             # Cloud reads (Aeolus)
    provider: aws              # aws | azure | gcp; inventory reads are
                               # AWS-only today. The model's region is
                               # separate: see Model below.
    billedCosts:
      enabled: false           # Actual costs from AWS Cost Explorer. AWS
                               # bills your account $0.01 per request, so
                               # it's off: costs are list-price estimates
                               # from the free Price List API. Needs the
                               # Cost Explorer IAM policy (iam-setup.md).
      dailyRequestBudget: 20   # At most this many requests a day (UTC).
      cacheHours: 12           # Each answer is reused this long.
  corePlus:
    enabled: false             # Approved changes and scaffolding (Argus)
    writeOperations:
      enabled: false           # Separate toggle: Core Plus on with writes
                               # off is a valid "scaffolding only" mode.
                               # restrictions and resources narrow writes;
                               # see the chart's values.yaml.

Module gating follows this priority order (see Modules for the long version):

  1. Entitlement. Free installs (no license key) are entitled to every module; a license from Intelligant, if set, is authoritative (see License).
  2. Helm values (can opt out of entitled features; never opt in to unentitled ones).
  3. Auto-detection (optional integrations only — Prometheus, ArgoCD, metrics-server, etc.).

Agent runtime

agent:
  clusterName: ""              # Shown in tool-call footers and audit entries.
                               # Blank: the cloud's cluster name, then the
                               # control plane's hostname.
  logLevel: info               # info | debug | warning | error
  schedule:
    healthCheckInterval: 30m   # Reporter cadence
    knowledgeGraphRefresh: 1h  # Scanner re-run
    entitlementCheck: 1h       # License re-verification
    preflightRecheck: 5m       # Model and permission probes re-run
  namespaces:                  # Reserved, not applied yet: scans read every
    include: []                # namespace Tiphys's reader can.
    exclude:
      - kube-system
      - kube-public
      - kube-node-lease

logLevel is how much the backend logs. Leave it at info and set debug while you chase a problem: Tiphys then logs each tool call, AWS call and helm run, with how long it took. Debug lines name what ran (a tool and its verb, an AWS operation and its error code, a helm command) and never carry manifests, values, prompts or secrets, and libraries stay at info (some write credentials into their own debug output). See Troubleshooting.

Which model handles each kind of work isn't here: it's llm.tiers (scheduled for background scans and reports, interactive for chat; each fast or smart, both fast by default), and each provider's models name the model behind a tier. Bedrock's region is llm.bedrock.region. See Model.

Model

Tiphys is tuned for Claude. Pick where it runs with llm.provider; every provider but openai-compatible serves Claude. Whatever the model, it must call tools and take at least 64k tokens of context: Tiphys works through tool calls, and its instructions and tool results are long.

llm.providerWhereHow Tiphys gets in
anthropicThe Anthropic APIAn API key, from a Secret
bedrock (default)Amazon Bedrock, your AWS accountKeyless: IRSA or EKS Pod Identity
vertexVertex AI, your Google Cloud projectKeyless: workload identity
azureAzure AI Foundry (Claude) or Azure OpenAIKeyless: workload identity; or the resource's key
openai-compatibleAny chat-completions endpointA bearer key, if it needs one

Prefer a keyless provider: nothing long-lived to rotate or leak. Keys come only from Secrets you create; the chart never takes a key for these providers as a value. llm.tiers picks the tier per kind of work (scheduled, interactive), and each provider's models.fast and models.smart say which model is behind each tier.

Each investigation, one issue in one chat, may run for a limited time: its model and tool time, never the time waiting on you. At 80% of it Tiphys wraps up with what it found, the evidence and the fix it proposes; at the limit it pauses and asks whether to go on, and your next message starts a new investigation that picks up from the chat. Background work (history summaries) has small fixed limits of its own.

llm:
  investigationMinutes: 10   # 0: no limit

Anthropic API

llm:
  provider: anthropic
  anthropic:
    existingSecret: tiphys-anthropic   # kubectl create secret generic tiphys-anthropic \
    secretKey: api_key                 #   --from-literal=api_key=sk-ant-...
    baseUrl: ""                        # blank: https://api.anthropic.com
    models:
      fast: ""                         # blank: claude-haiku-4-5
      smart: ""                        # blank: claude-sonnet-4-6

Amazon Bedrock

llm:
  provider: bedrock
  bedrock:
    region: us-east-1                  # a region with Claude model access
    models:
      fast: ""                         # blank: Claude Haiku 4.5
      smart: ""                        # blank: Claude Sonnet 4.6
serviceAccount:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/tiphys-irsa

The role needs bedrock:InvokeModel and bedrock:Converse on the models (IAM setup).

Vertex AI

llm:
  provider: vertex
  vertex:
    project: my-project
    region: us-east5                   # a region serving Claude, or "global"
    models:
      fast: ""                         # blank: claude-haiku-4-5@20251001
      smart: ""                        # blank: claude-sonnet-4-6
    serviceAccount: tiphys@my-project.iam.gserviceaccount.com

Enable the Claude models in Vertex AI's Model Garden first. Then, keyless:

  • GKE: turn on workload identity, give the Google service account roles/aiplatform.user, and let the Kubernetes ServiceAccount act as it (roles/iam.workloadIdentityUser for serviceAccount:my-project.svc.id.goog[tiphys/tiphys]). The chart annotates the ServiceAccount with vertex.serviceAccount. Or grant roles/aiplatform.user to the Kubernetes ServiceAccount's principal directly and leave vertex.serviceAccount blank.
  • Any other cluster: workload identity federation. Create a pool and an OIDC provider that trusts your cluster's service-account issuer, then the credential configuration with gcloud iam workload-identity-pools create-cred-config ... --credential-source-file=/var/run/secrets/tiphys/google-token/token. Put that file in a Secret (vertex.credentials.existingSecret, key credentials.json) and set vertex.tokenAudience to the provider's audience; the chart projects the pod's token to that path.

A service-account key file in that Secret works too, as a last resort.

Azure

llm:
  provider: azure
  azure:
    endpoint: https://my-resource.services.ai.azure.com   # or https://my-resource.openai.azure.com
    api: foundry                       # foundry (Claude) | openai (Azure OpenAI)
    apiVersion: "2024-10-21"           # Azure OpenAI only
    models:
      fast: ""                         # deployment names; Foundry's default to
      smart: ""                        # claude-haiku-4-5 / claude-sonnet-4-6
    workloadIdentity:
      clientId: 00000000-0000-0000-0000-000000000000
      tenantId: ""                     # blank: the cluster's default tenant
    existingSecret: ""                 # or the resource's key, from a Secret
    secretKey: api_key

Keyless on AKS: turn on the OIDC issuer and workload identity, create a user-assigned managed identity with the Cognitive Services User role on the resource, and add a federated credential for system:serviceaccount:tiphys:tiphys with your cluster's issuer. Set azure.workloadIdentity.clientId to the identity's client ID; the chart labels the pod and annotates the ServiceAccount for the webhook. Without workload identity, set azure.existingSecret to a Secret holding the resource's key. With api: openai, name your deployments in models (Tiphys doesn't guess); a blank tier uses the other tier's deployment.

OpenAI-compatible endpoint

llm:
  provider: openai-compatible
  openaiCompatible:
    endpoint: https://gateway.example.com/v1
    existingSecret: tiphys-llm         # a Secret with `api_key`; blank for none
    models:
      fast: my-fast-model
      smart: my-smart-model

For a gateway, vLLM, Ollama, or another provider's chat-completions API. Tiphys is tuned for Claude; with other models, results may differ.

Integrations (optional, auto-detected)

integrations:
  prometheus:
    enabled: "auto"            # auto | true | false
    url: ""                    # Override auto-discovery; e.g.
                               # http://prometheus-kube-prometheus-prometheus.monitoring.svc:9090
  metricsServer:
    enabled: "auto"
  externalSecrets:
    enabled: "auto"
  argocd:
    enabled: "auto"
  vpa:
    enabled: "auto"            # Vertical Pod Autoscaler (its CRD)

auto defers to detection: the scanner walks Services / CRDs / APIServices and flips the integration on when it sees the expected shape.

Helm (chart installs)

How Tiphys stores the releases it installs, and which extra chart repositories it can install from:

helm:
  releaseStorage: secret       # secret | configmap
  repos: []                    # Extra chart repositories, registered at
                               # pod startup
  # repos:
  #   - name: my-org-private
  #     url: https://charts.private.my-org.com   # or oci://host[/path]
  #     auth:
  #       existingSecret: helm-private-creds     # keys: username, password
  • secret (default) stores release records as standard Helm 3 Secrets, so helm ls from your shell sees them. When the setting is secret, a startup migration copies any release records Tiphys stored as ConfigMaps to Secrets.
  • configmap stores them as ConfigMaps (the backend gets HELM_DRIVER=configmap); helm ls then needs HELM_DRIVER=configmap too. Pick it when Tiphys must not write Secrets, together with modules.corePlus.writeOperations.resources.secrets: false and customResources: false.

Tiphys already registers a curated set of public repositories (Prometheus Community, Grafana, Bitnami, jetstack, ingress-nginx, argo, and others); repos adds yours. HTTPS repositories are added with helm repo add, OCI registries with helm registry login. Credentials come only from a Secret, never from values.

Authentication

auth:
  mode: builtin                # builtin | proxy | dev | disabled
  builtin:
    sessionTtlHours: 168       # How long a sign-in lasts
    sessionIdleMinutes: 15     # A sign-in nobody uses this long ends (0: never)
    existingSecret: ""         # Optional: a Secret holding the admin password
    existingSecretKey: password
  dev:
    userId: "dev@localhost"
    userEmail: "dev@localhost"
    userGroups: "dev"

builtin (default) signs everyone in as one admin account, with a one-time password created on first start. proxy trusts X-Forwarded-User / X-Forwarded-Email from an authenticating ingress and is the only mode that records each person in the audit log. dev is for local kind clusters; disabled turns auth off. With persistence.mode: configmap, built-in sign-in needs auth.builtin.existingSecret. Setup for each mode is in UI Access.

UI

ui:
  experimental:
    monacoEditor: false        # In-place YAML editing of k8s_apply
                               # manifests in the chat approval card

Experimental UI surfaces, off by default. With monacoEditor on, submitting an edited manifest rejects the current approval and stages a new one with the edited YAML.

Reports + approvals

reports:
  target: configmap            # Reserved: no effect yet. Reports are
  s3Bucket: ""                 #   stored with the rest of Tiphys's state
  retention: 30d               #   (see Persistence), the latest 30 kept.
  recommenderMode: true        # true: findings carry recommendations, the
                               #   operator stages them manually in the UI.
                               # false: the Reporter auto-creates
                               #   ApprovalRequests at cron time so the
                               #   Approvals view populates overnight.
  maxAutoStagedPerTick: 10     # Only applies when recommenderMode=false.

approvals:
  ttlSeconds: 86400            # 24h. Bump to 172800 (48h) for weekend
                               # coverage. Was 5 min pre-v0.0.1 — the old
                               # value only worked for actively-watched
                               # chat approvals.
  configmapName: tiphys-approvals

Persistence

Reports, approvals, snoozes, the audit trail and conversations survive pod restarts. Where they live depends on persistence.mode:

persistence:
  mode: sqlite                 # sqlite | configmap
  size: 5Gi                    # State PVC size (sqlite mode only)
  storageClass: ""             # Blank: the cluster's default StorageClass
  snoozesConfigmapName: tiphys-snoozes              # configmap mode only
  auditEventsConfigmapName: tiphys-audit-events     # configmap mode only:
                               # the audit trail's newest 800 events
  auditConfigmapName: tiphys-audit                  # the earlier audit log,
  auditMaxRetained: 500        # read once into the trail, then left as is
  conversationsConfigmapName: tiphys-conversations  # configmap mode only
  conversationsMaxRetained: 50

audit:
  retentionDays: 365           # Days each audit event is kept; -1 keeps
                               # everything. A license's
                               # audit_retention_days wins.
  adminGroups: []              # proxy mode: groups that see everyone's
                               # events (everyone else sees their own)

podDisruptionBudget:
  create: true                 # minAvailable 1: refuses voluntary
                               # evictions (kubectl drain, autoscaler
                               # scale-down). Turn off only on clusters
                               # without policy/v1.
  • sqlite (default): the chart deploys a StatefulSet with a state PVC mounted at /var/lib/tiphys, and everything goes in one SQLite file, /var/lib/tiphys/state.db. See Backup and Restore.
  • configmap: for clusters with no StorageClass. The chart deploys a Deployment with no PVC, and each store is its own ConfigMap in the pod's namespace: tiphys-reports, tiphys-approvals (approvals.configmapName), tiphys-snoozes, tiphys-audit-events and tiphys-conversations. The reports name is fixed. A ConfigMap holds 1 MiB, so the audit trail keeps its newest 800 events here; SQLite keeps every event for audit.retentionDays.

The audit trail is described in Write operations: what's recorded, retention, who sees what, and the export.

In either mode the scan cache, AWS list prices and billed-cost answers are ConfigMaps (tiphys-scan, tiphys-prices, tiphys-billed-costs).

Notifications

Outbound webhooks only — Tiphys never receives inbound traffic from these:

notifications:
  slack:
    enabled: false
    webhookUrl: ""
  teams:
    enabled: false
    webhookUrl: ""

Notifications fire on new critical findings since the previous report tick; a steady-state crashloop produces one notification, not one per scan interval.

Control plane (opt-in)

Off by default. With controlPlane.enabled: false, Tiphys never contacts Intelligant AI: no client is built, no poll is scheduled, and nothing leaves the cluster. Turn it on if you want Intelligant AI to be able to pause writes or announce maintenance on your install.

controlPlane:
  enabled: false                         # opt in with true
  endpoint: "https://api.intelligant.ai"
  pollSeconds: 300                       # minimum 30

What it sends. One unauthenticated GET {endpoint}/public/products/tiphys/status every pollSeconds, plus one at startup. No cluster name, no install id, no query string, no body, no credentials; the only identifying header is User-Agent: tiphys/<version>. The answer is Intelligant AI's public status for Tiphys, the same for every install.

What it does.

  • While the answer says writes are off (always the case during maintenance), the write-safety gate blocks every write tool before it stages anything, and POST /api/approve refuses to approve a change (the approval stays pending, so you can approve it once writes resume). Reads, chat, and reports keep working.
  • The UI shows a banner: "Tiphys is under maintenance" or "Changes are paused by Intelligant AI", with Intelligant's message and the expected end time.
  • The startup helm-release-record migration (Tiphys's own bookkeeping Secrets) is skipped while writes are paused. It is idempotent and runs on every start, so it catches up on the next restart.

Fail open. If the endpoint is unreachable, times out (5 s), returns a non-2xx, or returns something unexpected, Tiphys keeps the last answer it got. If it has never had an answer, writes are allowed and there is no maintenance. Errors are logged, never raised.

Images

images:
  backend:
    repository: ghcr.io/intelligant-ai/tiphys-backend
    tag: ""                    # Blank: the chart's appVersion
    pullPolicy: IfNotPresent
  frontend:
    repository: ghcr.io/intelligant-ai/tiphys-frontend
    tag: ""
    pullPolicy: IfNotPresent
  pullSecrets: []              # e.g. [{name: my-registry-creds}]

Both images are multi-arch (amd64 + arm64). Air-gapped installs mirror them to an internal registry and point each repository there, with pullSecrets if the registry needs credentials.

Resources

resources:
  backend:
    requests:
      cpu: 200m
      memory: 512Mi
    limits:
      cpu: 1000m
      memory: 1Gi
  frontend:
    requests:
      cpu: 50m
      memory: 64Mi
    limits:
      cpu: 200m
      memory: 128Mi

The backend's memory floor is driven by the LLM client buffering streams in flight. The frontend is a static nginx — the defaults are generous.

ServiceAccount + RBAC

serviceAccount:
  create: true
  name: tiphys                 # Fixed, so the IRSA trust subject is always
                               # system:serviceaccount:<namespace>:tiphys
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123:role/tiphys-irsa
service_account_role_arn: ""   # Shortcut for the annotation above
                               # (--set without escaping dots); wins
                               # when both are set
rbac:
  helmValuesDecode: false      # true: the reader may read every Secret

RBAC roles the chart installs:

  • tiphys-reader — ClusterRole with get/list/watch on standard resources (Pods, Deployments, Services, ConfigMaps, Events, etc.). No Secret access unless rbac.helmValuesDecode=true, which grants cluster-wide Secret read so Helm release views work; read Data residency by inference provider first. Always installed.
  • tiphys-writer — ClusterRole with create/update/patch/delete/deletecollection on the resource classes enabled under modules.corePlus.writeOperations.resources (all on by default; customResources adds a write rule on every API group). No cluster-admin, no secret-content reads. Installed only when both modules.corePlus.enabled and modules.corePlus.writeOperations.enabled are true.
  • tiphys-state — namespaced Role for the agent's own state ConfigMaps, scoped by resource name: tiphys-scan, tiphys-prices and tiphys-billed-costs, plus the five store ConfigMaps in configmap mode. It also has create on ConfigMaps in its namespace (Kubernetes can't scope create by name). Always installed.

License

license:
  key: ""                      # License file contents; empty = free (default)
  existingSecret: ""           # Or reference an existing Secret holding
                               # the license under data.license (preferred)

Tiphys is free: leave both empty and every module is available.

Licenses come from Intelligant. Your company's admin issues one for each install in Intelligant Accounts (Company → Licenses), named for where it runs (for example prod-east), and can download it again later. Treat the file like a credential: install it as a Secret rather than in your values file, and don't paste it into tickets or logs.

kubectl -n tiphys create secret generic tiphys-license --from-file=license=<your-file>
helm upgrade tiphys oci://ghcr.io/intelligant-ai/charts/tiphys -n tiphys \
  --reuse-values --set license.existingSecret=tiphys-license

The license is checked offline against keys built into the image, so air-gapped installs work and nothing is sent to Intelligant. It is re-checked with each cluster rescan (hourly by default). What it covers comes from your plan's limits, and only from the license: Helm values can turn a module off but never on. A license only ever adds to what a free install gets, and today the free install already has everything.

When it expires, Tiphys keeps running as licensed through the license's grace period (usually 14 days). A banner in the UI and warnings in the log name the date it stops. After that, anything only the license covered stops and Tiphys runs on the free tier. Your data (reports, audit log, conversations) stays readable, and the banner says why. Install a renewed license to restore it.

A license that has been altered, wasn't issued for Tiphys, or was signed with a key this version doesn't carry is refused: the reason is in the backend log and Tiphys runs read-only (Core) until a valid license is installed. If a newly issued license is refused for an unknown key, upgrade Tiphys. Licenses Tiphys issued itself before it joined Intelligant keep working until they expire.

For local development, license.key: dev marks the install as dev in the UI and audit trail.

Settings-to-env mapping

The chart's ConfigMap template flattens the Helm values into env vars the backend's Pydantic Settings class reads. The naming rule:

  • modules.cloud.enabled → MODULE_CLOUD_ENABLED
  • agent.logLevel → LOG_LEVEL
  • llm.tiers.scheduled → AGENT_MODEL_SCHEDULED
  • llm.anthropic.models.smart → LLM_ANTHROPIC_MODEL_SMART; likewise LLM_VERTEX_* and LLM_AZURE_* (each renders only for its provider). Keys come from Secrets as LLM_ANTHROPIC_API_KEY, LLM_AZURE_API_KEY and LLM_OPENAI_API_KEY, never through the ConfigMap.
  • integrations.prometheus.url → INTEGRATION_PROMETHEUS_URL
  • reports.recommenderMode → REPORTS_RECOMMENDER_MODE
  • approvals.ttlSeconds → APPROVAL_TTL_SECONDS
  • controlPlane.enabled → CONTROL_PLANE_ENABLED (CONTROL_PLANE_ENDPOINT and CONTROL_PLANE_POLL_SECONDS render only when enabled)

To see the full mapping for an installed release, render the chart and inspect the rendered ConfigMap:

helm get manifest <release-name> -n tiphys \
  | yq 'select(.kind == "ConfigMap" and (.metadata.name | contains("tiphys")))'

To override just one value without rendering the full chart, set the env var directly on the StatefulSet (the Deployment with persistence.mode: configmap) via your own overlay.