AI Agents

  • Added

    • The standalone umbrella’s wiring, ported into the connectivity chart and gated on the component toggles the meta chart forwards (roadmap#4348, PRD Q6): with components.backstage on, the portal’s Agent Platform app-config ConfigMap agent-platform-backstage-app-config (the login provider from global.identity, one installation backstage.installationName, the in-cluster Kubernetes and muster entries, agentPlatform.fluxServiceAccountName from the one kagent.fluxServiceAccountName value, the skill repositories, the kagent / model-manager API routes when on, the pg block for backstage.database.engine: postgresql), the public HTTPRoute backstage.<domain> and a post-install/post-upgrade config-reload hook that stamps the rendered app-config’s checksum into the Backstage Deployment’s pod template (kubectl set env by label: a no-op while unchanged, a rolling update on a change, nothing on a first install) with its network policy in both flavors (templates/backstage/); with components.mcp-kubernetes on and muster on, the MCPServer CR that registers the server with muster — OAuth, forwardToken, requiredAudiences: [mcp-kubernetes.kubernetesAudience], the infrastructure tool-group label (templates/mcp-kubernetes/); with the new feature switch components.modelServing on (an entry without chart:: the loop renders no release for it and forwards its flag like every other; a top-level block named after a switch — modelServing: — travels with forwardAllValues only while the switch is on, so a live connectivity chart that predates the block never sees it), model serving on KServe with vLLM from the modelServing: block — the ClusterServingRuntime, the seven shipped serving presets and their discovery ConfigMap, the Hugging Face cache PVC, the Kyverno cache policies (modelServing.policies.enabled: auto, resolved with the other cluster-shape knobs) and the serving namespace’s network policies in both flavors (templates/model-serving/, files/model-serving/), plus the guard that a model-manager on the kserve backend agrees with the layer; the render fails with a clear message when components.modelServing is on without components.kserve-crd and components.kserve-resources (or a cluster that serves the serving.kserve.io APIs; modelServing.kserve.requireApi: false skips the check); and with components.kserve-resources / components.kserve-llmisvc-resources on, the controllers’ network policies and guards (templates/kserve/). The wiring’s own keys keep the standalone’s names minus components. — backstage.<hostname, parentRefs, installationName, extraScopes, startUrlSearchParams, enabledExtensions, disabledExtensions, skillsRepositories, catalogs, configReload> and mcp-kubernetes.kubernetesAudience live in the chart blocks and are dropped from the values forwarded to the strict component charts (components.backstage.omitKeys, components.mcp-kubernetes.omitKeys); modelServing.* is the standalone’s components.modelServing.* one-to-one; components.kserve.* maps onto the four kserve component toggles (README, “Turning on the standalone’s extras”). The seven values blocks of the extras are no longer held back from the connectivity release (components.agent-platform-connectivity.omitKeys is empty), the connectivity release dependsOn muster (the MCPServer CRD) and backstage dependsOn agent-platform-connectivity (its pod mounts the ConfigMap rendered there). The kagent UI route guard from the standalone lands too: a kagent.uiRoute.hostname override with an oauth2-proxy redirect-url still derived from global.domain fails the render. global.identity.ca (secretName, key) is declared by the connectivity chart and accepted by the meta chart (global.identity is additionalProperties: true there — no default, so the global block injected into every component release is unchanged). make verify-wiring (in CI) asserts off = no object, the objects and guards on, both flavors and the vanilla shape, and the meta chart’s forwarding. No installation needs to act: every toggle is off on the fleet; the connectivity HelmRelease’s values gain the seven blocks and the modelServing roster line, its dependsOn gains muster, and the connectivity chart renders byte-identical objects from them — one Helm revision of that release, no object change, no pod rolled.
  • Fixed

    • A fresh install with components.kagent.enabled and postgres.enabled deadlocked: the kagent controller mounts the CNPG Secret kagent-pg-app that the connectivity release renders, while connectivity dependsOn kagent for its CRDs, so the kagent install waited for a controller that could never start (FailedMount), timed out, was uninstalled and retried, and connectivity never installed. The kagent child HelmRelease now carries install.disableWait: true (new per-component key components.<name>.installDisableWait): the first install is reported once the manifests (CRDs, Deployment) are applied, connectivity proceeds, the controller starts as soon as the Cluster exists; upgrades keep waiting for the rollout. make verify-meta asserts it. Existing installations see only the changed HelmRelease spec, no Helm action.
  • Added

    • The chart brings its own Flux engine (roadmap#4348, PRD Q1/Q2/Q3/Q9): helm install of the meta-package on a cluster without Flux yields a running platform. The new flux-engine subchart (helm/agent-platform/charts/flux-engine, released with this chart, the only dependencies: entry of Chart.yaml, condition: components.flux.enabled, default true) carries the seven Flux CRDs of source-controller and helm-controller and the four Flux Operator CRDs in its crds/, and renders the Flux Operator (ghcr.io/controlplaneio-fluxcd/flux-operator 0.59.0 as a Renovate-managed pin, web UI off, no network policy — the upstream chart’s Deployment/ServiceAccount/cluster-admin binding/metrics Service, lifted verbatim) and one FluxInstance named flux in the release namespace (distribution.version: "2.x" from ghcr.io/fluxcd, components: [source-controller, helm-controller], cluster.multitenant: true with tenantDefaultServiceAccount: default, no network policy). The operator upgrades Flux — controllers, CRDs, stored objects — inside the range on its own. Its values live under flux-engine:. components.flux is a feature switch, not a component: an entry without a chart key takes part in the roster and the enablement logic but renders no release (templates/components.yaml). Measured on a fresh kind cluster: helm install --wait deployed in about two minutes, the FluxInstance Ready at Flux v2.9.5 in 15 s.
    • The tenant identity agent-platform-flux: a ServiceAccount in the release namespace bound to cluster-admin, rendered by the subchart; gitops.serviceAccountName defaults to it whenever the engine is on, so every platform HelmRelease names it (under the lockdown a HelmRelease without one runs as the rights-less default account and fails). The fleet keeps "" and its exempt namespace and renders none.
    • Render guards for the engine (agent-platform.validateEngine): with the engine on, a cluster that already runs Flux — a helm-controller Deployment (app.kubernetes.io/component=helm-controller) or a FluxInstance outside the release namespace, looked up live under the Helm CLI, --dry-run=server and helm-controller — fails the render with this cluster runs Flux; set components.flux.enabled=false or install the chart through it; gitops.namespace set to another namespace fails (the tenant identity lives in the release namespace); with the engine off, turning it off on an installation that runs it fails (an upgrade would delete the operator together with the FluxInstance it finalizes and hang). helm template sees no cluster and renders the engine.
    • The ordered teardown: pre-delete hook Jobs (templates/hooks/, rendered only with the engine on) — a hook ServiceAccount + ClusterRoleBinding <release>-hooks to cluster-admin at weight -10, <release>-teardown-releases at weight 0 deleting the platform HelmReleases by name in gitops.namespace and waiting, <release>-teardown-engine at weight 5 deleting the FluxInstance and waiting; one plain kubectl command each in the distroless registry.k8s.io/kubectl (gitops.hooks.image, a Renovate-managed pin), restricted pod security, --ignore-not-found, hook-delete-policy: before-hook-creation,hook-succeeded; weights -6/-5 are reserved for the self-management hooks. helm uninstall --wait returns clean in well under a minute; the operator removes Flux including its CRDs (every HelmRelease object with them, the agents’ included; workloads and Helm storage stay), the four operator CRDs remain, a reinstall is clean. Without the hooks Helm deletes the operator together with the FluxInstance and hangs for its timeout (measured).
    • A kind install smoke in the ATS (.ats/main.yaml runs the smoke step with app-tests-skip-app-deploy: true; tests/ats/test_smoke.py): the Gateway API CRDs, then helm install --wait of the candidate with tests/test-values.yaml (the kind shape: engine on, muster + dicebear + connectivity, valkey off, muster’s OAuth server and the network policies off — the auto knobs resolve the rest), asserting the release deployed, the FluxInstance Ready at a Flux 2.x, every component HelmRelease Ready as agent-platform-flux, one Helm revision, the operator as field manager of the Flux CRDs; then helm uninstall --wait in under a minute with no Flux CRD left and the operator CRDs kept, and a clean reinstall. execute-chart-tests runs it on every PR.
    • make verify-engine (tests/verify-engine.py, in CI with Helm 3.17.3): engine off renders no CRD, no hook, no operator, no FluxInstance, no identity and no serviceAccountName, the fleet shape stays clean; engine on renders exactly the eleven CRDs, the operator objects, the FluxInstance (two controllers, multitenant), the identities and the hooks at their weights, every HelmRelease names agent-platform-flux, the teardown Job names every rendered HelmRelease; the two shapes’ OCIRepository/HelmRelease documents are identical but for serviceAccountName and the roster; Chart.yaml’s only dependency is flux-engine, conditional, a local directory, its version and appVersion in step with the subchart. make verify-meta asserts the pure-renderer rule with the engine off and that the one dependency is not a component pin. README: a quick start (domain, identity, components — nothing about Flux), the engine, clusters that run Flux, uninstalling, Helm versions. Management clusters need not act: they carry components.flux.enabled: false already (management-cluster-bases#721), and the fleet render with it is byte-identical. Other installations that run their own Flux set the value before upgrading — see UPGRADE.md.
  • Fixed

    Full Changelog: https://github.com/giantswarm/muster/compare/v5.14.0...v5.14.1

  • Changed

    Full Changelog: https://github.com/giantswarm/klaus/compare/v0.1.0...v0.1.1

  • Fixed

    Full Changelog: https://github.com/giantswarm/klausctl/compare/v0.4.0...v0.4.1

  • Fixed

    • The kagent Namespace (kagent.namespaceOverride, when it differs from the release namespace) renders only while the kagent component is on — the last of the standalone generator’s nine template patches, landed upstream. An installation without kagent no longer gets an empty, Helm-owned kagent namespace, and turning kagent off removes it with the release. On a management cluster where kagent is off, the connectivity upgrade deletes the empty kagent namespace; the fleet’s hand-written kagent-flux identity that used to live there was handed over to the chart first (where kagent runs) or orphaned (where it does not), so nothing else is in it. Where kagent is on, nothing changes.
  • Added

    • kagent.fluxServiceAccountName (default kagent-flux), in both charts: the tenant identity of the agents’ Flux HelmReleases, from ONE value. The connectivity chart renders ServiceAccount kagent-flux in the kagent namespace with a RoleBinding to cluster-admin (namespace-scoped admin: full control of the kagent namespace, nothing outside it) whenever kagent is on (templates/kagent/flux-service-account.yaml); the meta chart derives agent-manager’s flux.helmReleaseServiceAccount from the same value (agent-platform.componentDerivedValues, merged over the forwarded agent-manager block — agent-manager.flux.helmReleaseServiceAccount is no longer set in values.yaml, and a value set there must agree or the render fails naming the one key); and the agent-platform.kagent.fluxServiceAccountName helper exports it for the portal’s agentPlatform.fluxServiceAccountName. Changing it in one place changes all three; an empty value renders no identity and hands both callers an empty name. Under a Flux multi-tenancy lockdown (helm-controller with --no-cross-namespace-refs and a rights-less default ServiceAccount, or the Flux multi-tenancy admission policy on Giant Swarm management clusters) a HelmRelease without it runs as the default ServiceAccount and fails with secrets is forbidden. make verify-identity (in CI) asserts the objects, the single value across the three consumers, the guard and the empty case. No installation needs to act: a management cluster carried the same two objects hand-written in its Flux bases; the chart’s copy has the same spec, helm-controller takes ownership of them on the upgrade (its default) and both writers set the same fields. The hand-written copy is removed from the bases in a follow-up.

    Fixed

    • Six of the text patches the standalone umbrella’s generator applied to its copy of the connectivity templates were bugs here too and are fixed at their upstream location, so no generator is needed:
      • The kagent UI HTTPRoute (kagent.uiRoute without oauth2-proxy) targets the Service the kagent chart names from kagent.fullnameOverride (kagent-ui), not <release>-ui — as the oauth2-proxy branch and the controller route already did. The fleet runs the oauth2-proxy branch, so its render is unchanged.
      • The muster / HTTPRoute renders only while the muster component is on (components.muster.enabled): hostname-less on a shared Gateway, it blackholed every request when an umbrella turned muster off. The meta chart force-enables muster, so the fleet render is unchanged.
      • ingress.mode: muster-direct refuses the knobs that render agentgateway.dev objects or attach to the agentgateway Gateway — kagent.controllerRoute.enabled, klausGateway.agentgatewayRoute.enabled, and agent-platform-mcps’ agentgateway.enabled with mcpServers set — naming the knob, instead of shipping objects the API server rejects on a cluster without the agentgateway CRDs (the model-manager / agent-manager routes already guarded themselves this way). ci/test-klausgateway-obo-values.yaml moves to agentgateway-muster, ci/test-mcps-values.yaml sets agent-platform-mcps.agentgateway.enabled: false; every management cluster runs agentgateway-muster.
      • The legacy component-toggle probe (agent-platform.validateLegacyToggles, both charts) reports a leftover <block>.enabled whatever its value, also true under a component that is on: neither chart has a Helm dependency, so no chart default is ever coalesced into those blocks and the key can only be the operator’s. The “on + true passes” leg and its prose described an umbrella that feeds the blocks to real dependencies (the standalone patched both); make verify-modes asserts the strict probe in both charts.
      • The kserve API guard of the model-manager wiring defers to the platform’s own KServe when it is bundled: with components.kserve-resources or components.modelServing on, that component’s guards own the check (a missing API is then the first install) and the message names the components. The new agent-platform.optionalComponentEnabled helper treats a component absent from the roster as off — unlike componentEnabled, whose absent-is-on rule is for the force-on components.
      • The agent-platform.serviceMonitor helper’s prose stated default true, which an umbrella flipped; with the knob defaulting to auto (#291) the prose says so and no umbrella has a reason to flip it.
  • Added

    • The cluster-shape knobs default to auto and render by served API group (roadmap#4348, PRD Q4): kyvernoPolicies.enabled renders the Kyverno objects when kyverno.io/v1 is served; networkPolicy.flavor is cilium when cilium.io/v2 is served, else kubernetes; global.observability.metrics.serviceMonitor.enabled renders the monitor objects when monitoring.coreos.com/v1 is served; dicebear.route.enabled (an Envoy HTTPRouteFilter user) follows gateway.envoyproxy.io/v1alpha1; agentSandbox.podSecurity.enabled (a Kyverno mutate policy) follows the resolved kyvernoPolicies.enabled. The meta chart detects once, from .Capabilities.APIVersions (live under helm-controller, the Helm CLI and --dry-run=server; Helm’s built-in set under helm template, so an offline render without --api-versions yields the vanilla shape), resolves every knob before it inlines a component’s values, and derives the component-level copies from the same answers while they are left at auto: muster.networkPolicy.flavor, muster.muster.observability.metrics.prometheus.serviceMonitor.enabled / .prometheusRule.enabled, muster.muster.observability.grafanaDashboard.enabled, valkey.ciliumNetworkPolicy.enabled, valkey.valkey.metrics.podMonitor.enabled (written false only where monitors are off), kagent.otel.tracing.enabled / .logging.enabled, kagent.oauth2-proxy.metrics.serviceMonitor.enabled and the OTEL_EXPORTER_OTLP_HEADERS entry of kagent.controller.env (dropped when both OTel exporters are off). The connectivity chart carries the same defaults and the same resolution helpers (agent-platform.shape.*) for renders on its own; under the meta chart it receives resolved values, so the two cannot disagree on one cluster. Explicit true / false (cilium / kubernetes) values keep winning, on a knob and on a component copy; the schema accepts auto|true|false (auto|cilium|kubernetes) and rejects anything else; the connectivity chart’s .Capabilities guards for the Flux and KServe APIs stay hard failures. make verify-auto (in CI) asserts the resolution per shape, the byte-identical fleet render, the vanilla shape and the overrides. No installation needs to act: with the fleet’s API groups served the render is byte-identical to before; a kind or plain cloud cluster renders the vanilla shape from the same chart without a values file that describes it.
  • Added

    • Seven components, off by default — the extras the agent-platform-standalone umbrella carried as Helm dependencies on top of this roster, so a cluster with none of them turns them on from the same components: map: components.backstage (the Giant Swarm Backstage portal, 0.x), components.mcp-kubernetes (>=1.1.1 <2.0.0, the global.identity fallbacks its block relies on), components.cloudnative-pg (the upstream CloudNativePG operator from oci://ghcr.io/cloudnative-pg/charts, 0.29.x — one chart minor is one operator line and an operator upgrade rolls every instance pod, so moving it is a deliberate edit) and the four KServe charts components.kserve-crd, components.kserve-resources, components.kserve-llmisvc-crd, components.kserve-llmisvc-resources (0.2.x, one repository, moving together). Each is rendered by the existing loop as one OCIRepository + HelmRelease; the new top-level blocks backstage:, mcp-kubernetes:, cloudnative-pg:, kserve-crd:, kserve-resources:, kserve-llmisvc-crd:, kserve-llmisvc-resources: carry the standalone’s defaults (Backstage’s chart Ingress and VPA off, the base config restated, the Agent Platform app-config mounted from agent-platform-backstage-app-config, the credentials Secret and optional identity-provider CA from global.identity; mcp-kubernetes as an OAuth 2.1 resource server acting as the user with downstream OAuth; KServe in Standard deployment mode without per-model routes; the llm-d controller reusing the shared objects) and are forwarded verbatim with global injected. dependsOn replaces the standalone’s two-phase first-install guard: kserve-resources after kserve-crd, kserve-llmisvc-resources after kserve-crd, kserve-llmisvc-crd and kserve-resources, backstage after cloudnative-pg, and the CR consumers agent-platform-connectivity (the CNPG Cluster, the model serving objects) after cloudnative-pg and kserve-resources, model-manager after kserve-resources — every reference dropped at render time while the component is off, as before. None of the seven ships a crds/ dir (kserve-crd, kserve-llmisvc-crd and cloudnative-pg render their CRDs as templates, upgraded with the release), so none carries a crds: policy. kserve-llmisvc-crd is a component the standalone could not have: its 4.5 MB of CRDs did not fit in the umbrella’s one release Secret; as its own release it does. examples/customer-bom.yaml pins all seven (the standalone’s tested pins). The roster forwarded to the connectivity release carries the seven flags, so the wiring the standalone rendered by hand for them (the Backstage app-config and route, the mcp-kubernetes MCPServer, the model serving runtimes) can gate on them when it moves into the connectivity chart in a following release; the connectivity chart declares the seven roster entries and the seven blocks already. make verify-components asserts the roster (off by default, sources, ranges, order, BOM pins, the forwarded tree against the connectivity schema, schema symmetry between the two charts); make verify-components-charts pulls the seven charts at the range’s resolution and at the BOM pin and renders each with the forwarded values. No installation needs to act: the fleet render changes by the seven <name>: {enabled: false} roster lines inside the connectivity HelmRelease’s values only — one Helm revision of that release with unchanged objects and no pod rolled.
    • components.<name>.omitKeys applies to a forwardAllValues component too, dropping top-level blocks from the forwarded tree. components.agent-platform-connectivity.omitKeys holds the seven new blocks back from the connectivity release until its wiring reads them: that chart’s root schema is additionalProperties: false, and while both charts release off one tag, the fleet’s connectivity release re-resolves its chart on its own OCIRepository interval — a block the live chart does not declare would fail that release on every installation until the chart caught up. The release that adds the wiring drops the blocks from the list; the connectivity values.yaml declares them from this release on, so that step has no such window.