Agyn Platform Charts

June 12, 2026 · View on GitHub

This repository publishes production umbrella Helm charts for Agyn workloads. The charts compose service charts published under oci://ghcr.io/agynio/charts.

Charts

ChartPurpose
charts/agyn-platformDeploys the core platform services as one umbrella chart.
charts/agyn-appsDeploys optional apps plus the default Kubernetes runner.

Repository layout

platform-charts/
├── README.md
├── charts/
│   ├── agyn-platform/
│   │   ├── Chart.yaml
│   │   ├── values.yaml
│   │   ├── values.schema.json
│   │   └── templates/
│   └── agyn-apps/
│       ├── Chart.yaml
│       ├── values.yaml
│       ├── values.schema.json
│       └── templates/
└── .github/workflows/
    └── chart-release.yaml

Secret-first configuration

Production installs should provide database URLs, S3 credentials, app service tokens, and runner service tokens through pre-created Kubernetes Secrets. The charts intentionally do not require plaintext secrets in values files.

Example database secret:

kubectl create secret generic agyn-platform-database-urls \
  --from-literal=agents=postgresql://agents:REDACTED@postgres.example.com:5432/agents \
  --from-literal=threads=postgresql://threads:REDACTED@postgres.example.com:5432/threads

Example S3 secret for the files service:

kubectl create secret generic agyn-files-s3 \
  --from-literal=access-key=REDACTED \
  --from-literal=secret-key=REDACTED

Install

Install the platform chart:

helm dependency update charts/agyn-platform
helm upgrade --install agyn-platform charts/agyn-platform \
  --namespace platform \
  --create-namespace \
  --values production-platform-values.yaml

Install apps and the default runner:

helm dependency update charts/agyn-apps
helm upgrade --install agyn-apps charts/agyn-apps \
  --namespace apps \
  --create-namespace \
  --values production-apps-values.yaml

Published OCI installs use:

helm upgrade --install agyn-platform oci://ghcr.io/agynio/charts/agyn-platform \
  --version 0.1.0 \
  --namespace platform \
  --create-namespace \
  --values production-platform-values.yaml

helm upgrade --install agyn-apps oci://ghcr.io/agynio/charts/agyn-apps \
  --version 0.1.0 \
  --namespace apps \
  --create-namespace \
  --values production-apps-values.yaml

Local validation

helm dependency update charts/agyn-platform
helm dependency update charts/agyn-apps
helm lint charts/agyn-platform charts/agyn-apps
helm template agyn-platform charts/agyn-platform >/tmp/agyn-platform.yaml
helm template agyn-apps charts/agyn-apps >/tmp/agyn-apps.yaml
helm package charts/agyn-platform --destination .dist
helm package charts/agyn-apps --destination .dist
yamllint .

NATS JetStream event bus

agyn-platform can deploy NATS with JetStream as an optional dependency for durable platform service events. It is disabled by default for backwards compatibility. Enable it with:

nats:
  enabled: true

Default NATS settings deploy the upstream nats Helm chart with JetStream file storage, a persistent volume claim, and the stable in-cluster endpoint nats://nats:4222. The platform contract exposes that endpoint as platform.eventBus.url and the future workload environment variable name as platform.eventBus.urlEnvName (NATS_URL).

The chart also renders a stream configuration Job when nats.platform.streams.enabled is true. The default streams are:

nats:
  platform:
    streams:
      definitions:
        - name: AGYN_GROUPS
          subjects:
            - agyn.groups.>
        - name: AGYN_NETWORKS
          subjects:
            - agyn.networks.>

The stream defaults follow the architecture contract: file storage, limits-based retention, 7-day replay window, 1Gi per stream, one replica, and a 2-minute duplicate window. The JSON consumed by the stream configuration Job uses the NATS API schema, so stream duration values are configured in nanoseconds and stream sizes are configured in bytes. Production deployments can raise nats.platform.streams.replicas and the upstream NATS cluster settings together.

Registration and tokens

