Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 9 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ jobs:

- name: Run e2e tests
if: success()
working-directory: go
working-directory: go/core
run: |
# Get the Kind network gateway IP that pods can reach
HOST_IP=$(docker network inspect kind -f '{{range .IPAM.Config}}{{if .Gateway}}{{.Gateway}}{{"\n"}}{{end}}{{end}}' | grep -E '^[0-9]+\.' | head -1)
Expand All @@ -124,7 +124,7 @@ jobs:

# no need to run e2e tests with race, as this will just apply to the test code.
# all objects created in e2e tests have a generated name, so they can run in parallel safely.
go test -v github.com/kagent-dev/kagent/go/test/e2e -failfast -shuffle=on
go test -v github.com/kagent-dev/kagent/go/core/test/e2e -failfast -shuffle=on
- name: fail print info
if: failure()
run: |
Expand All @@ -148,12 +148,12 @@ jobs:
with:
go-version: "1.25"
cache: true
cache-dependency-path: go/go.sum
cache-dependency-path: go/*/go.sum

- name: Run cmd/main.go tests
- name: Run Go unit tests
working-directory: go
run: |
go test -race -skip 'TestE2E.*' -v ./...
go test -race -skip 'TestE2E.*' -v ./api/... ./adk/... ./core/...

helm-unit-tests:
env:
Expand Down Expand Up @@ -219,6 +219,7 @@ jobs:
- ui
- app
- cli
- golang-adk
- skills-init
runs-on: ubuntu-latest
services:
Expand Down Expand Up @@ -266,12 +267,12 @@ jobs:
with:
go-version: "1.25"
cache: true
cache-dependency-path: go/go.sum
cache-dependency-path: go/*/go.sum
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.8.0
working-directory: go
working-directory: go/core

