Skip to content

feat(controller): make Go (ADK) runtime agent image independently configurable - #2021

Merged
EItanya merged 11 commits into
kagent-dev:mainfrom
QuentinBisson:feat/go-runtime-image-config
Jul 21, 2026
Merged

EItanya merged 11 commits into
kagent-dev:mainfrom
QuentinBisson:feat/go-runtime-image-config

Conversation

@QuentinBisson

@QuentinBisson QuentinBisson commented Jun 15, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2018.

What

Adds DefaultGoImageConfig (registry, repository, tag, pullPolicy) so the Go (ADK) runtime agent image is configured independently instead of being derived from the Python repository by string surgery. Exposed end-to-end as:

  • --go-image-{registry,repository,tag,pull-policy} controller flags (auto-mapped to GO_IMAGE_* env vars via LoadFromEnv)
  • controller.goAgentImage.{registry,repository,tag,pullPolicy} Helm values
  • GO_IMAGE_* ConfigMap keys, following the same defaulting as agentImage/skillsInitImage (registry/pullPolicy default to the globals, tag coalesces with the global tag then the Chart version)

Defaults are encoded in the variable (ghcr.io/kagent-dev/kagent/golang-adk), matching DefaultImageConfig and DefaultSkillsInitImageConfig. Since #2242, regular declarative agents reference the image by tag; sandbox agents still pin by digest via GoADKImageDigest / GoADKFullImageDigest. The -full variant selection is unchanged for both paths.

Why

When spec.declarative.runtime: go is used, the controller derived the Go runtime repository from the Python repository by replacing the last path segment with golang-adk. This breaks for flat-name registry layouts (e.g. a mirrored registry where the image is my-registry.io/kagent-golang-adk, which the derivation cannot produce).

Breaking change

Operators who mirror images and only set agentImage no longer get a derived Go image location; they must set controller.goAgentImage as well. The controller logs a startup warning when the two registries differ so a misconfigured mirror is visible before a Go agent fails to pull. As discussed in the review thread, this targets a minor release (0.10.x).

Files changed

File Change
go/core/internal/controller/translator/agent/adk_api_translator.go DefaultGoImageConfig with encoded defaults
go/core/internal/controller/translator/agent/deployments.go Go image resolution via DefaultGoImageConfig; tag threaded through resolveRuntimeImage
go/core/pkg/app/app.go four --go-image-* flags + registry-mismatch startup warning
helm/kagent/values.yaml controller.goAgentImage block
helm/kagent/templates/controller-configmap.yaml GO_IMAGE_* keys
go/core/internal/controller/translator/agent/runtime_test.go, imageconfig_test.go tests updated to tag-based expectations

@github-actions github-actions Bot added the enhancement New feature or request label Jun 15, 2026
@QuentinBisson
QuentinBisson marked this pull request as ready for review June 15, 2026 17:52
Copilot AI review requested due to automatic review settings June 15, 2026 17:52
@QuentinBisson
QuentinBisson force-pushed the feat/go-runtime-image-config branch from 3e0ab42 to 10a9c6f Compare June 15, 2026 17:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds Go (ADK) runtime image configurability so operators can override registry/repository/pull policy independently from the default (Python) agent image, while preserving the existing derived-repo behavior.

Changes:

  • Introduces controller.goAgentImage Helm values and wires them into the controller ConfigMap as GO_IMAGE_* settings.
  • Adds controller flags for Go runtime image overrides and a DefaultGoImageConfig to drive translation.
  • Updates translator logic + adds unit tests covering explicit Go repo/registry overrides and fallback derivation.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
