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
200 changes: 143 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,97 @@
[![License](https://img.shields.io/github/license/kagenti/kagenti-operator)](LICENSE)
![Contributors](https://img.shields.io/github/contributors/kagenti/kagenti-operator)

**Kagenti Operator** is a Kubernetes operator that automates the deployment, discovery, and security of AI agents in Kubernetes clusters.
**Kagenti Operator** is a Kubernetes operator that automates the deployment, discovery, and security of AI agents in Kubernetes clusters. It provides workload identity (SPIFFE), mutual authentication (OAuth2/Keycloak), agent-to-agent trust (A2A signature verification), and observability (MLflow tracing) — all declaratively managed through Custom Resources.

## Overview

The Kagenti Operator manages the following Custom Resource Definitions (CRDs):

| Resource | Purpose |
|----------|---------|
| **[AgentRuntime](./kagenti-operator/docs/api-reference.md#agentruntime)** | Enrolls a workload into the Kagenti platform — applies labels, triggers sidecar injection, and configures identity and observability |
| **[AgentCard](./kagenti-operator/docs/api-reference.md#agentcard)** | Discovers, indexes, and verifies agent metadata for Kubernetes-native agent discovery |

Agents are deployed as standard Kubernetes **Deployments** or **StatefulSets** with the `kagenti.io/type: agent` label. The operator automatically discovers labeled workloads and creates AgentCard resources for them.

### Key Features

- **Agent Deployment** — Deploy agents using standard Kubernetes Deployments or StatefulSets with the `kagenti.io/type: agent` label
- **Dynamic Agent Discovery** — Automatic indexing of agent metadata via the A2A protocol
- **Signature Verification** — JWS-based cryptographic verification of agent cards (RSA, ECDSA)
- **Identity Binding** — SPIFFE-based workload identity binding with allowlist enforcement
- **Declarative Agent Enrollment** — Create an `AgentRuntime` CR pointing to a clean Deployment; the operator applies labels, injects sidecars, and manages rolling updates automatically

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

suggestion: "pointing to a clean Deployment" — the Deployment isn't fully clean since it carries the protocol.kagenti.io/a2a label. Consider "pointing to your Deployment" for consistency with the updated GETTING_STARTED.md heading ("Deploy a Deployment with Protocol Label").

- **AuthBridge Sidecar Injection** — Mutating webhook injects envoy-proxy (mTLS + token exchange), SPIFFE helper (workload identity), and client registration (Keycloak OAuth2) sidecars
- **Dynamic Agent Discovery** — Automatic indexing of agent metadata via the [A2A protocol](https://a2a-protocol.org/)
- **Signature Verification** — JWS-based cryptographic verification of agent cards (RSA, ECDSA) using SPIRE X.509 trust bundles
- **Identity Binding** — SPIFFE-based workload identity binding with trust domain validation
- **Network Policy Enforcement** — Automatic NetworkPolicy creation based on signature verification status
- **Flexible Configuration** — Complete control over pod specifications, service ports, and environment variables
- **MLflow Integration** — Auto-discovers MLflow instances, creates per-agent experiments, and configures tracing
- **Multi-Framework Support** — Works with LangGraph, CrewAI, AG2, and any A2A-compatible framework

## Architecture

```mermaid
graph TD;
subgraph Kubernetes
direction TB
style Kubernetes fill:#f0f4ff,stroke:#8faad7,stroke-width:2px

User[User/App]
style User fill:#ffecb3,stroke:#ffa000

Workload["Deployment / StatefulSet\n(with kagenti labels)"]
style Workload fill:#e1f5fe,stroke:#039be5

User -->|Creates| Workload

AgentCardSync[AgentCard Sync Controller]
style AgentCardSync fill:#ffe0b2,stroke:#fb8c00

AgentCardController[AgentCard Controller]
style AgentCardController fill:#ffe0b2,stroke:#fb8c00

NetworkPolicyController[NetworkPolicy Controller]
style NetworkPolicyController fill:#ffe0b2,stroke:#fb8c00
graph TB
subgraph "User Interaction"
User[User/Developer]
User -->|Creates| Deployment[Deployment/StatefulSet]
User -->|Creates| RuntimeCR[AgentRuntime CR]
end

AgentPod[Agent Pod]
style AgentPod fill:#c8e6c9,stroke:#66bb6a
subgraph "Kagenti Operator"
ValidationWebhook[Validating Webhooks]
InjectionWebhook[AuthBridge Mutating Webhook]
RuntimeController[AgentRuntime Controller]
SyncController[AgentCard Sync Controller]
CardController[AgentCard Controller]
NPController[NetworkPolicy Controller]
MLflowController[MLflow Controller]

AgentCardCRD["AgentCard CR"]
style AgentCardCRD fill:#e1f5fe,stroke:#039be5
RuntimeCR -->|Validates| ValidationWebhook
end

NetworkPolicy["NetworkPolicy"]
style NetworkPolicy fill:#ffcdd2,stroke:#e57373
subgraph "Config Sources"
ClusterCM[Cluster Defaults ConfigMaps]
NsCM[Namespace Defaults ConfigMap]
end

Workload -->|Deploys| AgentPod
Workload -->|Watches| AgentCardSync
AgentCardSync -->|Auto-creates| AgentCardCRD
AgentCardCRD -->|Reconciles| AgentCardController
AgentCardController -->|Fetches /.well-known/agent-card.json| AgentPod
AgentCardController -->|Verifies signatures & identity| AgentCardCRD
AgentCardCRD -->|Reconciles| NetworkPolicyController
NetworkPolicyController -->|Creates| NetworkPolicy
subgraph "Runtime"
Pod[Agent Pods]
Deployment -->|Creates| Pod
InjectionWebhook -->|Injects sidecars at CREATE| Pod
CardController -->|Fetches agent card from| Pod
end

RuntimeController -->|Applies labels + config-hash| Deployment
RuntimeController -->|Reads defaults| ClusterCM
RuntimeController -->|Reads defaults| NsCM
RuntimeController -->|Watches| RuntimeCR

SyncController -->|Watches| Deployment
SyncController -->|Auto-creates| AgentCardCR[AgentCard CR]
CardController -->|Reconciles| AgentCardCR
NPController -->|Creates| NetworkPolicy[NetworkPolicy]
MLflowController -->|Discovers MLflow, injects env vars| Deployment

style User fill:#ffecb3
style RuntimeCR fill:#e1f5fe
style AgentCardCR fill:#e1f5fe
style ValidationWebhook fill:#fff3e0
style InjectionWebhook fill:#fff3e0
style RuntimeController fill:#ffe0b2
style SyncController fill:#ffe0b2
style CardController fill:#ffe0b2
style NPController fill:#ffe0b2
style MLflowController fill:#ffe0b2
style Deployment fill:#d1c4e9
style Pod fill:#c8e6c9
```

The operator runs three controllers:
The operator runs the following controllers and webhooks:

| Controller | Purpose |
|------------|---------|
| **AgentCard Sync Controller** | Watches Deployments/StatefulSets with agent labels and auto-creates AgentCard resources |
| **AgentCard Controller** | Fetches agent card data from running agents, verifies signatures, evaluates identity binding |
| Component | Purpose |
|-----------|---------|
| **AgentRuntime Controller** | Reconciles AgentRuntime CRs — applies labels, computes config hash, triggers rolling updates on config change |
| **AuthBridge Webhook** | Mutating webhook that injects sidecar containers (envoy-proxy, SPIFFE helper, client registration) into agent/tool Pods |
| **AgentCard Sync Controller** | Watches labeled Deployments/StatefulSets and auto-creates AgentCard resources |
| **AgentCard Controller** | Fetches agent card data from running agents, verifies JWS signatures, evaluates identity binding |
| **NetworkPolicy Controller** | Creates permissive or restrictive NetworkPolicies based on signature verification status |
| **MLflow Controller** | Auto-discovers MLflow instances, creates experiments per agent, injects tracking env vars and RBAC |

## Quick Start

Expand Down Expand Up @@ -108,16 +125,20 @@ By default the script installs the released operator version pinned as a chart d
# Install the operator using OCI chart
helm install kagenti-operator \
oci://ghcr.io/kagenti/kagenti-operator/kagenti-operator-chart \
--version 0.2.0-alpha.19 \
--namespace kagenti-system \
--create-namespace
```

### Deploy Your First Agent

Deploy an agent as a standard Kubernetes Deployment with the required `kagenti.io/type: agent` label:
There are two ways to deploy agents. The **AgentRuntime** approach is recommended — it keeps your workload manifests clean and provides identity, auth, and observability configuration.

#### Option 1: AgentRuntime (Recommended)

Deploy a clean Deployment and create an AgentRuntime CR:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

suggestion: "Deploy a clean Deployment" contradicts the fact that users must add protocol.kagenti.io/a2a (shown a few lines below). Consider: "Deploy a Deployment with a protocol label and create an AgentRuntime CR:" — consistent with GETTING_STARTED.md which was correctly updated.


```bash
# Deploy the agent workload
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
Expand All @@ -126,7 +147,6 @@ metadata:
namespace: default
labels:
app.kubernetes.io/name: weather-agent
kagenti.io/type: agent
protocol.kagenti.io/a2a: ""
spec:
replicas: 1
Expand All @@ -137,7 +157,6 @@ spec:
metadata:
labels:
app.kubernetes.io/name: weather-agent
kagenti.io/type: agent
spec:
containers:
- name: agent
Expand All @@ -161,15 +180,74 @@ spec:
port: 8000
targetPort: 8000
EOF

# Enroll it with an AgentRuntime CR
kubectl apply -f - <<EOF
apiVersion: agent.kagenti.dev/v1alpha1
kind: AgentRuntime
metadata:
name: weather-agent-runtime
namespace: default
spec:
type: agent
targetRef:
apiVersion: apps/v1
kind: Deployment
name: weather-agent
EOF
```

The operator will automatically create an AgentCard for the workload and begin syncing agent metadata.
The operator will apply `kagenti.io/type: agent` labels and inject AuthBridge sidecars. The `protocol.kagenti.io/a2a` label on the Deployment triggers automatic AgentCard creation for agent discovery.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

suggestion (accuracy/clarity): This could be read as "the protocol label alone triggers AgentCard creation." Since shouldSyncWorkload() requires both kagenti.io/type=agent (applied by AgentRuntime) and a protocol label, consider:

The operator will apply kagenti.io/type: agent labels and inject AuthBridge sidecars. Together with the protocol.kagenti.io/a2a label on the Deployment, this triggers automatic AgentCard creation for agent discovery.


#### Option 2: Manual Labels

For quick tests, add labels directly to your Deployment:

```bash
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: weather-agent
namespace: default
labels:
app.kubernetes.io/name: weather-agent
kagenti.io/type: agent
protocol.kagenti.io/a2a: ""
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: weather-agent
template:
metadata:
labels:
app.kubernetes.io/name: weather-agent
kagenti.io/type: agent
spec:
containers:
- name: agent
image: "ghcr.io/kagenti/agent-examples/weather_service:v0.0.1-alpha.3"
ports:
- containerPort: 8000
env:
- name: PORT
value: "8000"
EOF
```

### Verify Deployment

```bash
# Check AgentRuntime status (if using AgentRuntime)
kubectl get agentruntime
# NAME TYPE TARGET PHASE AGE
# weather-agent-runtime agent weather-agent Active 2m

# Check discovered agent cards
kubectl get agentcards
# NAME PROTOCOL KIND TARGET AGENT SYNCED AGE
# weather-agent-deployment-card a2a Deployment weather-agent Weather Assistant True 5m

# View agent logs
kubectl logs -l app.kubernetes.io/name=weather-agent
Expand All @@ -179,17 +257,25 @@ kubectl logs -l app.kubernetes.io/name=weather-agent

| Topic | Link |
|-------|------|
| **Getting Started** | [Tutorials & End-to-End Walkthrough](./kagenti-operator/GETTING_STARTED.md) |
| **API Reference** | [CRD Specifications & Examples](./kagenti-operator/docs/api-reference.md) |
| **Architecture** | [Operator Design & Components](./kagenti-operator/docs/architecture.md) |
| **AuthBridge Webhook** | [Sidecar Injection & Configuration](./kagenti-operator/docs/authbridge-webhook.md) |
| **Controller-Webhook Interaction** | [AgentRuntime Controller & Webhook Coordination](./kagenti-operator/docs/controller-webhook-interaction.md) |
| **Dynamic Discovery** | [Agent Discovery with AgentCard](./kagenti-operator/docs/dynamic-agent-discovery.md) |
| **Signature Verification** | [A2A AgentCard Signature Verification](./kagenti-operator/docs/a2a-signature-verification.md) |
| **Identity Binding** | [Workload Identity Binding](./kagenti-operator/docs/identity-binding-quickstart.md) |
| **Signature Verification** | [A2A AgentCard Signature Verification](./kagenti-operator/docs/agentcard-signature-verification.md) |
| **Identity Binding** | [SPIFFE Workload Identity Binding](./kagenti-operator/docs/agentcard-identity-binding.md) |
| **MLflow Integration** | [MLflow Tracing & Experiment Tracking](./kagenti-operator/docs/mlflow-integration.md) |
| **Client Registration** | [Operator-Managed Keycloak Registration](./kagenti-operator/docs/operator-managed-client-registration.md) |
| **Developer Guide** | [Contributing & Development](./kagenti-operator/docs/dev.md) |
| **Getting Started** | [Detailed Tutorials](./kagenti-operator/GETTING_STARTED.md) |

## Examples

See the [config/samples](./kagenti-operator/config/samples) directory for complete examples.
See the [config/samples](./kagenti-operator/config/samples) directory for AgentRuntime examples:

- [`agent_v1alpha1_agentruntime_basic.yaml`](./kagenti-operator/config/samples/agent_v1alpha1_agentruntime_basic.yaml) — Minimal AgentRuntime with type + targetRef
- [`agent_v1alpha1_agentruntime_full.yaml`](./kagenti-operator/config/samples/agent_v1alpha1_agentruntime_full.yaml) — With SPIFFE trust domain and OTEL trace overrides
- [`agent_v1alpha1_agentruntime_tool.yaml`](./kagenti-operator/config/samples/agent_v1alpha1_agentruntime_tool.yaml) — Tool-type workload (MCP server)

## Contributing

Expand Down
7 changes: 4 additions & 3 deletions kagenti-operator/GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ This scenario demonstrates the complete lifecycle of an AI agent deployment on t
### Kagenti Operator
The Kagenti Operator discovers, indexes, and secures AI agents deployed in Kubernetes. There are two ways to enroll workloads:

1. **AgentRuntime CR (Recommended)** — Create a clean Deployment and an `AgentRuntime` CR pointing to it. The controller applies labels and triggers sidecar injection automatically. Your workload manifests stay free of kagenti-specific labels.
1. **AgentRuntime CR (Recommended)** — Create a Deployment with a `protocol.kagenti.io/a2a` label and an `AgentRuntime` CR pointing to it. The controller applies `kagenti.io/type` labels and triggers sidecar injection automatically. The protocol label enables automatic AgentCard creation for agent discovery.
2. **Manual labels** — Add the `kagenti.io/type: agent` label directly to your Deployment or StatefulSet. This is simpler for quick tests but does not provide identity or observability configuration.

> **Note:** The `Agent` Custom Resource is deprecated and will be removed in a future release.
Expand All @@ -51,9 +51,9 @@ The Kagenti Operator discovers, indexes, and secures AI agents deployed in Kuber

## Deploy an Agent with AgentRuntime (Recommended)

The AgentRuntime approach keeps your workload manifests clean — no kagenti labels required. The controller applies labels, computes a config hash, and triggers the AuthBridge webhook to inject sidecars.
The AgentRuntime approach requires only a `protocol.kagenti.io/a2a` label on your Deployment — the controller applies `kagenti.io/type`, computes a config hash, and triggers the AuthBridge webhook to inject sidecars. The protocol label tells the AgentCard sync controller which protocol the agent speaks, enabling automatic discovery.

### Step 1: Deploy a Clean Deployment
### Step 1: Deploy a Deployment with Protocol Label

```yaml
kubectl apply -f - <<EOF
Expand All @@ -64,6 +64,7 @@ metadata:
namespace: team1
labels:
app.kubernetes.io/name: weather-agent
protocol.kagenti.io/a2a: ""
spec:
replicas: 1
selector:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Basic AgentRuntime: enroll a Deployment as an agent with default configuration.
# The controller applies kagenti.io/type label and triggers sidecar injection.
# Identity and trace settings come from cluster and namespace defaults.
# Note: The target Deployment should have a protocol.kagenti.io/a2a label
# for automatic AgentCard creation and agent discovery.
apiVersion: agent.kagenti.dev/v1alpha1
kind: AgentRuntime
metadata:
Expand Down
2 changes: 1 addition & 1 deletion kagenti-operator/docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The Kagenti Operator is a Kubernetes controller that implements the [Operator Pa
- Configures identity (SPIFFE) and observability (OTEL traces) per workload via 3-layer defaults (cluster → namespace → CR)
- Uses `targetRef` to reference backing workloads (Deployment, StatefulSet)
- The `kagenti.io/type` label applied by the controller triggers the webhook's `objectSelector`
- Developer workloads stay completely clean — no kagenti labels required in manifests
- Developer workloads only need a `protocol.kagenti.io/a2a` label — the controller applies `kagenti.io/type` and `managed-by` labels automatically

### Controllers

Expand Down
Loading