{
  "description": "AIServiceBackend is a resource that represents a single backend for AIGatewayRoute.\nA backend is a service that handles traffic with a concrete API specification.\n\nA AIServiceBackend is \"attached\" to a Backend which is either a k8s Service or a Backend resource of the Envoy Gateway.\n\nWhen a backend with an attached AIServiceBackend is used as a routing target in the AIGatewayRoute (more precisely, the\nHTTPRouteSpec defined in the AIGatewayRoute), the ai-gateway will generate the necessary configuration to do\nthe backend specific logic in the final HTTPRoute.",
  "properties": {
    "apiVersion": {
      "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
      "type": "string"
    },
    "kind": {
      "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
      "type": "string"
    },
    "metadata": {
      "type": "object"
    },
    "spec": {
      "description": "Spec defines the details of AIServiceBackend.",
      "properties": {
        "backendRef": {
          "description": "BackendRef is the reference to the Backend resource that this AIServiceBackend corresponds to.\n\nA backend must be a Backend resource of Envoy Gateway. Note that k8s Service will be supported\nas a backend in the future. See https://github.com/envoyproxy/ai-gateway/issues/902 for more details.\n\nThis is required to be set.",
          "properties": {
            "group": {
              "default": "",
              "description": "Group is the group of the referent. For example, \"gateway.networking.k8s.io\".\nWhen unspecified or empty string, core API group is inferred.",
              "maxLength": 253,
              "pattern": "^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$",
              "type": "string"
            },
            "kind": {
              "default": "Service",
              "description": "Kind is the Kubernetes resource kind of the referent. For example\n\"Service\".\n\nDefaults to \"Service\" when not specified.\n\nExternalName services can refer to CNAME DNS records that may live\noutside of the cluster and as such are difficult to reason about in\nterms of conformance. They also may not be safe to forward to (see\nCVE-2021-25740 for more information). Implementations SHOULD NOT\nsupport ExternalName Services.\n\nSupport: Core (Services with a type other than ExternalName)\n\nSupport: Implementation-specific (Services with type ExternalName)",
              "maxLength": 63,
              "minLength": 1,
              "pattern": "^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$",
              "type": "string"
            },
            "name": {
              "description": "Name is the name of the referent.",
              "maxLength": 253,
              "minLength": 1,
              "type": "string"
            },
            "namespace": {
              "description": "Namespace is the namespace of the backend. When unspecified, the local\nnamespace is inferred.\n\nNote that when a namespace different than the local namespace is specified,\na ReferenceGrant object is required in the referent namespace to allow that\nnamespace's owner to accept the reference. See the ReferenceGrant\ndocumentation for details.\n\nSupport: Core",
              "maxLength": 63,
              "minLength": 1,
              "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$",
              "type": "string"
            },
            "port": {
              "description": "Port specifies the destination port number to use for this resource.\nPort is required when the referent is a Kubernetes Service. In this\ncase, the port number is the service port number, not the target port.\nFor other resources, destination port might be derived from the referent\nresource or this field.",
              "format": "int32",
              "maximum": 65535,
              "minimum": 1,
              "type": "integer"
            }
          },
          "required": [
            "name"
          ],
          "type": "object",
          "x-kubernetes-validations": [
            {
              "message": "BackendRef must be a Backend resource of Envoy Gateway. See https://github.com/envoyproxy/ai-gateway/issues/902 for more details.",
              "rule": "has(self.kind) && self.kind == 'Backend' && has(self.group) && self.group == 'gateway.envoyproxy.io'"
            },
            {
              "message": "Must have port for Service reference",
              "rule": "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true"
            }
          ],
          "additionalProperties": false
        },
        "bodyMutation": {
          "description": "BodyMutation defines the mutation of HTTP request body JSON fields that will be applied to the request\nbefore sending it to the backend.",
          "properties": {
            "remove": {
              "description": "Remove the given JSON field(s) from the HTTP request body before sending to the backend.\nThe value of Remove is a list of top-level field names to remove.\n\nInput:\n  {\n    \"model\": \"gpt-4\",\n    \"service_tier\": \"default\",\n    \"internal_flag\": true\n  }\n\nConfig:\n  remove: [\"service_tier\", \"internal_flag\"]\n\nOutput:\n  {\n    \"model\": \"gpt-4\"\n  }",
              "items": {
                "type": "string"
              },
              "maxItems": 16,
              "type": "array",
              "x-kubernetes-list-type": "set"
            },
            "set": {
              "description": "Set overwrites/adds the request body with the given JSON field (name, value)\nbefore sending to the backend. Only top-level fields are currently supported.\n\nInput:\n  {\n    \"model\": \"gpt-4\",\n    \"service_tier\": \"default\"\n  }\n\nConfig:\n  set:\n  - path: \"service_tier\"\n    value: \"scale\"\n\nOutput:\n  {\n    \"model\": \"gpt-4\",\n    \"service_tier\": \"scale\"\n  }",
              "items": {
                "description": "HTTPBodyField represents a JSON field name and value for body mutation",
                "properties": {
                  "path": {
                    "description": "Path is the top-level field name to set in the request body.\nExamples: \"service_tier\", \"max_tokens\", \"temperature\"",
                    "minLength": 1,
                    "type": "string"
                  },
                  "value": {
                    "description": "Value is the JSON value to set at the specified field. This can be any valid JSON value:\nstring, number, boolean, object, array, or null.\nThe value will be parsed as JSON and inserted at the specified field.\n\nExamples:\n  - \"\\\"scale\\\"\" (string)\n  - \"42\" (number)\n  - \"true\" (boolean)\n  - \"{\\\"key\\\": \\\"value\\\"}\" (object)\n  - \"[1, 2, 3]\" (array)\n  - \"null\" (null)",
                    "type": "string"
                  }
                },
                "required": [
                  "path",
                  "value"
                ],
                "type": "object",
                "additionalProperties": false
              },
              "maxItems": 16,
              "type": "array",
              "x-kubernetes-list-map-keys": [
                "path"
              ],
              "x-kubernetes-list-type": "map"
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "headerMutation": {
          "description": "HeaderMutation defines the mutation of HTTP headers that will be applied to the request\nbefore sending it to the backend.",
          "properties": {
            "remove": {
              "description": "Remove the given header(s) from the HTTP request before the action. The\nvalue of Remove is a list of HTTP header names. Note that the header\nnames are case-insensitive (see\nhttps://datatracker.ietf.org/doc/html/rfc2616#section-4.2).\n\nInput:\n  GET /foo HTTP/1.1\n  my-header1: foo\n  my-header2: bar\n  my-header3: baz\n\nConfig:\n  remove: [\"my-header1\", \"my-header3\"]\n\nOutput:\n  GET /foo HTTP/1.1\n  my-header2: bar",
              "items": {
                "type": "string"
              },
              "maxItems": 16,
              "type": "array",
              "x-kubernetes-list-type": "set"
            },
            "set": {
              "description": "Set overwrites/adds the request with the given header (name, value)\nbefore the action.\n\nInput:\n  GET /foo HTTP/1.1\n  my-header: foo\n\nConfig:\n  set:\n  - name: \"my-header\"\n    value: \"bar\"\n\nOutput:\n  GET /foo HTTP/1.1\n  my-header: bar",
              "items": {
                "description": "HTTPHeader represents an HTTP Header name and value as defined by RFC 7230.",
                "properties": {
                  "name": {
                    "description": "Name is the name of the HTTP Header to be matched. Name matching MUST be\ncase-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).\n\nIf multiple entries specify equivalent header names, the first entry with\nan equivalent name MUST be considered for a match. Subsequent entries\nwith an equivalent header name MUST be ignored. Due to the\ncase-insensitivity of header names, \"foo\" and \"Foo\" are considered\nequivalent.",
                    "maxLength": 256,
                    "minLength": 1,
                    "pattern": "^[A-Za-z0-9!#$%&'*+\\-.^_\\x60|~]+$",
                    "type": "string"
                  },
                  "value": {
                    "description": "Value is the value of HTTP Header to be matched.",
                    "maxLength": 4096,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "value"
                ],
                "type": "object",
                "additionalProperties": false
              },
              "maxItems": 16,
              "type": "array",
              "x-kubernetes-list-map-keys": [
                "name"
              ],
              "x-kubernetes-list-type": "map"
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "schema": {
          "description": "APISchema specifies the API schema of the output format of requests from\nEnvoy that this AIServiceBackend can accept as incoming requests.\nBased on this schema, the ai-gateway will perform the necessary transformation for\nthe pair of AIGatewayRouteSpec.APISchema and AIServiceBackendSpec.APISchema.\n\nThis is required to be set.",
          "properties": {
            "name": {
              "description": "Name is the name of the API schema of the AIGatewayRoute or AIServiceBackend.",
              "enum": [
                "OpenAI",
                "Cohere",
                "AWSBedrock",
                "AzureOpenAI",
                "GCPVertexAI",
                "GCPAnthropic",
                "Anthropic",
                "AWSAnthropic"
              ],
              "type": "string"
            },
            "prefix": {
              "description": "Prefix is the prefix for the API.\n\nWhen the name is set to \"OpenAI\", \"chat completions\" API endpoint will be \"${this_field}/chat/completions\".\nIt can be with or without a leading slash (\"/\").\n\nThis is especially useful when routing to the backend that has an OpenAI compatible API but has a different\nprefix. For example, Gemini OpenAI compatible API (https://ai.google.dev/gemini-api/docs/openai) uses\n\"/v1beta/openai\" prefix. Another example is that Cohere AI (https://docs.cohere.com/v2/docs/compatibility-api)\nuses \"/compatibility/v1\" prefix. On the other hand, DeepSeek (https://api-docs.deepseek.com/) doesn't\nuse prefix, so you can leave this field unset.\n\nSee https://aigateway.envoyproxy.io/docs/capabilities/llm-integrations/supported-providers for details.",
              "type": "string"
            },
            "version": {
              "description": "Version is the version of the API schema.\n\nWhen the name is set to AzureOpenAI, this version maps to \"API Version\" in the\nAzure OpenAI API documentation (https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning).\n\n**Deprecated Behavior**: When the name is set to \"OpenAI\", this version field will behave as the\nprefix field. This is to maintain backward compatibility. This will be removed in future releases.\n\nSee https://aigateway.envoyproxy.io/docs/capabilities/llm-integrations/supported-providers for details.",
              "type": "string"
            }
          },
          "required": [
            "name"
          ],
          "type": "object",
          "additionalProperties": false
        }
      },
      "required": [
        "backendRef",
        "schema"
      ],
      "type": "object",
      "additionalProperties": false
    },
    "status": {
      "description": "Status defines the status details of the AIServiceBackend.",
      "properties": {
        "conditions": {
          "description": "Conditions is the list of conditions by the reconciliation result.\nCurrently, at most one condition is set.\n\nKnown .status.conditions.type are: \"Accepted\", \"NotAccepted\".",
          "items": {
            "description": "Condition contains details for one aspect of the current state of this API Resource.",
            "properties": {
              "lastTransitionTime": {
                "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.",
                "format": "date-time",
                "type": "string"
              },
              "message": {
                "description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.",
                "maxLength": 32768,
                "type": "string"
              },
              "observedGeneration": {
                "description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.",
                "format": "int64",
                "minimum": 0,
                "type": "integer"
              },
              "reason": {
                "description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.",
                "maxLength": 1024,
                "minLength": 1,
                "pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
                "type": "string"
              },
              "status": {
                "description": "status of the condition, one of True, False, Unknown.",
                "enum": [
                  "True",
                  "False",
                  "Unknown"
                ],
                "type": "string"
              },
              "type": {
                "description": "type of condition in CamelCase or in foo.example.com/CamelCase.",
                "maxLength": 316,
                "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                "type": "string"
              }
            },
            "required": [
              "lastTransitionTime",
              "message",
              "reason",
              "status",
              "type"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        }
      },
      "type": "object",
      "additionalProperties": false
    }
  },
  "type": "object"
}
