Skip to content
Open
Show file tree
Hide file tree
Changes from 10 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
6 changes: 5 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ jobs:
--push
run: |
echo "Cache key: ${{ needs.setup.outputs.cache-key }}"
make build-controller build-golang-adk
make build-controller build-golang-adk build-claude-harness
make helm-install-provider
kubectl rollout status deployment/kagent-controller -n kagent --timeout=120s
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/component=controller -n kagent --timeout=120s
Expand All @@ -132,6 +132,9 @@ jobs:
RUNTIME_DIGEST=$(docker buildx imagetools inspect "localhost:5001/kagent-dev/kagent/golang-adk:${VERSION}" | awk '$1 == "Digest:" { print $2; exit }')
test -n "$RUNTIME_DIGEST"
export KAGENT_E2E_RUNTIME_IMAGE="localhost:5001/kagent-dev/kagent/golang-adk@${RUNTIME_DIGEST}"
CLAUDE_DIGEST=$(docker buildx imagetools inspect "localhost:5001/kagent-dev/kagent/claude-harness:${VERSION}" | awk '$1 == "Digest:" { print $2; exit }')
test -n "$CLAUDE_DIGEST"
export KAGENT_E2E_CLAUDE_IMAGE="localhost:5001/kagent-dev/kagent/claude-harness@${CLAUDE_DIGEST}"
envsubst < core/test/e2e/manifests/lifecycle.yaml.tmpl | kubectl apply -f -
for _ in $(seq 1 60); do
READY=$(kubectl get agenttemplate smoke -n kagent -o jsonpath='{.status.harnesses[?(@.harness=="kagent")].conditions[?(@.type=="Ready")].status}')
Expand Down Expand Up @@ -411,6 +414,7 @@ jobs:
- kagent-adk
- cli
- golang-adk
- claude-harness
runs-on: ubuntu-latest
services:
registry:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/image-scan.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ jobs:
- build_target: golang-adk
image_name: golang-adk
tag_suffix: ""
- build_target: claude-harness
image_name: claude-harness
tag_suffix: ""
runs-on: ubuntu-latest
services:
registry:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tag.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
- ui
- kagent-adk
- golang-adk
- claude-harness
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down
14 changes: 13 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,17 @@ UI_IMAGE_NAME ?= ui
KAGENT_ADK_IMAGE_NAME ?= kagent-adk
GOLANG_ADK_IMAGE_NAME ?= golang-adk

CLAUDE_HARNESS_IMAGE_NAME ?= claude-harness
CONTROLLER_IMAGE_TAG ?= $(VERSION)
UI_IMAGE_TAG ?= $(VERSION)
KAGENT_ADK_IMAGE_TAG ?= $(VERSION)
GOLANG_ADK_IMAGE_TAG ?= $(VERSION)
CLAUDE_HARNESS_IMAGE_TAG ?= $(VERSION)
CONTROLLER_IMG ?= $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(CONTROLLER_IMAGE_NAME):$(CONTROLLER_IMAGE_TAG)
UI_IMG ?= $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(UI_IMAGE_NAME):$(UI_IMAGE_TAG)
KAGENT_ADK_IMG ?= $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(KAGENT_ADK_IMAGE_NAME):$(KAGENT_ADK_IMAGE_TAG)
GOLANG_ADK_IMG ?= $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(GOLANG_ADK_IMAGE_NAME):$(GOLANG_ADK_IMAGE_TAG)
CLAUDE_HARNESS_IMG ?= $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(CLAUDE_HARNESS_IMAGE_NAME):$(CLAUDE_HARNESS_IMAGE_TAG)

#take from go/go.mod
AWK ?= $(shell command -v gawk || command -v awk)
Expand Down Expand Up @@ -219,17 +222,19 @@ build-all: ## Build all images for amd64+arm64 without pushing (outputs to /dev/
build-all: BUILD_ARGS ?= --progress=plain --builder $(BUILDX_BUILDER_NAME) --platform linux/amd64,linux/arm64 --output type=tar,dest=/dev/null
build-all: proto-generate buildx-create
$(DOCKER_BUILDER) $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -f go/Dockerfile ./go
$(DOCKER_BUILDER) $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -f go/harness/claude/Dockerfile ./go
$(DOCKER_BUILDER) $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -f ui/Dockerfile ./ui
$(DOCKER_BUILDER) $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -f python/Dockerfile ./python

.PHONY: build
build: ## Build and push all component images
build: buildx-create build-ui build-kagent-adk build-golang-adk build-controller
build: buildx-create build-ui build-kagent-adk build-golang-adk build-claude-harness build-controller
@echo "Build completed successfully."
@echo "Controller Image: $(CONTROLLER_IMG)"
@echo "UI Image: $(UI_IMG)"
@echo "Kagent ADK Image: $(KAGENT_ADK_IMG)"
@echo "Golang ADK Image: $(GOLANG_ADK_IMG)"
@echo "Claude Harness Image: $(CLAUDE_HARNESS_IMG)"

