Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -160,52 +160,6 @@
- permissive
- strict
type: string
skills:
description: |-
Skills declares OCI skill images to mount into the agent pod as
Kubernetes ImageVolumes. Each skill is mounted read-only at
/agent/skills/<name>/. Requires the skillImageVolumes feature gate
and Kubernetes 1.31+ with the ImageVolume feature gate enabled.
items:
description: SkillImageRef identifies an OCI skill image to mount
into the agent pod.
properties:
image:
description: Image is the OCI image reference for the skill.
minLength: 1
type: string
mountPath:
description: |-
MountPath is the absolute path where the skill image is mounted in
the container. Different agent frameworks expect skills in different
locations (e.g. /agent/skills/my-skill, /app/.claude/skills/my-skill).
minLength: 1
pattern: ^/.*
type: string
name:
description: |-
Name is a unique identifier for this skill mount, used as the volume
name suffix (skill-<name>).
maxLength: 58
minLength: 1
pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$
type: string
pullPolicy:
description: |-
PullPolicy for pulling the OCI skill image. Defaults to Always for
:latest tags and IfNotPresent otherwise (standard Kubernetes behavior).
enum:
- Always
- Never
- IfNotPresent
type: string
required:
- image
- mountPath
- name
type: object
maxItems: 20
type: array
targetRef:
description: TargetRef identifies the workload backing this agent
runtime (duck typing).
Expand Down Expand Up @@ -471,7 +425,7 @@
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.

Check warning on line 428 in charts/kagenti-operator/crds/agent.kagenti.dev_agentruntimes.yaml

View workflow job for this annotation

GitHub Actions / YAML Lint

428:151 [line-length] line too long (162 > 150 characters)
format: date-time
type: string
message:
Expand All @@ -483,7 +437,7 @@
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date

Check warning on line 440 in charts/kagenti-operator/crds/agent.kagenti.dev_agentruntimes.yaml

View workflow job for this annotation

GitHub Actions / YAML Lint