helm/kagent/values.yaml Adds controller.goAgentImage values with fallback/derivation semantics.
helm/kagent/templates/controller-configmap.yaml Exposes Go image override values via GO_IMAGE_* entries when set.
go/core/pkg/app/app.go Adds --go-image-* flags to set Go-specific image defaults.
go/core/internal/controller/translator/agent/adk_api_translator.go Introduces DefaultGoImageConfig global for Go runtime image overrides.
go/core/internal/controller/translator/agent/deployments.go Applies Go-specific registry/pullPolicy overrides and optional repository override logic.
go/core/internal/controller/translator/agent/runtime_test.go Adds tests for explicit Go repo/registry overrides and fallback derivation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread go/core/pkg/app/app.go Outdated
Comment on lines +221 to +223
commandLine.StringVar(&agent_translator.DefaultGoImageConfig.Registry, "go-image-registry", "", "The registry to use for the Go (ADK) runtime agent image. When empty, falls back to --image-registry.")
commandLine.StringVar(&agent_translator.DefaultGoImageConfig.Repository, "go-image-repository", "", "The repository to use for the Go (ADK) runtime agent image. When empty, derived from --image-repository by replacing the last path segment with \"golang-adk\".")
commandLine.StringVar(&agent_translator.DefaultGoImageConfig.PullPolicy, "go-image-pull-policy", "", "The pull policy to use for the Go (ADK) runtime agent image. When empty, falls back to --image-pull-policy.")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: the flags now use the DefaultGoImageConfig fields as StringVar defaults, same as the skills-init-image-* flags. Defaults are encoded in the config since the derivation fallback was dropped.

Comment on lines +541 to +544
img := deployment.Spec.Template.Spec.Containers[0].Image
assert.Contains(t, img, "/kagent-golang-adk@", "Image should use the explicit flat repository")
assert.NotContains(t, img, "/golang-adk@", "Derived path must not appear when repository is explicitly set")
assert.Contains(t, img, "@sha256:test-go-base")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: the tests now assert equality on the full image reference (e.g. my-registry.io/kagent-golang-adk:v0.0.0-test) instead of substring matching.