.PHONY: build-monitor
build-monitor: ## Watch BuildKit process list inside the buildx container
Expand Down Expand Up @@ -257,6 +262,7 @@ build-img-versions: ## Print the fully-qualified image tags for all components
@echo ui=$(UI_IMG)
@echo kagent-adk=$(KAGENT_ADK_IMG)
@echo golang-adk=$(GOLANG_ADK_IMG)
@echo claude-harness=$(CLAUDE_HARNESS_IMG)

.PHONY: controller-manifests
controller-manifests: ## Regenerate CRD manifests and copy them into the Helm chart
Expand Down Expand Up @@ -289,6 +295,12 @@ build-golang-adk: proto-generate buildx-create
$(DOCKER_BUILDER) $(DOCKER_BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) --build-arg BUILD_PACKAGE=adk/cmd/main.go -t $(GOLANG_ADK_IMG) -f go/Dockerfile ./go
$(DOCKER_PUSH) $(GOLANG_ADK_IMG)

.PHONY: build-claude-harness
build-claude-harness: ## Build and push the native Claude Harness image
build-claude-harness: buildx-create
$(DOCKER_BUILDER) $(DOCKER_BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -t $(CLAUDE_HARNESS_IMG) -f go/harness/claude/Dockerfile ./go
$(DOCKER_PUSH) $(CLAUDE_HARNESS_IMG)

.PHONY: push
push: ## Push all component images (controller, ui, ADKs)
push: push-controller push-ui push-kagent-adk push-golang-adk
Expand Down
1 change: 1 addition & 0 deletions go/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ RUN --mount=type=cache,target=/root/go/pkg/mod,rw \
COPY api/ api/
COPY core/ core/
COPY adk/ adk/
COPY harness/ harness/

# Build
ARG LDFLAGS
Expand Down
5 changes: 4 additions & 1 deletion go/adk/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ func main() {
}
if err := agentplugins.MaterializeAgentConfig(
logr.NewContext(context.Background(), logger), agentConfig,
agentplugins.Paths{Plugins: agentplugins.DefaultPluginRoot, Skills: agentplugins.DefaultSkillsRoot, Data: agentplugins.DefaultDataRoot},
agentplugins.ADKPaths{
SkillPaths: agentplugins.SkillPaths{Plugins: agentplugins.DefaultPluginRoot, Skills: agentplugins.DefaultSkillsRoot},
Data: agentplugins.DefaultDataRoot,
},
); err != nil {
logger.Error(err, "Failed to materialize Agent Plugins")
os.Exit(1)
Expand Down
45 changes: 4 additions & 41 deletions go/api/adk/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"database/sql/driver"
"encoding/json"
"fmt"

"github.com/kagent-dev/kagent/go/api/agentplugin"
)

type StreamableHTTPConnectionParams struct {
Expand Down Expand Up @@ -548,45 +550,6 @@ type NetworkConfig struct {
AllowedDomains []string `json:"allowed_domains,omitempty"`
}

// AgentPluginConfig describes immutable Agent Plugin and standalone skill
// packages that the runtime must download before starting the agent.
type AgentPluginConfig struct {
Skills []StandaloneSkill `json:"skills,omitempty"`
Plugins []AgentPluginBundle `json:"plugins,omitempty"`
}

// StandaloneSkill identifies one independently sourced skill, rather than a
// skill selected from an Agent Plugin bundle.
type StandaloneSkill struct {
Name string `json:"name"`
Source AgentPluginSource `json:"source"`
}

type AgentPluginBundle struct {
Source AgentPluginSource `json:"source"`
Skills []string `json:"skills,omitempty"`
}

type AgentPluginSource struct {
OCI string `json:"oci,omitempty"`
Git *AgentPluginGit `json:"git,omitempty"`
S3 *AgentPluginS3 `json:"s3,omitempty"`
Path string `json:"path,omitempty"`
}

type AgentPluginGit struct {
URL string `json:"url"`
Commit string `json:"commit"`
}

type AgentPluginS3 struct {
Endpoint string `json:"endpoint"`
Bucket string `json:"bucket"`
Key string `json:"key"`
VersionID string `json:"versionId"`
Region string `json:"region,omitempty"`
}

// AgentContextConfig is the context management configuration that flows through config.json to the Python runtime.
type AgentContextConfig struct {
Compaction *AgentCompressionConfig `json:"compaction,omitempty"`
Expand Down Expand Up @@ -642,7 +605,7 @@ type AgentConfig struct {
Stream *bool `json:"stream,omitempty"`
Memory *MemoryConfig `json:"memory,omitempty"`
Network *NetworkConfig `json:"network,omitempty"`
AgentPlugins *AgentPluginConfig `json:"agent_plugins,omitempty"`
AgentPlugins *agentplugin.Resources `json:"agent_plugins,omitempty"`
ContextConfig *AgentContextConfig `json:"context_config,omitempty"`
ShareTools *bool `json:"share_tools,omitempty"`
SessionDBURL string `json:"session_db_url,omitempty"`
Expand Down Expand Up @@ -671,7 +634,7 @@ func (a *AgentConfig) UnmarshalJSON(data []byte) error {
Stream *bool `json:"stream,omitempty"`
Memory json.RawMessage `json:"memory"`
Network *NetworkConfig `json:"network,omitempty"`
AgentPlugins *AgentPluginConfig `json:"agent_plugins,omitempty"`
AgentPlugins *agentplugin.Resources `json:"agent_plugins,omitempty"`
ContextConfig *AgentContextConfig `json:"context_config,omitempty"`
ShareTools *bool `json:"share_tools,omitempty"`
SessionDBURL string `json:"session_db_url,omitempty"`
Expand Down
6 changes: 4 additions & 2 deletions go/api/adk/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import (
"encoding/json"
"reflect"
"testing"

"github.com/kagent-dev/kagent/go/api/agentplugin"
)

func TestAgentConfigStdioToolsRoundTrip(t *testing.T) {
want := []StdioMcpServerConfig{{Command: "server", Args: []string{"--stdio"}, Env: map[string]string{"KEY": "value"}, Dir: "/plugin"}}
wantPlugins := &AgentPluginConfig{Skills: []StandaloneSkill{{
wantPlugins := &agentplugin.Resources{Skills: []agentplugin.Skill{{
Name: "review",
Source: AgentPluginSource{Git: &AgentPluginGit{
Source: agentplugin.Source{Git: &agentplugin.GitSource{
URL: "https://example.com/plugin.git", Commit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
}},
}}}
Expand Down
45 changes: 45 additions & 0 deletions go/api/agentplugin/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Package agentplugin defines the runtime-neutral configuration for immutable
// standalone skills and Agent Plugin packages.
package agentplugin

// Resources describes the skill resources a Harness must materialize before
// starting an agent.
type Resources struct {
Skills []Skill `json:"skills,omitempty"`
Plugins []Bundle `json:"plugins,omitempty"`
}

// Skill identifies one independently sourced skill.
type Skill struct {
Name string `json:"name"`
Source Source `json:"source"`
}

// Bundle selects named skills from one immutable Agent Plugin package.
type Bundle struct {
Source Source `json:"source"`
Skills []string `json:"skills,omitempty"`
}

// Source selects one immutable artifact and an optional directory within it.
type Source struct {
OCI string `json:"oci,omitempty"`
Git *GitSource `json:"git,omitempty"`
S3 *S3Source `json:"s3,omitempty"`
Path string `json:"path,omitempty"`
}

// GitSource identifies one immutable Git commit.
type GitSource struct {
URL string `json:"url"`
Commit string `json:"commit"`
}

// S3Source identifies one immutable S3 object version.
type S3Source struct {
Endpoint string `json:"endpoint"`
Bucket string `json:"bucket"`
Key string `json:"key"`
VersionID string `json:"versionId"`
Region string `json:"region,omitempty"`
}
8 changes: 5 additions & 3 deletions go/api/config/crd/bases/kagent.dev_agenttemplates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ spec:
- templateRef
type: object
mcp:
description: MCPToolBinding selects tools from a same-namespace
description: MCPToolBinding binds tools from a same-namespace
MCP server.
properties:
server:
Expand All @@ -337,16 +337,18 @@ spec:
- name
type: object
tools:
description: |-
Tools optionally limits which server tools are exposed. An omitted or empty
list exposes every tool. Harnesses that cannot enforce a partial selection
may expose the whole server and report a warning.
items:
minLength: 1
type: string
maxItems: 50
minItems: 1
type: array
x-kubernetes-list-type: set
required:
- server
- tools
type: object
type: object
x-kubernetes-validations:
Expand Down
10 changes: 6 additions & 4 deletions go/api/v1alpha3/agenttemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,18 @@ type AgentTemplatePromptSource struct {
Alias string `json:"alias,omitempty"`
}

// MCPToolBinding selects tools from a same-namespace MCP server.
// MCPToolBinding binds tools from a same-namespace MCP server.
type MCPToolBinding struct {
// +required
Server AgentTemplateTypedLocalReference `json:"server"`
// +kubebuilder:validation:MinItems=1
// Tools optionally limits which server tools are exposed. An omitted or empty
// list exposes every tool. Harnesses that cannot enforce a partial selection
// may expose the whole server and report a warning.
// +kubebuilder:validation:MaxItems=50
// +kubebuilder:validation:items:MinLength=1
// +listType=set
// +required
Tools []string `json:"tools"`
// +optional
Tools []string `json:"tools,omitempty"`
}

// AgentToolIsolation controls whether a referenced template shares its parent's runtime boundary.
Expand Down
Loading
Loading