440:151 [line-length] line too long (162 > 150 characters)
with respect to the current state of the instance.
format: int64
minimum: 0
Expand Down Expand Up @@ -523,6 +477,15 @@
description: ConfiguredPods is the count of pods with expected labels/config
format: int32
type: integer
linkedSkills:
description: |-
LinkedSkills lists skill names discovered from the kagenti.io/skills
annotation on the target workload. This annotation is set by the
kagenti backend (PR #1440) or manually by the user. The operator
reads but never sets this annotation.
items:
type: string
type: array
phase:
description: Phase is the high-level state of the AgentRuntime
enum:
Expand Down
8 changes: 4 additions & 4 deletions charts/kagenti-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@ featureGates:
# Default false — cached mode is faster and sufficient when namespace ConfigMaps
# rarely change. Cache is cleared on webhook pod restart.
perWorkloadConfigResolution: false
# skillImageVolumes controls whether AgentRuntime can mount OCI skill images
# as Kubernetes ImageVolumes into agent pods. Requires Kubernetes 1.31+ with
# the ImageVolume feature gate enabled. Default false.
skillImageVolumes: false
# skillDiscovery controls whether the AgentRuntime controller reads the
# kagenti.io/skills annotation from target workloads and populates
# status.linkedSkills. Default false.
skillDiscovery: false

# Platform defaults for AuthBridge sidecar injection.
# These are the lowest-priority layer — overridden by feature gates,
Expand Down
50 changes: 7 additions & 43 deletions kagenti-operator/api/v1alpha1/agentruntime_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,6 @@ type AgentRuntimeSpec struct {
// +optional
// +kubebuilder:validation:Enum=disabled;permissive;strict
MTLSMode string `json:"mtlsMode,omitempty"`

// Skills declares OCI skill images to mount into the agent pod as
// Kubernetes ImageVolumes. Each skill is mounted read-only at
// /agent/skills/<name>/. Requires the skillImageVolumes feature gate
// and Kubernetes 1.31+ with the ImageVolume feature gate enabled.
// +optional
// +kubebuilder:validation:MaxItems=20
Skills []SkillImageRef `json:"skills,omitempty"`
}

// IdentitySpec configures workload identity for an AgentRuntime.
Expand Down Expand Up @@ -194,41 +186,6 @@ type CardStatus struct {
AttestedAgentSpiffeID string `json:"attestedAgentSpiffeID,omitempty"`
}

// +kubebuilder:validation:Enum=Always;Never;IfNotPresent
type SkillPullPolicy string

const (
SkillPullAlways SkillPullPolicy = "Always"
SkillPullNever SkillPullPolicy = "Never"
SkillPullIfNotPresent SkillPullPolicy = "IfNotPresent"
)

// SkillImageRef identifies an OCI skill image to mount into the agent pod.
type SkillImageRef struct {
// Name is a unique identifier for this skill mount, used as the volume
// name suffix (skill-<name>).
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=58
// +kubebuilder:validation:Pattern=`^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$`
Name string `json:"name"`

// Image is the OCI image reference for the skill.
// +kubebuilder:validation:MinLength=1
Image string `json:"image"`

// MountPath is the absolute path where the skill image is mounted in
// the container. Different agent frameworks expect skills in different
// locations (e.g. /agent/skills/my-skill, /app/.claude/skills/my-skill).
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^/.*`
MountPath string `json:"mountPath"`

// PullPolicy for pulling the OCI skill image. Defaults to Always for
// :latest tags and IfNotPresent otherwise (standard Kubernetes behavior).
// +optional
PullPolicy SkillPullPolicy `json:"pullPolicy,omitempty"`
}

// AgentRuntimeStatus defines the observed state of AgentRuntime.
type AgentRuntimeStatus struct {
// Phase is the high-level state of the AgentRuntime
Expand All @@ -243,6 +200,13 @@ type AgentRuntimeStatus struct {
// +optional
Card *CardStatus `json:"card,omitempty"`

// LinkedSkills lists skill names discovered from the kagenti.io/skills
// annotation on the target workload. This annotation is set by the
// kagenti backend (PR #1440) or manually by the user. The operator
// reads but never sets this annotation.
// +optional
LinkedSkills []string `json:"linkedSkills,omitempty"`

// Conditions represent the current state of the AgentRuntime
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
Expand Down
25 changes: 5 additions & 20 deletions kagenti-operator/api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -160,52 +160,6 @@ spec:
- permissive
- strict
type: string
skills:
description: |-
Skills declares OCI skill images to mount into the agent pod as
Kubernetes ImageVolumes. Each skill is mounted read-only at
/agent/skills/<name>/. Requires the skillImageVolumes feature gate
and Kubernetes 1.31+ with the ImageVolume feature gate enabled.
items:
description: SkillImageRef identifies an OCI skill image to mount
into the agent pod.
properties:
image:
description: Image is the OCI image reference for the skill.
minLength: 1
type: string
mountPath:
description: |-
MountPath is the absolute path where the skill image is mounted in
the container. Different agent frameworks expect skills in different
locations (e.g. /agent/skills/my-skill, /app/.claude/skills/my-skill).
minLength: 1
pattern: ^/.*
type: string
name:
description: |-
Name is a unique identifier for this skill mount, used as the volume
name suffix (skill-<name>).
maxLength: 58
minLength: 1
pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$
type: string
pullPolicy:
description: |-
PullPolicy for pulling the OCI skill image. Defaults to Always for
:latest tags and IfNotPresent otherwise (standard Kubernetes behavior).
enum:
- Always
- Never
- IfNotPresent
type: string
required:
- image
- mountPath
- name
type: object
maxItems: 20
type: array
targetRef:
description: TargetRef identifies the workload backing this agent
runtime (duck typing).
Expand Down Expand Up @@ -523,6 +477,15 @@ spec:
description: ConfiguredPods is the count of pods with expected labels/config
format: int32
type: integer
linkedSkills:
description: |-
LinkedSkills lists skill names discovered from the kagenti.io/skills
annotation on the target workload. This annotation is set by the
kagenti backend (PR #1440) or manually by the user. The operator
reads but never sets this annotation.
items:
type: string
type: array
phase:
description: Phase is the high-level state of the AgentRuntime
enum:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Full AgentRuntime: enroll a Deployment as an agent with per-workload overrides.
# Overrides the SPIFFE trust domain, and mounts OCI skill images
# (requires skillImageVolumes feature gate + K8s 1.31+).
# Overrides the SPIFFE trust domain for this workload.
apiVersion: agent.kagenti.dev/v1alpha1
kind: AgentRuntime
metadata:
Expand All @@ -17,7 +16,3 @@ spec:
identity:
spiffe:
trustDomain: custom.example.com
skills:
- name: weather-forecast
image: ghcr.io/redhat-et/skillimage/weather-forecast:v1.0.0
mountPath: /agent/skills/weather-forecast
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# AgentRuntime with skill discovery: reads the kagenti.io/skills annotation
# from the target workload to discover linked skills.
# Requires: skillDiscovery feature gate enabled.
#
# Skills are declared on the Deployment, not the AgentRuntime.
# Two delivery mechanisms are supported:
#
# 1. OCI ImageVolumes (user-managed, GitOps-friendly, K8s 1.31+):
# volumes:
# - name: skill-openshift-review
# image:
# reference: quay.io/myorg/openshift-review:1.0.0
#
# 2. ConfigMap volumes (kagenti backend, PR #1440):
# volumes:
# - name: skill-0
# configMap:
# name: summarizer
#
# Both paths set SKILL_FOLDERS so the agent discovers skills at startup.
# The agent reports discovered skills in its A2A card.
# The operator reads the kagenti.io/skills annotation and populates
# status.linkedSkills.
---
# Example Deployment with OCI skill ImageVolume
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-agent
labels:
app.kubernetes.io/name: my-agent
kagenti.io/type: agent
protocol.kagenti.io/a2a: ""
annotations:
kagenti.io/skills: '["openshift-review"]'
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: my-agent
template:
metadata:
labels:
app.kubernetes.io/name: my-agent
kagenti.io/type: agent
spec:
containers:
- name: agent
image: ghcr.io/kagenti/agent-examples/a2a_currency_converter:v0.1.0-alpha.1
ports:
- containerPort: 8000
env:
- name: SKILL_FOLDERS
value: /app/skills/openshift-review
volumeMounts:
- name: skill-openshift-review
mountPath: /app/skills/openshift-review
readOnly: true
volumes:
- name: skill-openshift-review
image:
reference: quay.io/myorg/openshift-review:1.0.0
---
# AgentRuntime observes the Deployment — no spec.skills needed
apiVersion: agent.kagenti.dev/v1alpha1
kind: AgentRuntime
metadata:
name: my-agent
labels:
app.kubernetes.io/name: my-agent
spec:
type: agent
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-agent

This file was deleted.

Loading
Loading