agynio/bootstrap currently registers apps/runners and creates service tokens through Terraform resources. These umbrella charts only deploy workloads and wire configuration. Registration IDs and service tokens must be supplied as pre-created Kubernetes Secrets or non-secret values where appropriate.

Platform database and S3 source Secrets

agyn-platform wires workloads directly to operator-provided Secrets. It does not render intermediate Secrets and does not require plaintext database URLs or S3 credentials in Helm values.

Database URLs come from platform.database.existingSecret. The key for each service is derived from platform.database.existingSecretKeyPattern; the pattern is evaluated with a service variable and defaults to the service name:

platform:
  database:
    mode: external
    existingSecret: agyn-platform-database-urls
    existingSecretKeyPattern: "{{ .service }}"

Each database-backed dependency must point at that same Secret/key contract. The default values already do this. If you change the top-level database Secret or key pattern, update the matching dependency override paths in the same values file; the chart validates these refs during render and fails if they drift. Important override paths are:

agents.env[].valueFrom.secretKeyRef
agents-orchestrator.env[].valueFrom.secretKeyRef
apps.env[].valueFrom.secretKeyRef
chat.env[].valueFrom.secretKeyRef
expose.env[].valueFrom.secretKeyRef
groups.env[].valueFrom.secretKeyRef
identity.env[].valueFrom.secretKeyRef
organizations.env[].valueFrom.secretKeyRef
runners.env[].valueFrom.secretKeyRef
threads.env[].valueFrom.secretKeyRef
tracing.env[].valueFrom.secretKeyRef
users.env[].valueFrom.secretKeyRef
ziti-management.env[].valueFrom.secretKeyRef
secrets.database.existingSecret
llm.llm.databaseUrl
files.files.databaseUrl

Example custom database Secret and key pattern:

platform:
  database:
    existingSecret: prod-db-urls
    existingSecretKeyPattern: "{{ .service }}-url"

agents:
  env:
    - name: GRPC_ADDRESS
      value: ":50051"
    - name: DATABASE_URL
      valueFrom:
        secretKeyRef:
          name: prod-db-urls
          key: agents-url

files:
  files:
    databaseUrl:
      existingSecret: prod-db-urls
      existingSecretKey: files-url

The database Secret should contain keys for:

agents
agents-orchestrator
apps
chat
expose
files
groups
identity
llm
organizations
runners
secrets
threads
tracing
users
ziti-management

Groups event bus enablement

groups.enabled=true requires a reachable NATS event bus because the Groups service publishes membership events on startup paths. Use one of these options:

groups:
  enabled: true
nats:
  enabled: true

Or point the platform event bus contract at an externally managed NATS endpoint:

groups:
  enabled: true
  env:
    - name: GRPC_ADDRESS
      value: ":50051"
    - name: DATABASE_URL
      valueFrom:
        secretKeyRef:
          name: agyn-platform-database-urls
          key: groups
    - name: AUTHORIZATION_GRPC_TARGET
      value: authorization:50051
    - name: IDENTITY_GRPC_TARGET
      value: identity:50051
    - name: NATS_URL
      value: nats://external-nats.example.com:4222
platform:
  serviceEndpoints:
    nats: nats://external-nats.example.com:4222
  eventBus:
    url: nats://external-nats.example.com:4222

When groups.enabled=true, render-time validation fails if the chart is still using the default in-cluster NATS endpoint while nats.enabled=false. Groups service target metadata comes from platform.serviceEndpoints.groups and must match the rendered Groups service target from groups.fullnameOverride. External event bus values must also update groups.env[NATS_URL] because the Groups dependency consumes its environment list directly.

S3 credentials for the files service are also wired directly to the operator-provided Secret. files.files.s3.accessKey.existingSecret and files.files.s3.secretKey.existingSecret must match s3.existingSecret, while their key fields must match s3.accessKeyKey and s3.secretKeyKey:

