Skip to content
Draft
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
355 changes: 355 additions & 0 deletions api/v1alpha1/agentgateway_backend_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
)

// +kubebuilder:rbac:groups=gateway.kgateway.dev,resources=agentgatewaybackends,verbs=get;list;watch
// +kubebuilder:rbac:groups=gateway.kgateway.dev,resources=agentgatewaybackends/status,verbs=get;update;patch

// +kubebuilder:printcolumn:name="Accepted",type=string,JSONPath=".status.conditions[?(@.type=='Accepted')].status",description="Backend configuration acceptance status"
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=".metadata.creationTimestamp",description="The age of the backend."

// +genclient
// +kubebuilder:object:root=true
// +kubebuilder:metadata:labels={app=kgateway,app.kubernetes.io/name=kgateway}
// +kubebuilder:resource:categories=kgateway,shortName=agbe
// +kubebuilder:subresource:status
type AgentgatewayBackend struct {
metav1.TypeMeta `json:",inline"`
// metadata for the object
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
metav1.ObjectMeta `json:"metadata,omitempty"`

// spec defines the desired state of AgentgatewayBackend.
Spec AgentgatewayBackendSpec `json:"spec"`

// status defines the current state of AgentgatewayBackend.
Status AgentgatewayBackendStatus `json:"status,omitempty"`
// TODO: embed this into a typed Status field when
// https://github.com/kubernetes/kubernetes/issues/131533 is resolved
}

// AgentgatewayBackend defines the observed state of AgentgatewayBackend.
type AgentgatewayBackendStatus struct {
// Conditions is the list of conditions for the backend.
// +listType=map
// +listMapKey=type
// +kubebuilder:validation:MaxItems=8
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

// +kubebuilder:object:root=true
type AgentgatewayBackendList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AgentgatewayBackend `json:"items"`
}

// +kubebuilder:validation:ExactlyOneOf=ai;static;dynamicForwardProxy;mcp
type AgentgatewayBackendSpec struct {
// static represents a static hostname.
Static *AgentStaticBackend `json:"static,omitempty"`

// ai represents a LLM backend.
AI *AIBackend `json:"ai,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

How do host override and the other override options get configured now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its still on AIBackend


// mcp represents an MCP backend
NCO *MCPBackend `json:"mcp,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

NCO?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is "MCP" when your fingers are 1 key shifted left 🙃


// dynamicForwardProxy configures the proxy to dynamically send requests to the destination based on the incoming
// request HTTP host header, or TLS SNI for TLS traffic.
//
// Note: this Backend type enables users to send trigger the proxy to send requests to arbitrary destinations. Proper
// access controls must be put in place when using this backend type.
DynamicForwardProxy *AgentDynamicForwardProxyBackend `json:"dynamicForwardProxy,omitempty"`

// policies controls policies for communicating with this backend. Policies may also be set in AgentgatewayPolicy;
// policies are merged on a field-level basis, with policies on the Backend (this field) taking precedence.
Policies *AgentgatewayPolicyBackend `json:"policies,omitempty"`
}

type AgentDynamicForwardProxyBackend struct {
}

// AgentAppProtocol defines the application protocol to use when communicating with the backend.
// +kubebuilder:validation:Enum=kubernetes.io/h2c
type AgentAppProtocol string

const (
// AppProtocolKubernetesH2C is the kubernetes.io/h2c app protocol.
AgentAppProtocolKubernetesH2C AgentAppProtocol = "kubernetes.io/h2c"
)

type AgentStaticBackend struct {
// host to connect to.
// +kubebuilder:validation:MinLength=1
Host ShortString `json:"host"`
// port to connect to.
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
Port int32 `json:"port"`

// appProtocol is the application protocol to use when communicating with the backend.
AppProtocol *AgentAppProtocol `json:"appProtocol,omitempty"`
}

// AIBackend specifies the AI backend configuration
// +kubebuilder:validation:ExactlyOneOf=provider;groups
type AIBackend struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

How do you configure routeType on the AI Backend with this API?

// provider specifies configuration for how to reach the configured LLM provider.
LLM *LLMProvider `json:"provider,omitempty"`

