Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ var PythonADKFullImageDigest string
var GoADKImageDigest string
var GoADKFullImageDigest string

// DefaultGoImageConfig is the image config for the Go (ADK) runtime agent.
// Regular agents reference it by tag; sandbox agents pin by digest via
// GoADKImageDigest / GoADKFullImageDigest.
var DefaultGoImageConfig = ImageConfig{
Registry: "ghcr.io",
Tag: version.Get().Version,
PullPolicy: string(corev1.PullIfNotPresent),
Repository: "kagent-dev/kagent/golang-adk",
}

// DefaultSkillsInitImageConfig is the image config for the skills-init container
// that clones skill repositories from Git and pulls OCI skill images.
var DefaultSkillsInitImageConfig = ImageConfig{
Expand Down
51 changes: 20 additions & 31 deletions go/core/internal/controller/translator/agent/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"maps"
"slices"
"strings"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
Expand Down Expand Up @@ -92,31 +91,14 @@ func getDefaultNodeSelector(incoming map[string]string) map[string]string {
return nodeSelector
}

// getRuntimeImageRepository returns the image repository for a given runtime.
// It respects DefaultImageConfig.Repository for the Python runtime, and derives
// the Go runtime repository by replacing the last path segment with "golang-adk".
// This ensures custom repository configurations (e.g., --image-repository flag) work correctly.
// getRuntimeImageRepository returns the image repository for a given runtime:
// DefaultGoImageConfig.Repository for the Go runtime, DefaultImageConfig.Repository
// otherwise.
func getRuntimeImageRepository(runtime v1alpha2.DeclarativeRuntime) string {
switch runtime {
case v1alpha2.DeclarativeRuntime_Go:
// Derive Go runtime repository from the default Python repository
// by replacing the last segment (typically "app") with "golang-adk".
// This respects any custom repository configuration.
pythonRepo := DefaultImageConfig.Repository
lastSlash := strings.LastIndex(pythonRepo, "/")
if lastSlash == -1 {
// No slash found, repository is just the image name
return "golang-adk"
}
baseRepo := pythonRepo[:lastSlash]
return baseRepo + "/golang-adk"
case v1alpha2.DeclarativeRuntime_Python:
// Use the configured Python repository as-is
return DefaultImageConfig.Repository
default:
// Default to Python (should never happen due to enum validation)
return DefaultImageConfig.Repository
if runtime == v1alpha2.DeclarativeRuntime_Go {
return DefaultGoImageConfig.Repository
}
return DefaultImageConfig.Repository
}

// validateExtraContainers checks that none of the extra containers use the
Expand All @@ -143,7 +125,7 @@ func resolvePythonRuntimeImage(registry string, full, pinDigest bool) (string, e
digest = PythonADKFullImageDigest
imageLabel = "app-full"
}
return resolveRuntimeImage(registry, repo, digest, imageLabel, full, pinDigest)
return resolveRuntimeImage(registry, repo, DefaultImageConfig.Tag, digest, imageLabel, full, pinDigest)
}

func resolveGoRuntimeImage(registry string, full, pinDigest bool) (string, error) {
Expand All @@ -154,7 +136,7 @@ func resolveGoRuntimeImage(registry string, full, pinDigest bool) (string, error
digest = GoADKFullImageDigest
imageLabel = "golang-adk-full"
}
return resolveRuntimeImage(registry, repo, digest, imageLabel, full, pinDigest)
return resolveRuntimeImage(registry, repo, DefaultGoImageConfig.Tag, digest, imageLabel, full, pinDigest)
}

// resolveRuntimeImage builds the image reference for a declarative agent runtime.
Expand All @@ -168,9 +150,8 @@ func resolveGoRuntimeImage(registry string, full, pinDigest bool) (string, error
// Sandbox agents require pinDigest: Substrate ActorTemplate validation rejects
// image refs without a digest, so those use the link-time (or flag-overridden)
// runtime image digests.
func resolveRuntimeImage(registry, repository, digest, imageLabel string, full, pinDigest bool) (string, error) {
func resolveRuntimeImage(registry, repository, tag, digest, imageLabel string, full, pinDigest bool) (string, error) {
if !pinDigest {
tag := DefaultImageConfig.Tag
if full {
tag += "-full"
}
Expand Down Expand Up @@ -210,8 +191,16 @@ func resolveInlineDeployment(agent v1alpha2.AgentObject, mdd *modelDeploymentDat
// Determine runtime (defaults to python when spec.declarative.runtime is unset).
runtime := v1alpha2.EffectiveDeclarativeRuntime(agent.GetAgentSpec())

// Get registry
registry := DefaultImageConfig.Registry
// Resolve base registry and pull policy; the Go runtime uses DefaultGoImageConfig.
baseRegistry := DefaultImageConfig.Registry
basePullPolicy := DefaultImageConfig.PullPolicy
if runtime == v1alpha2.DeclarativeRuntime_Go {
baseRegistry = DefaultGoImageConfig.Registry
basePullPolicy = DefaultGoImageConfig.PullPolicy
}

// Per-agent spec overrides take precedence over all defaults.
registry := baseRegistry
if spec.ImageRegistry != "" {
registry = spec.ImageRegistry
}
Expand All @@ -236,7 +225,7 @@ func resolveInlineDeployment(agent v1alpha2.AgentObject, mdd *modelDeploymentDat
}
}

imagePullPolicy := corev1.PullPolicy(DefaultImageConfig.PullPolicy)
imagePullPolicy := corev1.PullPolicy(basePullPolicy)
if spec.ImagePullPolicy != "" {
imagePullPolicy = corev1.PullPolicy(spec.ImagePullPolicy)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,13 @@ func TestResolvePythonRuntimeImageWithoutDigest(t *testing.T) {

func TestResolveRuntimeImageByTag(t *testing.T) {
originalTag := DefaultImageConfig.Tag
t.Cleanup(func() { DefaultImageConfig.Tag = originalTag })
originalGoTag := DefaultGoImageConfig.Tag
t.Cleanup(func() {
DefaultImageConfig.Tag = originalTag
DefaultGoImageConfig.Tag = originalGoTag
})
DefaultImageConfig.Tag = "v9.9.9"
DefaultGoImageConfig.Tag = "v8.8.8"

got, err := resolvePythonRuntimeImage("my-registry.example.com", false, false)
require.NoError(t, err)
Expand All @@ -144,11 +149,11 @@ func TestResolveRuntimeImageByTag(t *testing.T) {

got, err = resolveGoRuntimeImage("my-registry.example.com", false, false)
require.NoError(t, err)
require.Equal(t, "my-registry.example.com/kagent-dev/kagent/golang-adk:v9.9.9", got)
require.Equal(t, "my-registry.example.com/kagent-dev/kagent/golang-adk:v8.8.8", got)

got, err = resolveGoRuntimeImage("my-registry.example.com", true, false)
require.NoError(t, err)
require.Equal(t, "my-registry.example.com/kagent-dev/kagent/golang-adk:v9.9.9-full", got)
require.Equal(t, "my-registry.example.com/kagent-dev/kagent/golang-adk:v8.8.8-full", got)
}

func TestResolveRuntimeImageByTagIgnoresMissingDigest(t *testing.T) {
Expand Down
Loading
Loading