s3:
  existingSecret: agyn-files-s3
  accessKeyKey: access-key
  secretKeyKey: secret-key
  endpoint: s3.example.com
  bucket: agyn-files
  region: us-east-1
  useSSL: true
  forcePathStyle: false

files:
  files:
    s3:
      endpoint: s3.example.com
      bucket: agyn-files
      region: us-east-1
      useSSL: true
      accessKey:
        existingSecret: agyn-files-s3
        existingSecretKey: access-key
      secretKey:
        existingSecret: agyn-files-s3
        existingSecretKey: secret-key

The existing files subchart remains a chart dependency. The non-secret S3 settings are set on files.files.s3.*; forcePathStyle is additionally exposed to the files container as S3_FORCE_PATH_STYLE through the agyn-platform-files-s3-config ConfigMap because the files subchart does not have a native value for it.

Set validation.requireExistingSecrets=true for install/upgrade against a live cluster to fail rendering when the referenced DB/S3 Secrets or required keys are missing. This validation uses Helm lookup, so it requires access to the target cluster and is disabled by default for offline helm lint / helm template workflows.

Override points

The platform chart exposes a top-level non-sensitive OpenFGA contract at openfga.apiUrl, openfga.storeId, and openfga.modelId. The chart renders those values into the agyn-platform-openfga ConfigMap and wires the authorization subchart through authorization.extraEnvVarsCM.

Sensitive cluster-admin token configuration is not exposed as plaintext. The gateway subchart receives CLUSTER_ADMIN_TOKEN through gateway.env using a Kubernetes Secret reference. Override gateway.env directly when your Secret name or key differs:

gateway:
  env:
    - name: CLUSTER_ADMIN_TOKEN
      valueFrom:
        secretKeyRef:
          name: agyn-cluster-admin
          key: token

The apps chart intentionally exposes only dependency toggles at apps.*.enabled and runners.k8s.enabled. Runtime configuration maps directly to the dependent subchart values:

  • reminders.env
  • telegram-connector.env
  • k8s-runner.env

Use those paths to override database URL Secret refs, service token Secret refs, app IDs, gateway addresses, runner namespace, runner PVC size, and other workload environment values.

Egress-specific dependency overrides are validated against the same top-level contract. The Egress control-plane database Secret ref must match platform.database.existingSecret and the key produced by platform.database.existingSecretKeyPattern for egress. Gateway, Secrets, Egress, and Egress Gateway service targets must match platform.serviceEndpoints.*; render fails if those dependency overrides drift.

Required Egress Gateway env vars are wired by default:

EGRESS_ADDRESS
SECRETS_SERVICE_ADDRESS
NOTIFICATIONS_ADDRESS
METERING_ADDRESS
TRACING_ADDRESS
AGENTS_SERVICE_ADDRESS
ZITI_MANAGEMENT_ADDRESS
ZITI_IDENTITY_FILE
EGRESS_CA_CERT_PATH
EGRESS_CA_KEY_PATH

Egress deployment contract

agyn-platform deploys the Egress control-plane service (egress) and the Egress Gateway data-plane service (egress-gateway) by default. The platform chart expects the platform database Secret to include an egress connection string key, matching platform.database.existingSecretKeyPattern.

The Egress CA contract is fixed across deployment layers:

  • Secret name: egress-ca
  • Public certificate key: tls.crt
  • Private key key: tls.key
  • Egress Gateway mount path: /var/run/agyn/egress-ca/
  • Egress Gateway env vars: EGRESS_CA_CERT_PATH and EGRESS_CA_KEY_PATH

The Egress Gateway Ziti identity is consumed from the egress-gateway-ziti-identity Secret and mounted at /var/lib/ziti. In bootstrap environments this Secret is created by the bootstrap platform stack; in external environments operators must provide an enrolled identity Secret with an identity.json key before enabling egress-gateway.

gateway.gateway.egressRulesGrpcTarget and secrets.egressRules.grpcTarget are both validated against platform.serviceEndpoints.egress so Gateway and Secrets call the configured Egress control-plane service instead of drifting to the legacy egress-rules name.