Skip to content

feat(dev-images): a harness target by digest and a controller target that follows the line — the Go ADK build through a lab registry, the kagent controller's image name from the render - #154

Merged
teemow merged 1 commit into
mainfrom
feat/dev-images-harness-and-line-controller
Sep 11, 2026

Conversation

@teemow

@teemow teemow commented Sep 11, 2026

Copy link
Copy Markdown
Member

Fixes #139

What

platform.devImages gains the harness target — the platform Harness's workload image, the Go ADK every agent runs on under kagent API v2 — and the kagent controller target now follows the line the lab runs instead of a fixed image name.

The harness target

Under kagent API v2 the agent runtime is no Deployment the lab could patch: the connectivity chart renders the image by digest into the Harness object (the CRD rejects a tag), and Substrate's atelet pulls it from a registry into its own layer cache (/var/lib/ateom-gvisor, the actors' overlay lowerdirs) — never through the node's containerd. A kind side-load is therefore invisible to it; the path atelet implements for local development is the kind local-registry pattern (--localhost-registry-replacement, exposed by the substrate chart as atelet.extraArgs). So agentlab platform:

  1. runs a registry container <clusterName>-registry (registry:3.0.0) on the kind docker network, published on 127.0.0.1:<platform.devRegistryPort> (default 5001; created on demand, removed by agentlab down);
  2. tags and pushes the local build there and reads the manifest digest the registry computed;
  3. renders kagent.harness.image: localhost:<port>/<path>@sha256:<digest> (forwarded by the meta chart to the connectivity chart's Harness) and substrate.atelet.extraArgs: [--localhost-registry-replacement=<clusterName>-registry:5000] (forwarded to the substrate component; the lab's own Substrate values template carries the same flag) — both part of the release, so one plain helm upgrade applies them and removing the entry restores the chart's digest and drops the flag;
  4. after the install asserts the Harness pins the dev digest and waits for every template the Harness admits to recompile (desired revision moved, latest successful revision caught up, Ready), reporting them in the boot log; a platform.valuesFiles overlay that pins kagent.harness.image itself is refused while the target is configured.

The Deployment targets

The image name a kustomize override replaces is now read off the component chart's render — the render the boot already produces to side-load the platform images — so the kagent target replaces ghcr.io/giantswarm/kagent/controller under the kagent line's chart (4.x) and gsoci.azurecr.io/giantswarm/kagent-controller under the 3.x wrapper, whatever Deployment kagent-controller's controller container names. A target whose chart rendered without that Deployment/container is refused before the install (kustomize would drop the override silently); a chart that did not render at all falls back to the table's name with a note.

Also

  • docs/platform.md "Dev images": both targets, the digest constraint (a digest-pinned Harness recompiles every admitted template; the swap is part of the release), the 3.x/4.x controller name rule, the refusal behaviour, platform.devRegistryPort.
  • internal/config: DevImageComponents + DevImageHarness, Platform.DevRegistryPort, validation (harness needs platform.agents).
  • Unit tests: name resolution on both lines and the unmatched-target refusal, the render parser, the registry naming/digest read (httptest), the values templates with and without the target, config validation.

Lab verification

