Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- **Dev channel (branch `poc/kagent-main`): Substrate comes from the Giant Swarm line.** `kagent.substrateWorkerPool.workerImage` is `ghcr.io/giantswarm/substrate/ateom-gvisor:0.0.27-dev.giantswarm.2026-09-10.19-33-37.h734ec53` — the gVisor worker image the fork [giantswarm/substrate](https://github.com/giantswarm/substrate) publishes from its `giantswarm` branch (upstream kagent-dev/substrate 0.0.26, the version the kagent line's `go.mod` pins, plus the cherry-picked kagent-dev/substrate#33; its `FORK.md` is the ledger of pin, carried patches and published digests) instead of upstream's `ghcr.io/kagent-dev/substrate/ateom-gvisor:v0.0.26`. The fork tags images with the bare version. The Substrate control plane a cluster runs (installed by agentlab, later by meta chart 4.0) must be the same version: the README's Substrate prerequisite names the fork's charts. The render is otherwise unchanged. The ATS smoke clears `components.agent-platform-connectivity.semverFilter` and `gitops.self.semverFilter` where it pins the candidate's exact version: on this line the defaults admit only `poc-kagent-main` builds, so the candidate of a pull request against the line (a `-dev.<pr-branch>.` version) matched nothing and every smoke on such a pull request failed at the install — pushes to the branch itself were unaffected.
- **Dev channel (branch `poc/kagent-main`, the kagent API v2 line).** The chart's defaults follow the RFC dev builds of its sibling POC branches: `components.agent-platform-connectivity` `versionRange: ">=3.0.0-0 <4.0.0-0"`, `components.backstage`, `components.model-manager`, `components.agent-manager` `versionRange: ">=0.0.0-0 <1.0.0-0"`, each with `semverFilter: ".*-dev\\.poc-kagent-main\\..*"`, and `gitops.self.semverFilter` the same, so a consumer selects the meta chart's dev channel once and every sibling follows its own branch's newest build. kagent is kagent `main` from the kagent fork's `poc/agent-platform` branch, published under `ghcr.io/giantswarm` (`components.kagent` and the new roster entry `components.kagent-crds`: `oci://ghcr.io/giantswarm/kagent/helm`, `versionRange: ">=0.11.0-0 <0.12.0-0"`, `semverFilter: ".*-dev\\.poc-agent-platform\\..*"`; kagent `dependsOn` kagent-crds, the connectivity release too; the render refuses kagent on without kagent-crds); the `kagent:` block carries the fork's image names under `registry: ghcr.io` with an explicit `tag`, `controller.substrate.*` (Agent Substrate in `ate-system`, a cluster prerequisite), the `substrateWorkerPool` (`kagent-default`, 4 gVisor workers), pgvector on the bundled Postgres, `serviceMonitor.enabled: false` (kagent `main` serves no metrics listener) and the two platform `harnesses[]` (Go ADK and Claude Code, digest-pinned); `kagent-crds:` keeps its kmcp and Substrate CRD subcharts off. The filter constant is defined once, in the `components:` preamble of `values.yaml`, together with the switch to `.*-bd384adaft.*` once gitsemver ships the RFC's final tag schema. **The release of this line resets all of it**: every `semverFilter` goes and the ranges return to the stable lines (`agent-platform-connectivity` `">=1.0.0"`, the three siblings `"0.x"`, kagent to the GS wrapper on gsoci). The customer BOM example pins the dev builds and clears the filters (an exact pin with a filter matches nothing).
- The connectivity chart wires kagent `main` (`kagent.dev/v1alpha3`) — a POC branch, not for a `main` merge while the fleet runs the kagent 0.2.x wrapper (v1alpha2). The shared muster `RemoteMCPServer`, `kagent.remoteMcpServers[]` and `kagent.modelConfigs[]` render as `v1alpha3`; the muster server moves from the release namespace into the kagent namespace and loses `allowedNamespaces` — on `main` an `AgentTemplate`'s `tools[].mcp.server` binds a server of its own namespace only, and the agents are `AgentTemplate`s agent-manager and the portal write there, as the person. New `kagent.harnesses[]` renders the platform's `Harness` objects: runtime type (`kagent | claude | codex | byo`), a digest-pinned `workload.image` (a tag fails the render, as the CRD would fail it at admission), optional `command`/`args`/`env`, the Substrate `workerPoolRef` and `snapshotPolicy.location`, and the `allowedAgentTemplates` selector (default `kagent.dev/harness: <name>`); the meta chart holds the key back from the kagent release (`omitKeys`). Both charts declare a passthrough `kagent-crds` values block for the kagent-crds component an installation adds to the roster (kagent `main` ships its CRDs as their own chart, which the kagent release `dependsOn`); without it the meta chart's root schema refused those values. The two kagent declarative-agent Kyverno `ClusterPolicy`s and the seccomp `PolicyException` are gone with the `Agent` CRD, the per-agent Deployments and the config Secrets they mutated — agents run as Substrate actors in gVisor worker pods — and with them `kyvernoPolicies.seccompPolicyName` / `seccompRuleNames`. The Backstage app-config's `agentPlatform.kagent.installations.<installation>.apiBaseUrl` is `https://<agentgateway hostname><pathPrefix>` with no `/api` suffix: the controller serves gRPC, gRPC-Web and `/mcp` on one port and no REST. The kagent network policies are unchanged and their agent-pod selectors (`app: kagent`) are documented as v1alpha2-shaped (actor traffic leaves through Substrate's `atenet-egress`; unverified in the POC). `make verify-kagent-harnesses` asserts the Harness render and its guards; `verify-kagent-discovery` the API version, the kagent namespace and the absence of `allowedNamespaces`; `verify-modes` the remaining kyverno.io object count.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ spec:

`ref.semverFilter` needs source-controller ≥ v1.3 (spidertron runs v1.9.5). The `HelmRelease` keeps `components.flux.enabled: false`; add `components.kagent-crds.enabled: true` next to kagent and drop the two `kyvernoPolicies.seccomp*` keys. The image discovery of a mirror-on-PR setup does not see the components' images (the meta chart renders no workloads), so the cluster pulls gsoci and `ghcr.io/giantswarm` directly; both are public. To go **back** to the stable line, restore `semver: ">=3.20.2 <4.0.0"` without the filter — a prerelease never outranks the stable releases the range admits.

**The Substrate prerequisite.** kagent `main` needs [Agent Substrate](https://github.com/kagent-dev/substrate) (0.0.26) on the cluster, which this chart does not install: (1) the apiserver feature gates `ClusterTrustBundle`, `ClusterTrustBundleProjection`, `PodCertificateRequest` and `--runtime-config=certificates.k8s.io/v1beta1=true`, the same gates on the controller manager and every kubelet; (2) the charts `oci://ghcr.io/kagent-dev/substrate/helm/substrate-crds` and `…/substrate` (0.0.26, exact pins) into `ate-system`; (3) the bootstrap objects the charts mount but do not create — the four pools `service-dns-ca-pool`, `pod-identity-ca-pool` (namespace `podcertificate-controller-system`), `actor-id-jwt-pool`, `actor-id-ca-pool` (`ate-system`), the Secret `actor-id-ca-certs` and the ConfigMap `ate-api-authentication` with the cluster's service-account issuer (`https://kubernetes.default.svc.cluster.local` on kubeadm and kind) — generated once (`kubectl-ate admin make-ca-pool` / `make-jwt-pool` from the substrate release, or agentlab's port) and, on a GitOps cluster, committed encrypted. The recipe and its objects are kagent's [`setup-cluster.sh`](https://github.com/kagent-dev/kagent/blob/main/scripts/setup-cluster/setup-cluster.sh) and the substrate repository's docs; the `WorkerPool` the Harnesses run on (`kagent-default`) comes with the kagent release (`kagent.substrateWorkerPool`), the gVisor `SandboxConfig` with the substrate chart. Worker pods need caps and an `Unconfined` AppArmor profile a restricted-PSS cluster (Kyverno) must except, and egress to `storage.googleapis.com` for the gVisor assets.
**The Substrate prerequisite.** kagent `main` needs Agent Substrate on the cluster, which this chart does not install — the Giant Swarm line of [kagent-dev/substrate](https://github.com/kagent-dev/substrate), published from [giantswarm/substrate](https://github.com/giantswarm/substrate) (branch `giantswarm`: upstream 0.0.26 plus cherry-picked fixes; its `FORK.md` records pin, patches and versions) as `ghcr.io/giantswarm/substrate/*` images and `oci://ghcr.io/giantswarm/substrate/helm` charts at `0.0.27-dev.giantswarm.…` versions: (1) the apiserver feature gates `ClusterTrustBundle`, `ClusterTrustBundleProjection`, `PodCertificateRequest` and `--runtime-config=certificates.k8s.io/v1beta1=true`, the same gates on the controller manager and every kubelet; (2) the charts `oci://ghcr.io/giantswarm/substrate/helm/substrate-crds` and `…/substrate` (the exact version `kagent.substrateWorkerPool.workerImage` names — the worker image and the control plane are one Substrate version) into `ate-system`; (3) the bootstrap objects the charts mount but do not create — the four pools `service-dns-ca-pool`, `pod-identity-ca-pool` (namespace `podcertificate-controller-system`), `actor-id-jwt-pool`, `actor-id-ca-pool` (`ate-system`), the Secret `actor-id-ca-certs` and the ConfigMap `ate-api-authentication` with the cluster's service-account issuer (`https://kubernetes.default.svc.cluster.local` on kubeadm and kind) — generated once (`kubectl-ate admin make-ca-pool` / `make-jwt-pool` from the substrate release, or agentlab's port) and, on a GitOps cluster, committed encrypted. The recipe and its objects are kagent's [`setup-cluster.sh`](https://github.com/kagent-dev/kagent/blob/main/scripts/setup-cluster/setup-cluster.sh) and the substrate repository's docs; the `WorkerPool` the Harnesses run on (`kagent-default`) comes with the kagent release (`kagent.substrateWorkerPool`), the gVisor `SandboxConfig` with the substrate chart. Worker pods need caps and an `Unconfined` AppArmor profile a restricted-PSS cluster (Kyverno) must except, and egress to `storage.googleapis.com` for the gVisor assets.

**Switching the filter when gitsemver ships the RFC schema.** The RFC's final dev tag is `X.Y.Z-b<crc32(branch), 8 hex>t<YYYYMMDDHHMMSS>c<sha7>`; gitsemver v2.0.1 does not emit it yet. When it does (architect-orb / app-build-suite pick it up), the constant becomes `.*-bd384adaft.*` for this branch (`crc32 IEEE("poc/kagent-main") = d384adaf`) — change every `semverFilter` in `values.yaml` (the preamble lists them), `gitops.self.semverFilter`, `tests/verify-components.py` and the consumers' `OCIRepository`s; the kagent charts' constant follows the kagent fork's branch the same way (`poc/agent-platform` → `d7bda063`).

Expand Down
2 changes: 1 addition & 1 deletion helm/agent-platform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ This chart version is a build of the `poc/kagent-main` branch — the kagent API
| kagent.substrateWorkerPool.create | bool | `true` | |
| kagent.substrateWorkerPool.name | string | `"kagent-default"` | |
| kagent.substrateWorkerPool.replicas | int | `4` | |
| kagent.substrateWorkerPool.workerImage | string | `"ghcr.io/kagent-dev/substrate/ateom-gvisor:v0.0.26"` | |
| kagent.substrateWorkerPool.workerImage | string | `"ghcr.io/giantswarm/substrate/ateom-gvisor:0.0.27-dev.giantswarm.2026-09-10.19-33-37.h734ec53"` | |
| kagent.substrateWorkerPool.sandboxClass | string | `"gvisor"` | |
| kagent.ui.image.repository | string | `"giantswarm/kagent/ui"` | |
| kagent.database.postgres.vectorEnabled | bool | `true` | |
Expand Down
19 changes: 12 additions & 7 deletions helm/agent-platform/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1433,8 +1433,11 @@ kagent: # @schema skipProperties: true; additionalProperties: true
# Harnesses (kagent main has no skills-init image any more).
agentImage:
repository: giantswarm/kagent/golang-adk
# Agent Substrate (kagent-dev/substrate 0.0.26), a cluster prerequisite on
# this line: agents run as Substrate actors in gVisor worker pods, so the
# Agent Substrate — the Giant Swarm line of kagent-dev/substrate
# (giantswarm/substrate, branch giantswarm: upstream 0.0.26 plus
# cherry-picked fixes, published as ghcr.io/giantswarm/substrate; its
# FORK.md is the ledger) — a cluster prerequisite on this line: agents run
# as Substrate actors in gVisor worker pods, so the
# controller talks to ate-api (with its PodCertificate client certificate)
# and routes through atenet; every Harness names a WorkerPool of the kagent
# namespace — the one substrateWorkerPool below creates. Substrate itself
Expand Down Expand Up @@ -1484,15 +1487,17 @@ kagent: # @schema skipProperties: true; additionalProperties: true

# The Substrate WorkerPool (ate.dev/v1alpha1) the Harnesses run on, rendered
# by the kagent chart in the kagent namespace: platform capacity, not an
# agent's. workerImage is the gVisor worker of the Substrate release the
# cluster runs (the chart requires it when create is true); sandboxClass
# gvisor is what kagent's generated ActorTemplates select. Four workers is
# the POC's sizing; raise replicas for more concurrent agents.
# agent's. workerImage is the gVisor worker of the Substrate version the
# cluster runs — the line's image, tagged with the bare version the fork
# publishes (agentlab installs the same version; a re-pin of the line moves
# both together) — and the chart requires it when create is true;
# sandboxClass gvisor is what kagent's generated ActorTemplates select. Four
# workers is the POC's sizing; raise replicas for more concurrent agents.
substrateWorkerPool:
create: true
name: kagent-default
replicas: 4
workerImage: ghcr.io/kagent-dev/substrate/ateom-gvisor:v0.0.26
workerImage: ghcr.io/giantswarm/substrate/ateom-gvisor:0.0.27-dev.giantswarm.2026-09-10.19-33-37.h734ec53
sandboxClass: gvisor

ui:
Expand Down
10 changes: 8 additions & 2 deletions tests/ats/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@
# prerelease version (3.19.1-dev.<branch>.<date>.h<sha>, abs), and Masterminds
# semver — Flux's — never matches a prerelease against a release-only bound
# (`>=X <4.0.0`), so the derived range would find no tag. A released chart
# has no prerelease; verify-self asserts the derived range offline.
# has no prerelease; verify-self asserts the derived range offline. The exact
# pin also clears the chart's semverFilter: a dev line's default filter admits
# one branch's builds (`.*-dev\.<branch>\..*`), and the candidate of a pull
# request against that line carries its own branch name, so an exact pin
# behind the filter matches nothing (the README's BOM example says the same).
SELF_INTERVAL = "1m"
SELF_INTERVAL_S = 60

Expand All @@ -140,6 +144,7 @@ def self_management_sets(version: str) -> List[str]:
"gitops.self.insecure=true",
f"gitops.self.interval={SELF_INTERVAL}",
f"gitops.self.versionRange={version}",
"gitops.self.semverFilter=",
]


Expand All @@ -155,12 +160,13 @@ def connectivity_sets(version: str) -> List[str]:
return [
f"components.{CONNECTIVITY}.repository={REGISTRY_URL}",
f"components.{CONNECTIVITY}.versionRange={version}",
f"components.{CONNECTIVITY}.semverFilter=",
f"components.{CONNECTIVITY}.insecure=true",
]


def connectivity_values(version: str) -> Dict[str, Any]:
return {"components": {CONNECTIVITY: {"repository": REGISTRY_URL, "versionRange": version, "insecure": True}}}
return {"components": {CONNECTIVITY: {"repository": REGISTRY_URL, "versionRange": version, "semverFilter": "", "insecure": True}}}

# ---------------------------------------------------------------------------
# Processes, waiting, timing
Expand Down
Loading