Model
A Model defines an AI language model endpoint that agents call. Each model names a provider (the backend client), a model identifier, and a provider-specific config block holding the base URL, credentials, and generation properties. Agents reference a model by name via modelRef, falling back to the model named default when none is set. For a task-oriented walkthrough see User Guide → Configure models; this page is the field-by-field reference.
Spec
apiVersion: ark.mckinsey.com/v1alpha1
kind: Model
metadata:
name: default
spec:
# --- Required ----------------------------------------------------------
provider: openai # openai | azure | bedrock | anthropic
model:
value: gpt-4o # model identifier (ValueSource)
config: # exactly one provider block below
openai:
baseUrl:
value: "https://api.openai.com/v1"
apiKey:
valueFrom:
secretKeyRef:
name: default-model-token
key: token
# --- Common optional fields --------------------------------------------
type: completions # DEPRECATED selector; default 'completions'
pollInterval: 1m # health-probe interval (default '1m')Fields
| Field | Type | Required | Description |
|---|---|---|---|
spec.provider | enum (openai, azure, bedrock, anthropic) | yes | Selects the backend client. This is the authoritative selector — the matching config.<provider> block must be present. |
spec.model | ValueSource | yes | The model identifier (e.g. gpt-4o, us.anthropic.claude-3-5-haiku-20241022-v1:0). Supports value or valueFrom (secretKeyRef, configMapKeyRef, serviceRef, queryParameterRef). |
spec.config | ModelConfig | yes | Provider-specific configuration. Holds exactly one of openai, azure, bedrock, anthropic, matching spec.provider. |
spec.type | enum (completions, openai, azure, bedrock, anthropic) | no | Deprecated. Default completions. Legacy provider values (openai, azure, bedrock) are migrated to spec.provider by the mutating webhook. Use spec.provider instead — spec.type will be removed in release 1.0. |
spec.pollInterval | duration | no | How often the controller probes the model for health. Defaults to 1m. |
Provider config fields
spec.config carries one block keyed by provider. Every credential/URL field is a ValueSource (direct value or valueFrom a Secret, ConfigMap, service, or query parameter).
| Provider block | Field | Type | Required | Description |
|---|---|---|---|---|
config.openai | baseUrl | ValueSource | yes | API endpoint URL. |
apiKey | ValueSource | yes | API key. Store in a Secret. | |
headers[] | []Header | no | Custom HTTP headers. | |
properties | map[string]ValueSource | no | Generation parameters (temperature, max_tokens, …). | |
config.azure | baseUrl | ValueSource | yes | Azure OpenAI resource URL. |
auth | AzureAuth | no | Exactly one of apiKey, managedIdentity, workloadIdentity. | |
apiKey | ValueSource | no | Deprecated — use auth.apiKey. Accepted when auth is unset. | |
apiVersion | ValueSource | no | Azure API version (e.g. 2024-12-01-preview). | |
headers[] | []Header | no | Custom HTTP headers. | |
properties | map[string]ValueSource | no | Generation parameters. | |
config.bedrock | region | ValueSource | no | AWS region. |
baseUrl | ValueSource | no | Override endpoint (defaults to the AWS Bedrock endpoint). | |
accessKeyId | ValueSource | no | Explicit credential (defaults to the IAM role). | |
secretAccessKey | ValueSource | no | Explicit credential. | |
sessionToken | ValueSource | no | Temporary-credential / JWT token. | |
modelArn | ValueSource | no | Custom model ARN. | |
maxTokens | int (1–100000) | no | Max response tokens. | |
temperature | string (0–1) | no | Sampling temperature, as a string. | |
properties | map[string]ValueSource | no | Generation parameters. | |
config.anthropic | baseUrl | ValueSource | yes | Anthropic API URL. |
apiKey | ValueSource | yes | API key. Store in a Secret. | |
version | ValueSource | no | Anthropic API version header. | |
headers[] | []Header | no | Custom HTTP headers. | |
properties | map[string]ValueSource | no | Generation parameters. |
Providers
OpenAI
The openai provider supports any OpenAI-specification-compatible endpoint, including OpenAI itself and OpenAI-compatible gateways.
apiVersion: ark.mckinsey.com/v1alpha1
kind: Model
metadata:
name: default
spec:
provider: openai
type: completions # legacy; defaults to 'completions'
model:
value: gpt-4o
config:
openai:
baseUrl:
value: "https://api.openai.com/v1"
# Store the key in a Secret rather than inline.
apiKey:
valueFrom:
secretKeyRef:
name: default-model-token
key: token
properties:
temperature:
value: "0.7"
max_tokens:
value: "4096"
---
apiVersion: v1
kind: Secret
metadata:
name: default-model-token
type: Opaque
stringData:
token: "your-api-key-here"Create the API-key Secret directly with:
kubectl create secret generic default-model-token --from-literal=token="your-api-key-here"Azure OpenAI
Azure models support three authentication methods via config.azure.auth: API Key (default), Managed Identity (AKS node identity), and Workload Identity (Kubernetes ServiceAccount federated to Azure). Set exactly one.
API Key (explicit or legacy):
apiVersion: ark.mckinsey.com/v1alpha1
kind: Model
metadata:
name: gpt-4o-mini
spec:
provider: azure
type: completions
model:
value: gpt-4o-mini
config:
azure:
baseUrl:
value: "https://your-resource.openai.azure.com"
auth:
apiKey:
valueFrom:
secretKeyRef:
name: azure-openai-key
key: token
apiVersion:
value: "2024-12-01-preview"The top-level config.azure.apiKey field still works but is deprecated in favour of config.azure.auth.apiKey.
Managed Identity (AKS): Use when Ark runs on AKS and the cluster or node pool has a User-Assigned Managed Identity with access to the Azure OpenAI resource. No API key is stored on the cluster.
apiVersion: ark.mckinsey.com/v1alpha1
kind: Model
metadata:
name: gpt-4o-managed-identity
spec:
provider: azure
model:
value: gpt-4o
config:
azure:
baseUrl:
value: "https://your-resource.openai.azure.com"
apiVersion:
value: "2024-02-15-preview"
auth:
managedIdentity: {}
# Or with a user-assigned identity:
# managedIdentity:
# clientId:
# value: "12345678-1234-1234-1234-123456789abc"Workload Identity: Use when running on any Kubernetes cluster (including non-Azure) with Azure Workload Identity configured. The pod’s ServiceAccount is federated to an Azure Managed Identity. Both clientId and tenantId are required.
apiVersion: ark.mckinsey.com/v1alpha1
kind: Model
metadata:
name: gpt-4o-workload-identity
spec:
provider: azure
model:
value: gpt-4o
config:
azure:
baseUrl:
value: "https://your-resource.openai.azure.com"
apiVersion:
value: "2024-02-15-preview"
auth:
workloadIdentity:
clientId:
value: "12345678-1234-1234-1234-123456789abc"
tenantId:
value: "87654321-4321-4321-4321-210987654321"AWS Bedrock
apiVersion: ark.mckinsey.com/v1alpha1
kind: Model
metadata:
name: claude-haiku
spec:
provider: bedrock
type: completions
model:
value: "us.anthropic.claude-3-5-haiku-20241022-v1:0"
config:
bedrock:
# AWS region (optional).
region:
value: "us-west-2"
# Base URL (optional — only needed for a non-default endpoint).
baseUrl:
value: "https://aws-bedrock.prod.ai-gateway.quantumblack.com/your-project-id"
# API key (bearer token) - alternative to IAM credentials.
# When set, it takes precedence and IAM credentials are ignored.
apiKey:
valueFrom:
secretKeyRef:
name: bedrock-credentials
key: bedrock-api-key
# Explicit credentials (optional, defaults to IAM role)
accessKeyId:
valueFrom:
secretKeyRef:
name: aws-credentials
key: access-key-id
secretAccessKey:
valueFrom:
secretKeyRef:
name: aws-credentials
key: secret-access-key
# Session token for temporary credentials or JWT tokens.
sessionToken:
valueFrom:
secretKeyRef:
name: aws-credentials
key: session-token
# Custom model ARN (optional).
modelArn:
value: "arn:aws:bedrock:..."
properties:
temperature:
value: "0.7"
max_tokens:
value: "4096"Bedrock supports two authentication methods:
- API key (
apiKey) — a Bedrock bearer token. The executor authenticates withAuthorization: Bearer <key>, bypassing SigV4 signing. - IAM credentials (
accessKeyId/secretAccessKey/sessionToken) — or, if all are omitted, the pod’s IAM role via the AWS default credential chain.
When both apiKey and IAM credentials are set, the API key takes precedence and the IAM credentials are ignored, even when IAM credentials are also present in the executor environment. The mutating webhook stamps a non-blocking ark.mckinsey.com/migration-warning/bedrock-auth annotation in this case. A configured apiKey that cannot be resolved (missing Secret or empty value) fails loudly rather than silently falling back to IAM.
Google Gemini and Anthropic Models
Both Google Gemini and Anthropic provide OpenAI-compatible endpoints, allowing you to use their models with the openai provider. The base URLs are:
https://generativelanguage.googleapis.com/v1beta/openaifor Google Geminihttps://api.anthropic.com/v1for Anthropic Claude
Most other providers also support OpenAI compatible base URLs - check their docs for details.
Anthropic
The anthropic provider talks to the Anthropic Messages API natively — you do not need an OpenAI-compatible endpoint. The completions executor converts between Ark’s internal message format and the Messages API (including tool use and system prompts), so you point it straight at Anthropic’s own API:
apiVersion: ark.mckinsey.com/v1alpha1
kind: Model
metadata:
name: claude
spec:
provider: anthropic
model:
value: claude-3-5-sonnet-20241022
config:
anthropic:
baseUrl:
value: "https://api.anthropic.com/v1" # the native Messages API endpoint
apiKey:
valueFrom:
secretKeyRef:
name: anthropic-key
key: token
version:
value: "2023-06-01" # optional; sets the anthropic-version headerThe optional version field sets the anthropic-version request header. This provider works with any Messages-API-compatible endpoint, including Anthropic direct and gateways that expose the Messages API.
Anthropic also publishes an OpenAI-compatible endpoint, so if you prefer you can reach it through the openai provider with baseUrl: https://api.anthropic.com/v1 instead — but the native anthropic provider is the recommended path for Claude.
Google Gemini
Google Gemini has no dedicated provider — reach it through the openai provider against Gemini’s OpenAI-compatible endpoint:
https://generativelanguage.googleapis.com/v1beta/openai— Google Gemini
Most other providers publish OpenAI-compatible base URLs too — check their docs.
Model properties
Every provider block supports a properties map for generation parameters. Values are passed through to the underlying chat-completion call.
spec:
provider: openai
model:
value: gpt-4o
config:
openai:
baseUrl:
value: "https://api.openai.com/v1"
apiKey:
valueFrom:
secretKeyRef:
name: openai-secret
key: token
properties:
temperature:
value: "0.1"
max_tokens:
value: "1000"Any OpenAI ChatCompletion parameter is accepted, including temperature, max_tokens, top_p, frequency_penalty, presence_penalty, stop, and seed.
Custom HTTP headers
The openai, azure, and anthropic provider blocks accept headers[] for advanced authentication and routing. Each header value is a direct value or loaded valueFrom a Secret or ConfigMap.
apiVersion: ark.mckinsey.com/v1alpha1
kind: Model
metadata:
name: gateway-model
spec:
provider: azure
type: completions
model:
value: gpt-4o
config:
azure:
baseUrl:
value: "https://your-resource.openai.azure.com"
auth:
apiKey:
valueFrom:
secretKeyRef:
name: azure-openai-key
key: token
apiVersion:
value: "2024-12-01-preview"
headers:
# Direct value.
- name: X-Client-ID
value:
value: "production-client"
# From a Secret.
- name: X-API-Gateway-Key
value:
valueFrom:
secretKeyRef:
name: gateway-credentials
key: api-key
# From a ConfigMap.
- name: User-Agent
value:
valueFrom:
configMapKeyRef:
name: app-config
key: user-agentStatus
status:
resolvedAddress: "https://api.openai.com/v1"
conditions:
- type: ModelAvailable
status: "True"
reason: Available
message: "Model is available and probed successfully"
lastTransitionTime: "2026-01-15T10:30:00Z"The controller probes each model every spec.pollInterval and records the result in the ModelAvailable condition.
Status fields
| Field | Description |
|---|---|
status.resolvedAddress | The resolved base URL the controller reached during the health probe. |
status.conditions[] | Standard Kubernetes conditions. ModelAvailable reflects the health probe. |
ModelAvailable states:
| Status | Reason | Meaning |
|---|---|---|
True | Available | Model responded to the probe successfully. |
False | ModelProbeFailed | Probe failed (network, authentication, or configuration error) — details in message. |
Unknown | Initializing | Initial state before the first probe completes. |
Print columns
kubectl get models prints:
| Column | Source |
|---|---|
NAME | metadata.name |
TYPE | .spec.type |
PROVIDER | .spec.provider |
MODEL | .spec.model.value |
AVAILABLE | ModelAvailable condition status |
AGE | metadata.creationTimestamp |
kubectl get models
NAME TYPE PROVIDER MODEL AVAILABLE AGE
default completions azure gpt-4.1-mini True 5m
claude-haiku completions bedrock claude-3-haiku False 3mUse kubectl describe model <name> for the full condition message.
Migration: type → provider
spec.provider is the current backend selector; spec.type is deprecated. For backward compatibility, when spec.provider is empty and spec.type holds a legacy provider value (openai, azure, or bedrock), the mutating webhook copies it into spec.provider, resets spec.type to completions, and stamps an ark.mckinsey.com/migration-warning-provider annotation. A model with neither spec.provider nor a migratable spec.type is rejected with provider is required. Set spec.provider explicitly and leave spec.type at its completions default (or omit it).
Related
- Agents — reference a model via
spec.modelRef. - Query — target a model directly with
target.type: model. - Secrets & authentication — storing API keys and credentials for model config.