On the shared lab agentlab-dev2 at the released agent-platform 4.7.11 (kagent line 0.11.0-gs.3, Substrate 0.0.27-gs.5 chart-owned, connectivity 4.7.11; agentlab.yaml + a values overlay for the 4.x keys the v0.33.0 template does not render yet), two swap cycles under the lab lock, 2026-09-11 16:58–17:13Z, each restored exactly to the baseline afterwards with the released agentlab v0.33.0 (agentlab.yaml byte-identical, controller back on ghcr.io/giantswarm/kagent/controller:0.11.0-gs.3 with the same imageID, Harness back on the chart's golang-adk@sha256:a2d23f5e…, atelet args back, platform-test PASS 6/6).

Dev images: real local builds of the kagent line's consumed head fdfd405d (giantswarm/kagent-upstream, branch giantswarm) from go/Dockerfilegolang-adk:dev-139-fdfd405 (BUILD_PACKAGE=adk/cmd/main.go, 133 MB) and kagent-controller:dev-139-fdfd405 (core/cmd/controller/main.go, 208 MB), linux/amd64.

platform:
  devImages:
    harness: golang-adk:dev-139-fdfd405
    kagent: kagent-controller:dev-139-fdfd405

Cycle 1 (branch head 529dce4) and cycle 2 (head fca38b2, this PR's head, registry created by the run itself), each agentlab platform exit 0 in 2:03 / 2:17:

  • boot log: platform.devImages.kagent replaces ghcr.io/giantswarm/kagent/controller (Deployment kagent-controller, container controller in the kagent chart's render) (cycle 2), side-loaded 1 dev images, created the lab registry agentlab-dev2-registry (registry:3.0.0 on the kind network, published on localhost:5001), the platform Harness kagent pins localhost:5001/golang-adk@sha256:792306296292dff65e226707b2265948377bc8e34ba7bac7ef661ed74d472ce8, then Harness kagent runs localhost:5001/golang-adk@sha256:7923…; 1 admitted templates recompiled on it: agentlab-agents-test 88c11e38… -> ebfce698… (cycle 2: da820540… -> 904c86c2…);
  • objects: Deployment kagent-controllerdocker.io/library/kagent-controller:dev-139-fdfd405 (pod Running on it, imagePullPolicy: IfNotPresent); Harness kagent gen 8→9 (→11) spec.workload.image: localhost:5001/golang-adk@sha256:7923…; atelet DaemonSet args gained --localhost-registry-replacement=agentlab-dev2-registry:5000; the admitted AgentTemplate agentlab-agents-test's status.harnesses[kagent] moved desiredRevision and caught up latestSuccessfulRevision, Ready=True;
  • atelet log: Image cache miss ref=localhost:5001/golang-adk@sha256:7923…Image pulled into layer cache layers=3 took=0.63s/atelet.AteomHerder/Run + Checkpoint of the golden actor agentlab-agents-test-kagent-ebfce698… — the pull went through the lab registry, rewritten by atelet;
  • proofs with both swaps in place: platform-test PASS 6/6, test 10/10, skills-test PASS 3/3 — its throwaway AgentTemplate booted on the dev Harness image (Harness kagent: image localhost:5001/golang-adk@sha256:7923…, Ready after 20 s, golden snapshot written), one turn through the edge answered from the skill, nothing left behind;
  • restore: removing the two entries and re-running platform moved the Harness back to the chart's digest and the template recompiled onto it (ebfce698… -> da820540…, Ready), the controller back to the line's image.

Not exercised in the lab: the refusal paths (an override matching nothing in the render, an overlay overriding the pin or the atelet list) — unit-tested; agentlab down removing the registry — the shared lab is not torn down.

Rebased onto main after #156/#155 on 2026-09-11 19:01Z (the Substrate template and the lab's own Substrate install are gone with #156: the Harness pin now sits inside the chart's kagent.harness block, the atelet flag inside its substrate block; platformImages takes #156's roster and returns the component renders). Verified by render: without devImages the rebased binary's agentlab render output is identical to main's except the documented substrate.atelet.extraArgs default; with harness + kagent dev images it carries the controller's kustomize override and the atelet flag (the line's image name and the Harness digest are agentlab platform-time, unit-tested); an unknown devImages key is refused with the documented error. Unit tests green (go build, go vet, go test ./...).

Not verified

…that follows the line

platform.devImages gains the harness target: the Go ADK build is pushed to a
lab registry on the kind network and the platform Harness pins it by the
digest the registry computed (kagent.harness.image through the connectivity
values; atelet's --localhost-registry-replacement through the substrate
values), the boot asserting the pin and listing the admitted templates as
they recompile. The Deployment targets resolve the image name they replace
from the component chart's render (the kagent controller is the line's
ghcr.io/giantswarm/kagent/controller on 4.x, the wrapper's on 3.x); an
override that would match nothing is refused before the install instead of
being dropped silently by kustomize.

The Harness (connectivity's object) and atelet (substrate's) reconcile
independently, so a rewrite flag that only arrived with a swap could lose
the race to the Harness's new digest and fail the first golden boot; the
flag is inert for every other ref, so it is rendered whenever the agents
are. checkValues asserts both keys survived the values merge (an overlay
replacing the atelet list would strand the Harness), and the name resolution
notes the image each Deployment override replaces. The lab registry's host
spelling, the Dex SAN and the image-ref parser share one constant.

Refs #139
@teemow
teemow force-pushed the feat/dev-images-harness-and-line-controller branch from fca38b2 to e31521b Compare September 11, 2026 18:58
@teemow
teemow merged commit cf8f600 into main Sep 11, 2026
6 checks passed
@teemow
teemow deleted the feat/dev-images-harness-and-line-controller branch September 11, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dev loop for the kagent line: a harness dev-image target (Harnesses pin by digest) and a controller target that follows the line's image name

1 participant