Comment on lines +174 to +185
// Resolve base registry and pull policy; Go runtime uses DefaultGoImageConfig fields
// when set, falling back to DefaultImageConfig for any unset field.
baseRegistry := DefaultImageConfig.Registry
basePullPolicy := DefaultImageConfig.PullPolicy
if runtime == v1alpha2.DeclarativeRuntime_Go {
if DefaultGoImageConfig.Registry != "" {
baseRegistry = DefaultGoImageConfig.Registry
}
if DefaultGoImageConfig.PullPolicy != "" {
basePullPolicy = DefaultGoImageConfig.PullPolicy
}
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added TestRuntime_GoImageConfig_ExplicitPullPolicy: asserts the Go deployment uses the explicit pull policy and the Python deployment does not inherit it.

…figurable

Adds DefaultGoImageConfig (registry, repository, pullPolicy) with per-field
fallback to DefaultImageConfig and the existing golang-adk derivation logic.
Exposed as --go-image-{registry,repository,pull-policy} flags (auto-mapped to
GO_IMAGE_* env vars via LoadFromEnv) and as controller.goAgentImage.* Helm values.

Fixes registry layouts where the Python repository is a flat name that cannot
produce a valid path via last-segment replacement (e.g. kagent-golang-adk).

Tag is not configurable — Go runtime images are digest-pinned at link time.

Closes kagent-dev#2018

Signed-off-by: QuentinBisson <[email protected]>
@QuentinBisson
QuentinBisson force-pushed the feat/go-runtime-image-config branch from ac8e81a to b54ae33 Compare June 15, 2026 17:57
// the derived repository (last segment of DefaultImageConfig.Repository replaced with
// "golang-adk") when Repository is empty. Tag is unused — Go runtime images are
// digest-pinned at controller link time via GoADKImageDigest / GoADKFullImageDigest.
var DefaultGoImageConfig = ImageConfig{}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we just encode the defaults into this variable like we do for the other image configs?

@QuentinBisson QuentinBisson Jun 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @iplay88keys I wanted to preserve the issue's framing.

The empty default was there to avoid a breaking change: the controller currently derives the Go image from agentImage.repository, so anyone mirroring images only sets that one value and the Go image follows. If we hardcode the default and always emit GO_IMAGE_REPOSITORY, their next helm upgrade silently repoints the Go image back to cr.kagent.dev and pods fail to pull.

I do agree that this is not the better change though and I will replace this PR with the way it is done for the other images.

@iplay88keys iplay88keys Jun 17, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, is there another workaround we can build in? Maybe something like: if they are overriding the image for the python image, but not for the go image, throw an error/warning?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be able to add a log warning if the 2 registries are different yes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EItanya thoughts on the breaking change aspect? I'm thinking it's fine if we document it and we'd likely want that to go in on a minor release to draw attention to the breaking nature of that change.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @iplay88keys suggestion, this would likely go into the next minor release where we will make go runtime by default and it would be helpful to be able to configure go runtime images. So I think the breaking change would be fine as it's more clear in the long run

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, we can put it in 0.10.x

@github-actions

Copy link
Copy Markdown

This pull request has been marked as stale because of no activity in the last 15 days. It will be closed in the next 5 days unless it is tagged "no stalebot" or other activity occurs.

@github-actions github-actions Bot added the stale This issue or PR has become stale label Jul 11, 2026
Encode concrete defaults into DefaultGoImageConfig (registry, repository,
pullPolicy) like the other image configs, and drop the repository derivation
from the Python image. The Helm chart always emits GO_IMAGE_* and defaults the
registry to the global registry, so mirroring through .Values.registry covers
the Go runtime image too. The controller warns at startup when the Go and agent
image registries differ.

Signed-off-by: QuentinBisson <[email protected]>
@QuentinBisson
QuentinBisson requested a review from a team as a code owner July 11, 2026 23:28
@github-actions github-actions Bot removed the stale This issue or PR has become stale label Jul 12, 2026

@iplay88keys iplay88keys left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few changes that will need to be made to work with main. The biggest is that regular declarative agents are now referenced by tag and digests are only used for sandbox agents.

// Tag is unused: Go runtime images are digest-pinned at controller link time
// via GoADKImageDigest / GoADKFullImageDigest.
var DefaultGoImageConfig = ImageConfig{
Registry: "cr.kagent.dev",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be changed to ghcr.io

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Rebased on main and moved the defaults to ghcr.io/kagent-dev/kagent/golang-adk. Also adapted to #2242: regular Go agents are now tag-referenced (new tag field on goAgentImage, --go-image-tag, GO_IMAGE_TAG), sandbox agents still pin by digest.

Adapts to kagent-dev#2242 (declarative agents referenced by tag, digests only for
sandbox agents):
- DefaultGoImageConfig defaults to ghcr.io/kagent-dev/kagent/golang-adk
  and now carries a Tag (regular Go agents are tag-referenced)
- resolveRuntimeImage takes the tag as a parameter so the Go runtime
  resolves via DefaultGoImageConfig.Tag
- new --go-image-tag flag, controller.goAgentImage.tag Helm value and
  GO_IMAGE_TAG ConfigMap key (coalesced with global tag / Chart version)
- tests updated from digest to tag expectations; drops the upstream
  derivation test superseded by explicit Go image config
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Jul 17, 2026
@EItanya
EItanya merged commit ebb7ecb into kagent-dev:main Jul 21, 2026
30 checks passed
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
kagent 0.10.0

Created-by: HarmonybrewBot
Commit-by: HarmonybrewBot
Merged-by: HarmonybrewBot
Description: Created by `brew bump`

---

Created with `brew bump-formula-pr`.<details>
  <summary>release notes</summary>
  <pre><!-- Release notes generated using configuration in .github/release.yml at v0.10.0 -->

## What's Changed
### Features
* feat(streaming): configurable nginx, controller, and UI inactivity ti… by @yanivmn in kagent-dev/kagent#1973
* feat(helm): add controller service annotations by @anthonyhaussman in kagent-dev/kagent#2088
* feat: enable sharing of chat sessions by @onematchfox in kagent-dev/kagent#1935
* feat: substrate support for BYO and python runtimes for SandboxAgent CR by @jmhbh in kagent-dev/kagent#2043
* feat(substrate): bump agent substrate to 0.0.7 by @supreme-gg-gg in kagent-dev/kagent#2109
* feat(substrate): bump agent substrate to 0.0.8 by @jjamroga in kagent-dev/kagent#2140
* feat(helm/kagent): support deployment annotations by @anthonyhaussman in kagent-dev/kagent#2143
* feat: add nodeSelector support to agent helm charts by @the-mentor in kagent-dev/kagent#2145
* feat: expose icon, provider, documentation URL and version on agent A2A card by @QuentinBisson in kagent-dev/kagent#2188
* feat: add claude ACP sandbox target by @the-mentor in kagent-dev/kagent#2189
* feat(sandbox-agents): Store session state in `durableDir` volume for declarative sandbox agents by @jmhbh in kagent-dev/kagent#2171
* feat(helm): add UI HTTPRoute by @younsl in kagent-dev/kagent#2165
* feat(helm): bump bundled oauth2-proxy subchart to ~10.7.0 by @elihai-risk in kagent-dev/kagent#2254
* feat: default nodeSelector for agent deployments (--default-agent-node-selector) by @elihai-risk in kagent-dev/kagent#2259
* feat(helm): add podLabels for controller and UI pod templates by @elihai-risk in kagent-dev/kagent#2237
* feat(helm): add extraObjects for arbitrary manifests by @younsl in kagent-dev/kagent#2174
* feat(ui-test): Playwright ui tests foundation stage 0 by @cjlg-soloio in kagent-dev/kagent#2262
* feat: allow read-only shares to read A2A tasks by @QuentinBisson in kagent-dev/kagent#2191
* feat(controller): make Go (ADK) runtime agent image independently configurable by @QuentinBisson in kagent-dev/kagent#2021
* feat(helm): allow custom annotations on the default ModelConfig by @marians in kagent-dev/kagent#2201
* feat(ui-test): Playwright UI E2E suite — helpers + feature flows (stage 2) by @cjlg-soloio in kagent-dev/kagent#2264
* feat: serve A2A ListTasks from the task store by @QuentinBisson in kagent-dev/kagent#2187
* feat(models): add maxCompletionTokens for OpenAI by @anthonytwh in kagent-dev/kagent#2175
* feat(models): wire maxOutputTokens for native Gemini and Vertex by @anthonytwh in kagent-dev/kagent#2147
* feat: add envFrom support to agent deployment spec by @uncycler in kagent-dev/kagent#2321
* feat: add native AWS Bedrock Guardrails support to ModelConfig by @sanskar-singh-2403 in kagent-dev/kagent#2323
* feat(bedrock): configurable Bedrock read/connect timeout by @go-faustino in kagent-dev/kagent#2223
* feat: add deploymentAnnotations to agent deployment spec by @anthonyhaussman in kagent-dev/kagent#2359
* feat(helm/kagent): allow disabling default modelconfig by @anthonyhaussman in kagent-dev/kagent#2142
* feat(sts): send RFC 8707 resource and audience on token exchange by @QuentinBisson in kagent-dev/kagent#2106
* feat(sts): send RFC 8707 resource and audience on token exchange (Python) by @QuentinBisson in kagent-dev/kagent#2107
* Backport of 2407 (pg connection) to 0.10.x release by @supreme-gg-gg in kagent-dev/kagent#2399
* Backport 2409 (db session cleanup) to 0.10.x release by @supreme-gg-gg in kagent-dev/kagent#2403
* Backport of 2408 (s3 skills) to 0.10.x release by @supreme-gg-gg in kagent-dev/kagent#2405
* feat: configurable refresh interval for tool server controllers by @supreme-gg-gg in kagent-dev/kagent#2480
* feat: support file upload in agent chat by @supreme-gg-gg in kagent-dev/kagent#2429
### Bug Fixes
* fix(ui): chat interface overflows viewport causing input to be hidden below fold by @onematchfox in kagent-dev/kagent#2081
* fix(ui): avoid false stale chat send guard by @erauner12 in kagent-dev/kagent#2034
* fix(go-adk): extract system prompt from genai.GenerateContentConfig in Ollama and Bedrock model providers by @supreme-gg-gg in kagent-dev/kagent#2118
* fix(helm): support omitting image.registry in grafana-mcp chart by @michaelspinks in kagent-dev/kagent#2125
* fix(helm): support omitting image.registry in querydoc chart by @michaelspinks in kagent-dev/kagent#2124
* fix(security): patch CRITICAL/HIGH CVEs in golang-adk-full and app images by @jsonmp-k8 in kagent-dev/kagent#2133
* fix(go-adk): openai embeddings generation by @supreme-gg-gg in kagent-dev/kagent#2132
* fix(helm): omit empty repository segment in bundled image path by @michaelspinks in kagent-dev/kagent#2120
* fix: intermittent Postgres deadlock for concurrent memory searches by @supreme-gg-gg in kagent-dev/kagent#2146
* fix(deps): bump google-adk to 1.32.0 for Anthropic thinking blocks by @anxkhn in kagent-dev/kagent#2172
* fix: fix typos in part_converter comments by @mesutoezdil in kagent-dev/kagent#2195
* fix(adk): annotate serialize_metadata_value as str | dict by @anxkhn in kagent-dev/kagent#2173
* fix(ui): fix model name editing on the model config form by @Valyrian-Code in kagent-dev/kagent#1979
* fix: correct package comment in v1alpha2 groupversion_info by @mesutoezdil in kagent-dev/kagent#2183
* fix(crewai): unwrap Part before DataPart check so structured inputs are used by @anxkhn in kagent-dev/kagent#2231
* fix(helm): expose nodeSelector and tolerations for kagent-tools subchart by @the-mentor in kagent-dev/kagent#2213
* fix(helm): make the cluster DNS domain configurable by @shekhargit1912 in kagent-dev/kagent#2209
* fix: parse migration filenames the same way golang-migrate does by @mesutoezdil in kagent-dev/kagent#2194
* fix: build sandbox runtime outside QEMU emulation by @peterj in kagent-dev/kagent#2299
* fix: set kgateway.dev/a2a as appProtoco for BYO agents by @supreme-gg-gg in kagent-dev/kagent#2305
* fix(db): normalize agent name in memory vector search by @mesutoezdil in kagent-dev/kagent#2307
* fix(adk/bedrock): coerce nil tool-call args to empty object by @go-faustino in kagent-dev/kagent#2222
* fix: correct webhook typo in CLI help text by @tziyon31 in kagent-dev/kagent#2203
* fix(build): use AZURE_OPENAI_API_KEY env var name consistently by @mesutoezdil in kagent-dev/kagent#2310
* fix(security): scope task get, create, and delete to the owner by @mesutoezdil in kagent-dev/kagent#2265
* fix(adk): keep token refresh loop alive after a failed read by @mesutoezdil in kagent-dev/kagent#2330
* fix(acp-shim): drain child stdout during terminate to avoid teardown deadlock by @tomsen02 in kagent-dev/kagent#2338
* fix(adk): keep full session state when num_recent_events is set by @mesutoezdil in kagent-dev/kagent#2329
* fix(controller): wire up SessionSharesHandler in NewHandlers (#2363) by @onematchfox in kagent-dev/kagent#2420
* fix: ensure API key passthrough works for OpenAI embedding models by @onematchfox in kagent-dev/kagent#2494
* fix(adk): validate ask_user questions by @erauner12 in kagent-dev/kagent#2486
* Backport fix(golang-adk): resolve user identity from A2A call context to 0.10.x by @buravc in kagent-dev/kagent#2507
* fix(a2a): serve exact task reads from the persistent store by @erauner12 in kagent-dev/kagent#2484
* fix(ui): preserve post-login redirect target through `oauth2-proxy` sign-in by @onematchfox in kagent-dev/kagent#2532
### Documentation
* docs: fix duplicate descriptions and broken link in README by @mesutoezdil in kagent-dev/kagent#2068
* docs: fix typos and errors in component READMEs by @mesutoezdil in kagent-dev/kagent#2070
* docs: fix typos and list formatting in contributor docs by @mesutoezdil in kagent-dev/kagent#2069
* docs: replace outdated AutoGen reference in SECURITY.md by @mesutoezdil in kagent-dev/kagent#2110
* docs(python): fix kagent-langgraph README import to kagent.langgraph by @anxkhn in kagent-dev/kagent#2167
* docs(python): fix KAgentSession import path in kagent-openai README by @anxkhn in kagent-dev/kagent#2163
* docs: fix stale references and 

See merge request: Harmonybrew/homebrew-core!18335
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Make the Go runtime agent image independently configurable

6 participants