// groups specifies a list of groups in priority order where each group defines
// a set of LLM providers. The priority determines the priority of the backend endpoints chosen.
// Note: provider names must be unique across all providers in all priority groups. Backend policies
// may target a specific provider by name using targetRefs[].sectionName.
//
// Example configuration with two priority groups:
// ```yaml
// groups:
// - providers:
// - azureOpenai:
// deploymentName: gpt-4o-mini
// apiVersion: 2024-02-15-preview
// endpoint: ai-gateway.openai.azure.com
// authToken:
// secretRef:
// name: azure-secret
// namespace: kgateway-system
// - providers:
// - azureOpenai:
// deploymentName: gpt-4o-mini-2
// apiVersion: 2024-02-15-preview
// endpoint: ai-gateway-2.openai.azure.com
// authToken:
// secretRef:
// name: azure-secret-2
// namespace: kgateway-system
// ```
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=32
// TODO: enable this rule when we don't need to support older k8s versions where this rule breaks // +kubebuilder:validation:XValidation:message="provider names must be unique across groups",rule="self.map(pg, pg.providers.map(pp, pp.name)).map(p, self.map(pg, pg.providers.map(pp, pp.name)).filter(cp, cp != p).exists(cp, p.exists(pn, pn in cp))).exists(p, !p)"
PriorityGroups []PriorityGroup `json:"groups,omitempty"`
}

type PriorityGroup struct {
// providers specifies a list of LLM providers within this group. Each provider is treated equally in terms of priority,
// with automatic weighting based on health.
//
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=32
// +kubebuilder:validation:XValidation:message="provider names must be unique within a group",rule="self.all(p1, self.exists_one(p2, p1.name == p2.name))"
Providers []NamedLLMProvider `json:"providers,omitempty"`
}

type NamedLLMProvider struct {
// Name of the provider. Policies can target this provider by name.
Name gwv1.SectionName `json:"name"`

// policies controls policies for communicating with this backend. Policies may also be set in AgentgatewayPolicy, or
// in the top level AgentgatewayBackend. policies are merged on a field-level basis, with order: AgentgatewayPolicy <
// AgentgatewayBackend < AgentgatewayBackend LLM provider (this field).
Policies *AgentgatewayPolicyBackend `json:"policies,omitempty"`

LLMProvider `json:",inline"`
}

// LLMProvider specifies the target large language model provider that the backend should route requests to.
// +kubebuilder:validation:ExactlyOneOf=openai;azureopenai;anthropic;gemini;vertexai;bedrock
// +kubebuilder:validation:XValidation:rule="has(self.host) || has(self.port) ? has(self.host) && has(self.port) : true",message="both host and port must be set together"
type LLMProvider struct {
// OpenAI provider
OpenAI *OpenAIConfig `json:"openai,omitempty"`

// Azure OpenAI provider
AzureOpenAI *AzureOpenAIConfig `json:"azureopenai,omitempty"`

// Anthropic provider
Anthropic *AnthropicConfig `json:"anthropic,omitempty"`

// Gemini provider
Gemini *GeminiConfig `json:"gemini,omitempty"`

// Vertex AI provider
VertexAI *VertexAIConfig `json:"vertexai,omitempty"`

// Bedrock provider
Bedrock *BedrockConfig `json:"bedrock,omitempty"`

// Host specifies the hostname to send the requests to.
// If not specified, the default hostname for the provider is used.
// +kubebuilder:validation:MinLength=1
Host ShortString `json:"host,omitempty"`

// Port specifies the port to send the requests to.
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
Port int32 `json:"port,omitempty"`

// Path specifies the URL path to use for the LLM provider API requests.
// This is useful when you need to route requests to a different API endpoint while maintaining
// compatibility with the original provider's API structure.
// If not specified, the default path for the provider is used.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=1024
Path string `json:"path,omitempty"`
}

// OpenAIConfig settings for the [OpenAI](https://platform.openai.com/docs/api-reference/streaming) LLM provider.
type OpenAIConfig struct{}

// AzureOpenAIConfig settings for the [Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-services/openai/) LLM provider.
type AzureOpenAIConfig struct {
// The endpoint for the Azure OpenAI API to use, such as `my-endpoint.openai.azure.com`.
// If the scheme is included, it is stripped.
// +kubebuilder:validation:MinLength=1
Endpoint ShortString `json:"endpoint"`

// The name of the Azure OpenAI model deployment to use.
// For more information, see the [Azure OpenAI model docs](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models).
// +kubebuilder:validation:MinLength=1
DeploymentName ShortString `json:"deploymentName"`

// The version of the Azure OpenAI API to use.
// For more information, see the [Azure OpenAI API version reference](https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#api-specs).
// +kubebuilder:validation:MinLength=1
ApiVersion TinyString `json:"apiVersion"`
}

// GeminiConfig settings for the [Gemini](https://ai.google.dev/gemini-api/docs) LLM provider.
type GeminiConfig struct {
}

// Publisher configures the type of publisher model to use for VertexAI. Currently, only Google is supported.
type Publisher string

const (
PublisherGoogle Publisher = "Google"
)

