{
  "description": "ModelConfig is the Schema for the modelconfigs API.",
  "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",
        "null"
      ]
    },
    "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",
        "null"
      ]
    },
    "metadata": {
      "type": [
        "object",
        "null"
      ]
    },
    "spec": {
      "additionalProperties": false,
      "description": "ModelConfigSpec defines the desired state of ModelConfig.",
      "properties": {
        "anthropic": {
          "additionalProperties": false,
          "description": "Anthropic-specific configuration",
          "properties": {
            "baseUrl": {
              "description": "Base URL for the Anthropic API (overrides default)",
              "type": [
                "string",
                "null"
              ]
            },
            "maxTokens": {
              "description": "Maximum tokens to generate",
              "type": [
                "integer",
                "null"
              ]
            },
            "temperature": {
              "description": "Temperature for sampling",
              "type": [
                "string",
                "null"
              ]
            },
            "topK": {
              "description": "Top-k sampling parameter",
              "type": [
                "integer",
                "null"
              ]
            },
            "topP": {
              "description": "Top-p sampling parameter",
              "type": [
                "string",
                "null"
              ]
            }
          },
          "type": [
            "object",
            "null"
          ]
        },
        "anthropicVertexAI": {
          "additionalProperties": false,
          "description": "Anthropic-specific configuration",
          "properties": {
            "location": {
              "description": "The project location",
              "type": "string"
            },
            "maxTokens": {
              "description": "Maximum tokens to generate",
              "type": [
                "integer",
                "null"
              ]
            },
            "projectID": {
              "description": "The project ID",
              "type": "string"
            },
            "stopSequences": {
              "description": "Stop sequences",
              "items": {
                "type": "string"
              },
              "type": [
                "array",
                "null"
              ]
            },
            "temperature": {
              "description": "Temperature",
              "type": [
                "string",
                "null"
              ]
            },
            "topK": {
              "description": "Top-k sampling parameter",
              "type": [
                "string",
                "null"
              ]
            },
            "topP": {
              "description": "Top-p sampling parameter",
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "location",
            "projectID"
          ],
          "type": [
            "object",
            "null"
          ]
        },
        "apiKeyPassthrough": {
          "description": "APIKeyPassthrough enables forwarding the Bearer token from incoming A2A requests\ndirectly to the LLM provider as the API key. This is useful for organizations\nwith federated identity that want to avoid separate secret management.\nMutually exclusive with apiKeySecret.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "apiKeySecret": {
          "description": "The name of the secret that contains the API key. Must be a reference to the name of a secret in the same namespace as the referencing ModelConfig.\nFor the SAPAICore provider, the secret must contain two keys: \"client_id\" and \"client_secret\"\n(the OAuth2 client credentials for SAP AI Core). The apiKeySecretKey field is not used for SAPAICore.",
          "type": [
            "string",
            "null"
          ]
        },
        "apiKeySecretKey": {
          "description": "The key in the secret that contains the API key.\nNot used for the SAPAICore provider (which always reads \"client_id\" and \"client_secret\" from the secret).",
          "type": [
            "string",
            "null"
          ]
        },
        "azureOpenAI": {
          "additionalProperties": false,
          "description": "Azure OpenAI-specific configuration",
          "properties": {
            "apiVersion": {
              "description": "API version for the Azure OpenAI API",
              "type": "string"
            },
            "azureAdToken": {
              "description": "Azure AD token for authentication",
              "type": [
                "string",
                "null"
              ]
            },
            "azureDeployment": {
              "description": "Deployment name for the Azure OpenAI API",
              "type": [
                "string",
                "null"
              ]
            },
            "azureEndpoint": {
              "description": "Endpoint for the Azure OpenAI API",
              "type": "string"
            },
            "maxTokens": {
              "description": "Maximum tokens to generate",
              "type": [
                "integer",
                "null"
              ]
            },
            "temperature": {
              "description": "Temperature for sampling",
              "type": [
                "string",
                "null"
              ]
            },
            "topP": {
              "description": "Top-p sampling parameter",
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "apiVersion",
            "azureEndpoint"
          ],
          "type": [
            "object",
            "null"
          ]
        },
        "bedrock": {
          "additionalProperties": false,
          "description": "AWS Bedrock-specific configuration",
          "properties": {
            "additionalModelRequestFields": {
              "description": "AdditionalModelRequestFields passes model-specific parameters to Bedrock's\nadditionalModelRequestFields in the Converse API. Use this for provider-specific\noptions that are not part of the standard InferenceConfiguration block, such as\nClaude extended thinking or top_k. Values are forwarded as-is to the API.\nExample: {\"top_k\": 5, \"thinking\": {\"type\": \"enabled\", \"budget_tokens\": 16000}}",
              "x-kubernetes-preserve-unknown-fields": true
            },
            "cacheTTL": {
              "default": "5m",
              "description": "CacheTTL controls how long Bedrock retains a cached prefix when\nPromptCaching is enabled. Only meaningful when PromptCaching is true.\n\n  - \"5m\" (default): Bedrock's standard 5-minute sliding cache. Each cache\n    hit refreshes the window. Supported by all prompt-caching models.\n  - \"1h\": extended-TTL caching, useful for tasks whose Converse calls are\n    spaced more than 5 minutes apart.\n\nNOTE: \"1h\" is NOT strictly better than \"5m\". Extended-TTL cache writes are\nbilled at a higher per-token rate than 5-minute writes, and 1h is supported\non a narrower set of models. Only choose \"1h\" when calls are spaced far\nenough apart that a 5-minute cache would expire between them; otherwise the\nhigher write cost is wasted. See the AWS prompt-caching docs above.",
              "enum": [
                "5m",
                "1h"
              ],
              "type": [
                "string",
                "null"
              ]
            },
            "connectTimeout": {
              "description": "ConnectTimeout is the Bedrock HTTP client connection-establishment timeout\nin seconds, applied by both the Python and Go ADK runtimes. It bounds\nconnection setup only, not the response read. When unset, each runtime's\ndefault is used (Python ADK: botocore; Go ADK: net dialer).",
              "minimum": 1,
              "type": [
                "integer",
                "null"
              ]
            },
            "guardrail": {
              "additionalProperties": false,
              "properties": {
                "identifier": {
                  "description": "Identifier is the guardrail ID or full ARN. AWS accepts either a bare\nguardrail ID or an arn:aws:bedrock:...:guardrail/... ARN, so the value is\nonly length-bounded here (AWS caps guardrailIdentifier at 2048 chars).",
                  "maxLength": 2048,
                  "minLength": 1,
                  "type": "string"
                },
                "trace": {
                  "default": "disabled",
                  "enum": [
                    "disabled",
                    "enabled",
                    "enabled_full"
                  ],
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "version": {
                  "description": "Version is the guardrail version: a numeric version (e.g. \"1\") or \"DRAFT\".",
                  "maxLength": 8,
                  "minLength": 1,
                  "type": "string"
                }
              },
              "required": [
                "identifier",
                "version"
              ],
              "type": [
                "object",
                "null"
              ]
            },
            "promptCaching": {
              "default": false,
              "description": "PromptCaching enables Bedrock prompt caching by appending a CachePoint\nblock at the end of the Converse request's `system` content array and\nthe end of the `toolConfig.tools` array. Bedrock will cache the prefix up to and\nincluding those cache points across requests in the same region for\nroughly 5 minutes after first use, billing the cached portion at a\nreduced rate on cache hits.\n\nRecommended for tool-using agents that make many Converse calls per\ntask with a stable system prompt and tool set — the per-call input\ntoken count can drop by 70-90% on hit. Has no effect on models that\ndon't support caching; the marker is ignored by Bedrock for those.\n\nSee https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html\nfor the current list of supported models and minimum prefix sizes.",
              "type": [
                "boolean",
                "null"
              ]
            },
            "readTimeout": {
              "description": "ReadTimeout is the Bedrock HTTP client read timeout in seconds, applied by\nboth the Python and Go ADK runtimes. Raise this for agents that make long\nConverse calls (large tool-augmented turns, extended reasoning). On the\nPython ADK it overrides botocore's ~60s read timeout, which otherwise\naborts long completions with a ReadTimeoutError; on the Go ADK it bounds\nthe whole Converse request (default 30m). When unset, each runtime's\ndefault is used.",
              "minimum": 1,
              "type": [
                "integer",
                "null"
              ]
            },
            "region": {
              "description": "AWS region where the Bedrock model is available (e.g., us-east-1, us-west-2)",
              "type": "string"
            }
          },
          "required": [
            "region"
          ],
          "type": [
            "object",
            "null"
          ]
        },
        "defaultHeaders": {
          "additionalProperties": {
            "type": "string"
          },
          "type": [
            "object",
            "null"
          ]
        },
        "foundry": {
          "additionalProperties": false,
          "description": "Azure AI Foundry-specific configuration",
          "properties": {
            "apiFormat": {
              "default": "OpenAI",
              "description": "APIFormat selects the Foundry API format: \"OpenAI\" (default, chat\ncompletions) or \"Anthropic\" (Claude models served over the Anthropic\nMessages API).",
              "enum": [
                "OpenAI",
                "Anthropic"
              ],
              "type": [
                "string",
                "null"
              ]
            },
            "apiVersion": {
              "default": "2024-10-21",
              "description": "APIVersion is the Foundry OpenAI-compatible data-plane API version.\nIgnored when APIFormat is Anthropic (the Messages surface is versioned via\nthe anthropic-version header instead).",
              "type": [
                "string",
                "null"
              ]
            },
            "deployment": {
              "description": "Deployment is the Foundry model deployment name.",
              "type": "string"
            },
            "endpoint": {
              "description": "Endpoint is the Foundry or Azure AI Services account endpoint\n(e.g., https://my-account.cognitiveservices.azure.com/).\nMutually exclusive with EndpointFrom.",
              "type": [
                "string",
                "null"
              ]
            },
            "endpointFrom": {
              "additionalProperties": false,
              "description": "EndpointFrom resolves the Foundry endpoint from a ConfigMap key, such as\none written by Azure Service Operator. Mutually exclusive with Endpoint.\n\nThe selector's optional flag only controls how a missing key is handled: when\nset to true, the missing key is ignored while reading the ConfigMap, but a\nFoundry endpoint must always be supplied, so an unresolved endpointFrom still\nleaves the model unusable and the agent fails to start.",
              "properties": {
                "key": {
                  "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.",
                  "type": "string"
                },
                "name": {
                  "default": "",
                  "description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "optional": {
                  "description": "Specify whether the ConfigMap or its key must be defined",
                  "type": [
                    "boolean",
                    "null"
                  ]
                }
              },
              "required": [
                "key"
              ],
              "type": [
                "object",
                "null"
              ],
              "x-kubernetes-map-type": "atomic"
            }
          },
          "required": [
            "deployment"
          ],
          "type": [
            "object",
            "null"
          ],
          "x-kubernetes-validations": [
            {
              "message": "foundry.endpoint and foundry.endpointFrom are mutually exclusive",
              "rule": "!(has(self.endpoint) \u0026\u0026 size(self.endpoint) \u003e 0 \u0026\u0026 has(self.endpointFrom))"
            },
            {
              "message": "foundry.endpoint or foundry.endpointFrom is required",
              "rule": "(has(self.endpoint) \u0026\u0026 size(self.endpoint) \u003e 0) || has(self.endpointFrom)"
            }
          ]
        },
        "gemini": {
          "additionalProperties": false,
          "description": "Gemini-specific configuration",
          "properties": {
            "maxOutputTokens": {
              "description": "Maximum output tokens to generate for a single response",
              "minimum": 1,
              "type": [
                "integer",
                "null"
              ]
            }
          },
          "type": [
            "object",
            "null"
          ]
        },
        "geminiVertexAI": {
          "additionalProperties": false,
          "description": "Gemini Vertex AI-specific configuration",
          "properties": {
            "candidateCount": {
              "description": "Candidate count",
              "type": [
                "integer",
                "null"
              ]
            },
            "location": {
              "description": "The project location",
              "type": "string"
            },
            "maxOutputTokens": {
              "description": "Maximum output tokens",
              "minimum": 1,
              "type": [
                "integer",
                "null"
              ]
            },
            "projectID": {
              "description": "The project ID",
              "type": "string"
            },
            "responseMimeType": {
              "description": "Response mime type",
              "type": [
                "string",
                "null"
              ]
            },
            "stopSequences": {
              "description": "Stop sequences",
              "items": {
                "type": "string"
              },
              "type": [
                "array",
                "null"
              ]
            },
            "temperature": {
              "description": "Temperature",
              "type": [
                "string",
                "null"
              ]
            },
            "topK": {
              "description": "Top-k sampling parameter",
              "type": [
                "string",
                "null"
              ]
            },
            "topP": {
              "description": "Top-p sampling parameter",
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "location",
            "projectID"
          ],
          "type": [
            "object",
            "null"
          ]
        },
        "model": {
          "type": "string"
        },
        "ollama": {
          "additionalProperties": false,
          "description": "Ollama-specific configuration",
          "properties": {
            "host": {
              "description": "Host for the Ollama API",
              "type": [
                "string",
                "null"
              ]
            },
            "options": {
              "additionalProperties": {
                "type": "string"
              },
              "description": "Options for the Ollama API",
              "type": [
                "object",
                "null"
              ]
            }
          },
          "type": [
            "object",
            "null"
          ]
        },
        "openAI": {
          "additionalProperties": false,
          "description": "OpenAI-specific configuration",
          "properties": {
            "apiFormat": {
              "default": "chatCompletions",
              "description": "APIFormat selects which OpenAI HTTP API the runtime uses for this model.\nchatCompletions (default) posts to /v1/chat/completions.\nresponses posts to /v1/responses. Use responses for OpenAI-compatible\ngateways or models that require the Responses API.",
              "enum": [
                "chatCompletions",
                "responses"
              ],
              "type": [
                "string",
                "null"
              ]
            },
            "baseUrl": {
              "description": "Base URL for the OpenAI API (overrides default)",
              "type": [
                "string",
                "null"
              ]
            },
            "frequencyPenalty": {
              "description": "Frequency penalty",
              "type": [
                "string",
                "null"
              ]
            },
            "maxCompletionTokens": {
              "description": "Maximum completion tokens to generate. Sent as the OpenAI\n`max_completion_tokens` request parameter (an upper bound on visible\noutput plus reasoning tokens). This is the parameter reasoning models\n(GPT-5 / o-series) require in place of the deprecated maxTokens.\nMutually exclusive with maxTokens.",
              "minimum": 1,
              "type": [
                "integer",
                "null"
              ]
            },
            "maxTokens": {
              "description": "Maximum tokens to generate. Sent as the OpenAI `max_tokens` request\nparameter, which is deprecated and rejected by reasoning models\n(GPT-5 / o-series). For those models set maxCompletionTokens instead.\nMutually exclusive with maxCompletionTokens.",
              "minimum": 1,
              "type": [
                "integer",
                "null"
              ]
            },
            "n": {
              "description": "N value",
              "type": [
                "integer",
                "null"
              ]
            },
            "organization": {
              "description": "Organization ID for the OpenAI API",
              "type": [
                "string",
                "null"
              ]
            },
            "presencePenalty": {
              "description": "Presence penalty",
              "type": [
                "string",
                "null"
              ]
            },
            "reasoningEffort": {
              "description": "Reasoning effort",
              "enum": [
                "none",
                "minimal",
                "low",
                "medium",
                "high",
                "xhigh"
              ],
              "type": [
                "string",
                "null"
              ]
            },
            "seed": {
              "description": "Seed value",
              "type": [
                "integer",
                "null"
              ]
            },
            "temperature": {
              "description": "Temperature for sampling",
              "type": [
                "string",
                "null"
              ]
            },
            "timeout": {
              "description": "Timeout",
              "type": [
                "integer",
                "null"
              ]
            },
            "tokenExchange": {
              "additionalProperties": false,
              "description": "TokenExchange configures dynamic bearer token acquisition via credential exchange.\nRequires apiKeySecret (used as the service account secret) and is mutually exclusive with apiKeyPassthrough.",
              "properties": {
                "gdchServiceAccount": {
                  "additionalProperties": false,
                  "description": "GDCHServiceAccountConfig holds GDCH-specific token exchange parameters.",
                  "properties": {
                    "audience": {
                      "description": "Audience is the token exchange audience URL (the GDC inference gateway base URL)",
                      "type": "string"
                    }
                  },
                  "required": [
                    "audience"
                  ],
                  "type": [
                    "object",
                    "null"
                  ]
                },
                "type": {
                  "description": "TokenExchangeType identifies the token exchange mechanism",
                  "enum": [
                    "GDCHServiceAccount"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "type"
              ],
              "type": [
                "object",
                "null"
              ]
            },
            "topP": {
              "description": "Top-p sampling parameter",
              "type": [
                "string",
                "null"
              ]
            }
          },
          "type": [
            "object",
            "null"
          ],
          "x-kubernetes-validations": [
            {
              "message": "maxTokens and maxCompletionTokens are mutually exclusive",
              "rule": "!(has(self.maxTokens) \u0026\u0026 has(self.maxCompletionTokens))"
            }
          ]
        },
        "provider": {
          "default": "OpenAI",
          "description": "The provider of the model",
          "enum": [
            "Anthropic",
            "OpenAI",
            "AzureOpenAI",
            "Ollama",
            "Gemini",
            "GeminiVertexAI",
            "AnthropicVertexAI",
            "Bedrock",
            "SAPAICore",
            "Foundry"
          ],
          "type": [
            "string",
            "null"
          ]
        },
        "sapAICore": {
          "additionalProperties": false,
          "description": "SAP AI Core-specific configuration",
          "properties": {
            "authUrl": {
              "description": "OAuth2 token endpoint URL (e.g., https://tenant.authentication.eu10.hana.ondemand.com)",
              "type": [
                "string",
                "null"
              ]
            },
            "baseUrl": {
              "description": "Base URL for the SAP AI Core API (e.g., https://api.ai.prod.eu-central-1.aws.ml.hana.ondemand.com)",
              "type": "string"
            },
            "resourceGroup": {
              "default": "default",
              "description": "Resource group in SAP AI Core",
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "baseUrl"
          ],
          "type": [
            "object",
            "null"
          ]
        },
        "tls": {
          "additionalProperties": false,
          "description": "TLS configuration for provider connections.\nEnables agents to connect to internal LiteLLM gateways or other providers\nthat use self-signed certificates or custom certificate authorities.",
          "properties": {
            "caCertSecretKey": {
              "description": "CACertSecretKey is the key within the Secret that contains the\nCA certificate data (PEM-encoded). Required when CACertSecretRef\nis set — admission rejects ref-without-key regardless of\nDisableVerify (see the TLSConfig-level XValidation rules).",
              "type": [
                "string",
                "null"
              ]
            },
            "caCertSecretRef": {
              "description": "CACertSecretRef is a reference to a Kubernetes Secret containing\nCA certificate(s) in PEM format. The Secret must be in the same\nnamespace as the resource referencing it (ModelConfig,\nRemoteMCPServer, or any future consumer of TLSConfig).\nWhen set, the certificate will be used to verify the upstream's\nSSL certificate.",
              "type": [
                "string",
                "null"
              ]
            },
            "disableSystemCAs": {
              "default": false,
              "description": "DisableSystemCAs disables the use of system CA certificates.\nWhen false (default), system CA certificates are used for verification (safe behavior).\nWhen true, only the custom CA from CACertSecretRef is trusted.\nThis allows strict security policies where only corporate CAs should be trusted.",
              "type": [
                "boolean",
                "null"
              ]
            },
            "disableVerify": {
              "default": false,
              "description": "DisableVerify disables SSL certificate verification entirely.\nWhen false (default), SSL certificates are verified.\nWhen true, SSL certificate verification is disabled.\nWARNING: This should ONLY be used in development/testing environments.\nProduction deployments MUST use proper certificates.",
              "type": [
                "boolean",
                "null"
              ]
            }
          },
          "type": [
            "object",
            "null"
          ],
          "x-kubernetes-validations": [
            {
              "message": "caCertSecretKey requires caCertSecretRef",
              "rule": "!(has(self.caCertSecretKey) \u0026\u0026 size(self.caCertSecretKey) \u003e 0 \u0026\u0026 (!has(self.caCertSecretRef) || size(self.caCertSecretRef) == 0))"
            },
            {
              "message": "caCertSecretRef requires caCertSecretKey",
              "rule": "!(has(self.caCertSecretRef) \u0026\u0026 size(self.caCertSecretRef) \u003e 0 \u0026\u0026 (!has(self.caCertSecretKey) || size(self.caCertSecretKey) == 0))"
            },
            {
              "message": "disableSystemCAs requires caCertSecretRef or disableVerify (trust-nothing config rejects every upstream)",
              "rule": "!(has(self.disableSystemCAs) \u0026\u0026 self.disableSystemCAs \u0026\u0026 (!has(self.disableVerify) || !self.disableVerify) \u0026\u0026 (!has(self.caCertSecretRef) || size(self.caCertSecretRef) == 0))"
            }
          ]
        }
      },
      "required": [
        "model"
      ],
      "type": [
        "object",
        "null"
      ],
      "x-kubernetes-validations": [
        {
          "message": "provider.openAI must be nil if the provider is not OpenAI",
          "rule": "!(has(self.openAI) \u0026\u0026 self.provider != 'OpenAI')"
        },
        {
          "message": "provider.anthropic must be nil if the provider is not Anthropic",
          "rule": "!(has(self.anthropic) \u0026\u0026 self.provider != 'Anthropic')"
        },
        {
          "message": "provider.azureOpenAI must be nil if the provider is not AzureOpenAI",
          "rule": "!(has(self.azureOpenAI) \u0026\u0026 self.provider != 'AzureOpenAI')"
        },
        {
          "message": "provider.ollama must be nil if the provider is not Ollama",
          "rule": "!(has(self.ollama) \u0026\u0026 self.provider != 'Ollama')"
        },
        {
          "message": "provider.gemini must be nil if the provider is not Gemini",
          "rule": "!(has(self.gemini) \u0026\u0026 self.provider != 'Gemini')"
        },
        {
          "message": "provider.geminiVertexAI must be nil if the provider is not GeminiVertexAI",
          "rule": "!(has(self.geminiVertexAI) \u0026\u0026 self.provider != 'GeminiVertexAI')"
        },
        {
          "message": "provider.anthropicVertexAI must be nil if the provider is not AnthropicVertexAI",
          "rule": "!(has(self.anthropicVertexAI) \u0026\u0026 self.provider != 'AnthropicVertexAI')"
        },
        {
          "message": "provider.bedrock must be nil if the provider is not Bedrock",
          "rule": "!(has(self.bedrock) \u0026\u0026 self.provider != 'Bedrock')"
        },
        {
          "message": "provider.sapAICore must be nil if the provider is not SAPAICore",
          "rule": "!(has(self.sapAICore) \u0026\u0026 self.provider != 'SAPAICore')"
        },
        {
          "message": "provider.foundry must be nil if the provider is not Foundry",
          "rule": "!(has(self.foundry) \u0026\u0026 self.provider != 'Foundry')"
        },
        {
          "message": "apiKeySecret must be set if apiKeySecretKey is set",
          "rule": "!(has(self.apiKeySecretKey) \u0026\u0026 !has(self.apiKeySecret))"
        },
        {
          "message": "apiKeySecretKey must be set if apiKeySecret is set (except for Bedrock and SAPAICore providers)",
          "rule": "!(has(self.apiKeySecret) \u0026\u0026 !has(self.apiKeySecretKey) \u0026\u0026 self.provider != 'Bedrock' \u0026\u0026 self.provider != 'SAPAICore')"
        },
        {
          "message": "apiKeyPassthrough and apiKeySecret are mutually exclusive",
          "rule": "!(has(self.apiKeyPassthrough) \u0026\u0026 self.apiKeyPassthrough \u0026\u0026 has(self.apiKeySecret) \u0026\u0026 size(self.apiKeySecret) \u003e 0)"
        },
        {
          "message": "apiKeyPassthrough must be false if provider is Gemini;GeminiVertexAI;AnthropicVertexAI",
          "rule": "!(has(self.apiKeyPassthrough) \u0026\u0026 self.apiKeyPassthrough \u0026\u0026 (self.provider == 'Gemini' || self.provider == 'GeminiVertexAI' || self.provider == 'AnthropicVertexAI'))"
        },
        {
          "message": "openAI.tokenExchange requires apiKeySecret (the service account secret)",
          "rule": "!(has(self.openAI) \u0026\u0026 has(self.openAI.tokenExchange) \u0026\u0026 (!has(self.apiKeySecret) || size(self.apiKeySecret) == 0))"
        },
        {
          "message": "openAI.tokenExchange and apiKeyPassthrough are mutually exclusive",
          "rule": "!(has(self.openAI) \u0026\u0026 has(self.openAI.tokenExchange) \u0026\u0026 has(self.apiKeyPassthrough) \u0026\u0026 self.apiKeyPassthrough)"
        },
        {
          "message": "openAI.tokenExchange type GDCHServiceAccount requires openAI.tokenExchange.gdchServiceAccount",
          "rule": "!(has(self.openAI) \u0026\u0026 has(self.openAI.tokenExchange) \u0026\u0026 self.openAI.tokenExchange.type == 'GDCHServiceAccount' \u0026\u0026 !has(self.openAI.tokenExchange.gdchServiceAccount))"
        }
      ]
    },
    "status": {
      "additionalProperties": false,
      "description": "ModelConfigStatus defines the observed state of ModelConfig.",
      "properties": {
        "conditions": {
          "items": {
            "additionalProperties": false,
            "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",
                  "null"
                ]
              },
              "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"
          },
          "type": [
            "array",
            "null"
          ]
        },
        "observedGeneration": {
          "format": "int64",
          "type": [
            "integer",
            "null"
          ]
        },
        "secretHash": {
          "description": "The secret hash stores a hash of any secrets required by the model config (i.e. api key, tls cert) to ensure agents referencing this model config detect changes to these secrets and restart if necessary.",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "type": [
        "object",
        "null"
      ]
    }
  },
  "type": "object"
}