python-test:
env:
Expand Down Expand Up @@ -341,7 +342,7 @@ jobs:
with:
go-version: "1.25"
cache: true
cache-dependency-path: go/go.sum
cache-dependency-path: go/*/go.sum

- name: Generate controller manifests
run: make controller-manifests
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/tag.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Tag and Push
name: Tag and Push

on:
push:
Expand All @@ -20,6 +20,7 @@ jobs:
- controller
- ui
- app
- golang-adk
- skills-init
runs-on: ubuntu-latest
permissions:
Expand Down Expand Up @@ -122,7 +123,7 @@ jobs:
uv version $VERSION --package agentsts-core
uv build --package agentsts-core
uv publish --token ${{ secrets.PYPI_TOKEN }}
release:
# Only run release after images and helm chart are pushed
# In the future we can take the chart from the helm action,
Expand Down Expand Up @@ -152,5 +153,5 @@ jobs:
with:
generate_release_notes: true
files: |
go/bin/kagent-*
go/core/bin/kagent-*
kagent-*.tgz
65 changes: 35 additions & 30 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,24 @@ This document provides essential guidance for AI agents (Claude Code and others)

```
kagent/
├── go/ # Kubernetes controller, CLI, API server
│ ├── api/ # CRD definitions (v1alpha1, v1alpha2)
│ ├── cmd/ # Binary entry points
│ ├── internal/ # Core implementation
│ │ ├── controller/ # K8s reconciliation logic
│ │ ├── httpserver/ # REST/gRPC API
│ │ ├── database/ # SQLite/Postgres persistence
│ │ ├── a2a/ # Agent-to-Agent communication
│ │ ├── mcp/ # MCP integration
│ │ └── adk/ # Go ADK types
│ ├── pkg/ # Public Go packages
│ └── test/e2e/ # End-to-end tests
├── go/ # Go workspace (go.work)
│ ├── api/ # Shared types module: CRDs, ADK types, DB models, HTTP client
│ │ ├── v1alpha1/ # Legacy CRD types
│ │ ├── v1alpha2/ # Current CRD types
│ │ ├── adk/ # ADK config/model types (shared with go/adk)
│ │ ├── database/ # GORM model structs & Client interface
│ │ ├── httpapi/ # HTTP API request/response types
│ │ ├── client/ # REST HTTP client SDK
│ │ └── utils/ # Shared utilities
│ ├── core/ # Infrastructure module: controllers, HTTP server, CLI
│ │ ├── cmd/ # Binary entry points
│ │ ├── cli/ # CLI application (kagent CLI)
│ │ ├── internal/ # Controllers, HTTP server, DB implementation
│ │ ├── pkg/ # Auth, env vars, translator plugins
│ │ └── test/e2e/ # End-to-end tests
│ ├── adk/ # Go Agent Development Kit module
│ │ ├── cmd/ # ADK binary entry point
│ │ └── pkg/ # Agent runtime, models, MCP, sessions
├── python/ # Agent runtime and ADK
│ ├── packages/ # UV workspace packages
Expand Down Expand Up @@ -93,7 +99,7 @@ kagent/
- [Makefile](Makefile) - Root build orchestration
- [DEVELOPMENT.md](DEVELOPMENT.md) - Development setup guide
- [go/api/v1alpha2/agent_types.go](go/api/v1alpha2/agent_types.go) - Agent CRD definition
- [go/internal/controller/reconciler/reconciler.go](go/internal/controller/reconciler/reconciler.go) - Shared reconciler pattern
- [go/core/internal/controller/reconciler/reconciler.go](go/core/internal/controller/reconciler/reconciler.go) - Shared reconciler pattern
- [python/packages/kagent-adk/](python/packages/kagent-adk/) - Python ADK implementation
- [helm/kagent/values.yaml](helm/kagent/values.yaml) - Default configuration

Expand Down Expand Up @@ -164,11 +170,10 @@ make -C go generate

### Go Guidelines

**Code Organization:**
- `internal/` - Private implementation details
- `pkg/` - Public libraries (use sparingly)
- `api/` - CRD type definitions only
- `cmd/` - Binary entry points (thin, delegate to internal/)
**Code Organization (Go workspace with 3 modules):**
- `go/api/` - Shared types: CRD definitions, ADK types, database models, HTTP client SDK
- `go/core/` - Infrastructure: controllers, HTTP server, CLI, database implementation
- `go/adk/` - Go Agent Development Kit for building agents

**Error Handling:**
- Always wrap errors with context: `fmt.Errorf("context: %w", err)`
Expand Down Expand Up @@ -260,7 +265,7 @@ func TestSomething(t *testing.T) {
**Mock LLMs:**
Use `github.com/kagent-dev/mockllm` for testing LLM interactions.

**E2E tests location:** [go/test/e2e/](go/test/e2e/)
**E2E tests location:** [go/core/test/e2e/](go/core/test/e2e/)

### Python Testing

Expand All @@ -280,7 +285,7 @@ make -C python test
make -C ui test

# E2E tests (requires Kind cluster)
make -C go test-e2e
make -C go e2e

# With race detection (Go)
go test -race ./...
Expand Down Expand Up @@ -355,7 +360,7 @@ MCPServerController
- No application-level locking needed
- Controllers translate CRs to K8s manifests via translators

**Implementation reference:** [go/internal/controller/reconciler/reconciler.go](go/internal/controller/reconciler/reconciler.go)
**Implementation reference:** [go/core/internal/controller/reconciler/reconciler.go](go/core/internal/controller/reconciler/reconciler.go)

**When NOT to use:**
- Simple controllers without database persistence
Expand Down Expand Up @@ -398,7 +403,7 @@ func (r *AgentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl

**Schema evolution:** GORM AutoMigrate is sufficient during alpha stage.

**Models location:** [go/internal/database/models.go](go/internal/database/models.go)
**Models location:** [go/api/database/models.go](go/api/database/models.go)

**Common operations:**
```go
Expand Down Expand Up @@ -461,7 +466,7 @@ return ctrl.Result{}, nil
- KMCP repository for K8s-native tools (Prometheus, Helm, etc.)
- Each MCP server is independently deployable

**MCP protocol implementation:** MCP-related HTTP handlers live under [go/internal/httpserver/handlers/](go/internal/httpserver/handlers/).
**MCP protocol implementation:** MCP-related HTTP handlers live under [go/core/internal/httpserver/handlers/](go/core/internal/httpserver/handlers/).

**Tool discovery:**
- Tools are fetched from MCP servers at runtime
Expand Down Expand Up @@ -510,25 +515,25 @@ chore: update trivy action and exit on failures
1. Edit type definition in `go/api/v1alpha2/*_types.go`
2. Add validation markers and JSON tags
3. Run `make -C go generate` to update generated code
4. Update translator in `go/internal/controller/translator/` if needed
5. Add E2E test in `go/test/e2e/`
4. Update translator in `go/core/internal/controller/translator/` if needed
5. Add E2E test in `go/core/test/e2e/`
6. Update Helm chart values/templates if exposed to users

### Creating a New Controller

1. Create controller file in `go/internal/controller/`
1. Create controller file in `go/core/internal/controller/`
2. Implement `Reconcile()` method
3. Decide: use shared reconciler or custom logic
4. Add predicates for event filtering if needed
5. Register in `cmd/controller/main.go`
5. Register in `go/core/cmd/controller/main.go`
6. Add RBAC markers
7. Run `make -C go generate` to update RBAC manifests
8. Add unit and E2E tests

### Adding a New API Endpoint

1. Add handler in `go/internal/httpserver/handlers/`
2. Register route in `go/internal/httpserver/server.go`
1. Add handler in `go/core/internal/httpserver/handlers/`
2. Register route in `go/core/internal/httpserver/server.go`
3. Add auth middleware if needed
4. Update database models if storing data
5. Add unit tests for handler logic
Expand Down Expand Up @@ -637,7 +642,7 @@ make create-kind-cluster
| Build all | `make build` |
| Run all tests | `make test` |
| Run E2E tests | `make -C go e2e` |
| Lint code | `make lint` |
| Lint code | `make -C go lint` |
| Generate CRD code | `make -C go generate` |
| Run controller locally | `make -C go run` |
| Access UI | `kubectl port-forward -n kagent svc/kagent-ui 3000:80` |
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ npm run test
#### End-to-End (E2E) Tests

These tests are done in a `kind` cluster with real agents, using real or mock LLM providers.
See: [go/test/e2e](https://github.com/kagent-dev/kagent/tree/main/go/test/e2e)
See: [go/core/test/e2e](https://github.com/kagent-dev/kagent/tree/main/go/core/test/e2e)

Features that introduce behavior changes should be covered by E2E tests (exceptions can be made for minor changes). Testing with real Kubernetes resources and agent invocations is crucial because it:

Expand Down
42 changes: 27 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,29 +35,32 @@ CONTROLLER_IMAGE_NAME ?= controller
UI_IMAGE_NAME ?= ui
APP_IMAGE_NAME ?= app
KAGENT_ADK_IMAGE_NAME ?= kagent-adk
GOLANG_ADK_IMAGE_NAME ?= golang-adk
SKILLS_INIT_IMAGE_NAME ?= skills-init

CONTROLLER_IMAGE_TAG ?= $(VERSION)
UI_IMAGE_TAG ?= $(VERSION)
APP_IMAGE_TAG ?= $(VERSION)
KAGENT_ADK_IMAGE_TAG ?= $(VERSION)
GOLANG_ADK_IMAGE_TAG ?= $(VERSION)
SKILLS_INIT_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)
APP_IMG ?= $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(APP_IMAGE_NAME):$(APP_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)
SKILLS_INIT_IMG ?= $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(SKILLS_INIT_IMAGE_NAME):$(SKILLS_INIT_IMAGE_TAG)

#take from go/go.mod
#take from go/core/go.mod
AWK ?= $(shell command -v gawk || command -v awk)
TOOLS_GO_VERSION ?= $(shell $(AWK) '/^go / { print $$2 }' go/go.mod)
TOOLS_GO_VERSION ?= $(shell $(AWK) '/^go / { print $$2 }' go/core/go.mod)
export GOTOOLCHAIN=go$(TOOLS_GO_VERSION)

# Version information for the build
LDFLAGS := "-X github.com/$(DOCKER_REPO)/go/internal/version.Version=$(VERSION) \
-X github.com/$(DOCKER_REPO)/go/internal/version.GitCommit=$(GIT_COMMIT) \
-X github.com/$(DOCKER_REPO)/go/internal/version.BuildDate=$(BUILD_DATE)"
LDFLAGS := "-X github.com/$(DOCKER_REPO)/go/core/internal/version.Version=$(VERSION) \
-X github.com/$(DOCKER_REPO)/go/core/internal/version.GitCommit=$(GIT_COMMIT) \
-X github.com/$(DOCKER_REPO)/go/core/internal/version.BuildDate=$(BUILD_DATE)"

#tools versions
TOOLS_UV_VERSION ?= 0.10.4
Expand Down Expand Up @@ -104,7 +107,7 @@ init-git-hooks: ## Use the tracked version of Git hooks from this repo

# KMCP
KMCP_ENABLED ?= true
KMCP_VERSION ?= $(shell $(AWK) '/github\.com\/kagent-dev\/kmcp/ { print substr($$2, 2) }' go/go.mod) # KMCP version defaults to what's referenced in go.mod
KMCP_VERSION ?= $(shell $(AWK) '/github\.com\/kagent-dev\/kmcp/ { print substr($$2, 2) }' go/core/go.mod) # KMCP version defaults to what's referenced in go.mod

HELM_ACTION=upgrade --install

Expand Down Expand Up @@ -168,15 +171,15 @@ build-all: buildx-create
.PHONY: push-test-agent
push-test-agent: buildx-create build-kagent-adk
echo "Building FROM DOCKER_REGISTRY=$(DOCKER_REGISTRY)/$(DOCKER_REPO)/kagent-adk:$(VERSION)"
$(DOCKER_BUILDER) build --push $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -t $(DOCKER_REGISTRY)/kebab:latest -f go/test/e2e/agents/kebab/Dockerfile ./go/test/e2e/agents/kebab
kubectl apply --namespace kagent --context kind-$(KIND_CLUSTER_NAME) -f go/test/e2e/agents/kebab/agent.yaml
$(DOCKER_BUILDER) build --push $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -t $(DOCKER_REGISTRY)/kebab:latest -f go/core/test/e2e/agents/kebab/Dockerfile ./go/core/test/e2e/agents/kebab
kubectl apply --namespace kagent --context kind-$(KIND_CLUSTER_NAME) -f go/core/test/e2e/agents/kebab/agent.yaml
$(DOCKER_BUILDER) build --push $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -t $(DOCKER_REGISTRY)/poem-flow:latest -f python/samples/crewai/poem_flow/Dockerfile ./python
$(DOCKER_BUILDER) build --push $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -t $(DOCKER_REGISTRY)/basic-openai:latest -f python/samples/openai/basic_agent/Dockerfile ./python

.PHONY: push-test-skill
push-test-skill: buildx-create
echo "Building FROM DOCKER_REGISTRY=$(DOCKER_REGISTRY)/$(DOCKER_REPO)/kebab-maker:$(VERSION)"
$(DOCKER_BUILDER) build --push $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -t $(DOCKER_REGISTRY)/kebab-maker:latest -f go/test/e2e/testdata/skills/kebab-maker/Dockerfile ./go/test/e2e/testdata/skills/kebab-maker
$(DOCKER_BUILDER) build --push $(BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -t $(DOCKER_REGISTRY)/kebab-maker:latest -f go/core/test/e2e/testdata/skills/kebab-maker/Dockerfile ./go/core/test/e2e/testdata/skills/kebab-maker

.PHONY: create-kind-cluster
create-kind-cluster:
Expand All @@ -198,7 +201,7 @@ delete-kind-cluster:
clean: prune-kind-cluster
clean: prune-docker-images
docker buildx rm $(BUILDX_BUILDER_NAME) -f || true
rm -rf ./go/bin
rm -rf ./go/core/bin

.PHONY: prune-kind-cluster
prune-kind-cluster:
Expand All @@ -214,12 +217,13 @@ prune-docker-images:
docker images --filter dangling=true -q | xargs -r docker rmi || :

.PHONY: build
build: buildx-create build-controller build-ui build-app build-skills-init
build: buildx-create build-controller build-ui build-app build-golang-adk build-skills-init
@echo "Build completed successfully."
@echo "Controller Image: $(CONTROLLER_IMG)"
@echo "UI Image: $(UI_IMG)"
@echo "App Image: $(APP_IMG)"
@echo "Kagent ADK Image: $(KAGENT_ADK_IMG)"
@echo "Golang ADK Image: $(GOLANG_ADK_IMG)"
@echo "Skills Init Image: $(SKILLS_INIT_IMG)"

.PHONY: build-monitor
Expand All @@ -233,7 +237,7 @@ build-cli:
.PHONY: build-cli-local
build-cli-local:
make -C go clean
make -C go bin/kagent-local
make -C go core/bin/kagent-local

.PHONY: build-img-versions
build-img-versions:
Expand All @@ -248,14 +252,18 @@ lint:
make -C go lint
make -C python lint

.PHONY: push
push: push-controller push-ui push-app push-kagent-adk push-golang-adk


.PHONY: controller-manifests
controller-manifests:
make -C go manifests
cp go/config/crd/bases/* helm/kagent-crds/templates/
cp go/api/config/crd/bases/* helm/kagent-crds/templates/

.PHONY: build-controller
build-controller: buildx-create controller-manifests
$(DOCKER_BUILDER) build $(DOCKER_BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) -t $(CONTROLLER_IMG) -f go/Dockerfile ./go
$(DOCKER_BUILDER) build $(DOCKER_BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) --build-arg BUILD_PACKAGE=core/cmd/controller/main.go -t $(CONTROLLER_IMG) -f go/Dockerfile ./go

.PHONY: build-ui
build-ui: buildx-create
Expand All @@ -269,6 +277,10 @@ build-kagent-adk: buildx-create
build-app: buildx-create build-kagent-adk
$(DOCKER_BUILDER) build $(DOCKER_BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) --build-arg KAGENT_ADK_VERSION=$(KAGENT_ADK_IMAGE_TAG) --build-arg DOCKER_REGISTRY=$(DOCKER_REGISTRY) -t $(APP_IMG) -f python/Dockerfile.app ./python

.PHONY: build-golang-adk
build-golang-adk: buildx-create
$(DOCKER_BUILDER) build $(DOCKER_BUILD_ARGS) $(TOOLS_IMAGE_BUILD_ARGS) --build-arg BUILD_PACKAGE=adk/cmd/main.go -t $(GOLANG_ADK_IMG) -f go/Dockerfile ./go

.PHONY: build-skills-init
build-skills-init: buildx-create
$(DOCKER_BUILDER) build $(DOCKER_BUILD_ARGS) -t $(SKILLS_INIT_IMG) -f docker/skills-init/Dockerfile docker/skills-init
Expand Down Expand Up @@ -393,7 +405,7 @@ helm-publish: helm-version

.PHONY: kagent-cli-install
kagent-cli-install: use-kind-cluster build-cli-local helm-version helm-install-provider
KAGENT_HELM_REPO=./helm/ ./go/bin/kagent-local dashboard
KAGENT_HELM_REPO=./helm/ ./go/core/bin/kagent-local dashboard

.PHONY: kagent-cli-port-forward
kagent-cli-port-forward: use-kind-cluster
Expand Down
Loading
Loading