// VertexAIConfig settings for the [Vertex AI](https://cloud.google.com/vertex-ai/docs) LLM provider.
type VertexAIConfig struct {
// The version of the Vertex AI API to use.
// For more information, see the [Vertex AI API reference](https://cloud.google.com/vertex-ai/docs/reference#versions).
// +kubebuilder:validation:MinLength=1
ApiVersion TinyString `json:"apiVersion"`

// The ID of the Google Cloud Project that you use for the Vertex AI.
// +kubebuilder:validation:MinLength=1
ProjectId TinyString `json:"projectId"`

// The location of the Google Cloud Project that you use for the Vertex AI.
// +kubebuilder:validation:MinLength=1
Region TinyString `json:"region"`

// The type of publisher model to use. Currently, only Google is supported.
// +kubebuilder:validation:Enum=Google
Publisher Publisher `json:"publisher"`
}

// AnthropicConfig settings for the [Anthropic](https://docs.anthropic.com/en/release-notes/api) LLM provider.
type AnthropicConfig struct {
}

type BedrockConfig struct {
// Region is the AWS region to use for the backend.
// Defaults to us-east-1 if not specified.
// +optional
// +kubebuilder:default=us-east-1
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=63
// +kubebuilder:validation:Pattern="^[a-z0-9-]+$"
Region string `json:"region,omitempty"`

// Guardrail configures the Guardrail policy to use for the backend. See <https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html>
// If not specified, the AWS Guardrail policy will not be used.
// +optional
Guardrail *AWSGuardrailConfig `json:"guardrail,omitempty"`
}

type AWSGuardrailConfig struct {
// GuardrailIdentifier is the identifier of the Guardrail policy to use for the backend.
// +kubebuilder:validation:MinLength=1
GuardrailIdentifier string `json:"identifier"`

// GuardrailVersion is the version of the Guardrail policy to use for the backend.
// +kubebuilder:validation:MinLength=1
GuardrailVersion string `json:"version"`
}

// MCPBackend configures mcp backends
type MCPBackend struct {
// Targets is a list of MCPBackend targets to use for this backend.
// Policies targeting MCPBackend targets must use targetRefs[].sectionName
// to select the target by name.
// +listType=map
// +listMapKey=name
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=32
// +kubebuilder:validation:XValidation:message="target names must be unique",rule="self.all(t1, self.exists_one(t2, t1.name == t2.name))"
Targets []McpTargetSelector `json:"targets"`
}

// McpTargetSelector defines the MCPBackend target to use for this backend.
// +kubebuilder:validation:ExactlyOneOf=selector;static
type McpTargetSelector struct {
// Name of the MCPBackend target.
Name gwv1.SectionName `json:"name"`

// selector is a label selector is the selector to use to select Services.
// If policies are needed on a per-service basis, AgentgatewayPolicy can target the desired Service.
Selector *McpSelector `json:"selector,omitempty"`

// static configures a static MCP destination. When connecting to in-cluster Services, it is recommended to use
// 'selector' instead.
Static *McpTarget `json:"static,omitempty"`
}

// +kubebuilder:validation:AtLeastOneOf=namespaces;services
type McpSelector struct {
// namespace is the label selector in which namespaces Services should be selected from.
// If unset, only the namespace of the AgentgatewayBackend is searched.
Namespace *metav1.LabelSelector `json:"namespaces,omitempty"`

// services is the label selector for which Services should be selected.
Service *metav1.LabelSelector `json:"services,omitempty"`
}

// McpTarget defines a single MCPBackend target configuration.
type McpTarget struct {
// Host is the hostname or IP address of the MCPBackend target.
// +kubebuilder:validation:MinLength=1
Host ShortString `json:"host"`

// Port is the port number of the MCPBackend target.
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
Port int32 `json:"port"`

// Path is the URL path of the MCPBackend target endpoint.
// Defaults to "/sse" for SSE protocol or "/mcp" for StreamableHTTP protocol if not specified.
Path *string `json:"path,omitempty"`

// Protocol is the protocol to use for the connection to the MCPBackend target.
Protocol *MCPProtocol `json:"protocol,omitempty"`

// policies controls policies for communicating with this backend. Policies may also be set in AgentgatewayPolicy, or
// in the top level AgentgatewayBackend. Policies are merged on a field-level basis, with order: AgentgatewayPolicy <
// AgentgatewayBackend < AgentgatewayBackend MCP (this field).
Policies *AgentgatewayPolicyBackend `json:"policies,omitempty"`
}

// MCPProtocol defines the protocol to use for the MCPBackend target
// +kubebuilder:validation:Enum=StreamableHTTP;SSE
type MCPProtocol string

const (

// MCPProtocolStreamableHTTP specifies Streamable HTTP must be used as the protocol
MCPProtocolStreamableHTTP MCPProtocol = "StreamableHTTP"

// MCPProtocolSSE specifies Server-Sent Events (SSE) must be used as the protocol
MCPProtocolSSE MCPProtocol = "SSE"
)
Loading
Loading