Models
A model is a deployment that makes an LLM or an embedding model available through DIAL Core. Its entry tells Core where to send requests, which AI APIs it serves, who may use it, what it costs, and which interceptors process its traffic. Clients call it by its name, for example POST /openai/deployments/gpt-4o/chat/completions. This reference is for platform engineers who connect models; it assumes you know how DIAL Core is configured.
Where models are defined
| Source | Location |
|---|---|
| Config file | models.<name> |
| Configuration API | /v1/models/platform/<name> |
A model's name is a deployment ID, shared with applications, toolsets, and interceptors. DIAL Admin also manages models; see Models in DIAL Admin.
Fields
| Field | Description |
|---|---|
type | chat or embedding. Core uses it to choose the API endpoint and the payload schema. |
displayName | The name shown in DIAL clients, tables, and logs. |
displayVersion | The version shown next to the name, for example latest, beta, or a date. |
description | A short description of the model. |
intro | A short onboarding text shown to users separately from description. |
iconUrl | The URL of the icon shown for the model. |
descriptionKeywords | Keywords that describe the model, for example code-gen or text2image. |
author | The model's developer. |
createdAt, updatedAt | The dates the model was created and last updated. |
userRoles | The roles, from identity provider claims or API keys, that may use the model. When unset, every user may use it. |
endpoint | The adapter URL for Chat Completions or Embeddings, used as is. See Routing. |
responsesEndpoint | The adapter URL for the OpenAI Responses API, used as is. See Responses API. |
baseUrl | The root URL for every interfaces entry that declares no base_url. |
interfaces | The AI APIs the model serves, and what serves each one. See Interfaces. |
overrideName | Rewrites the request body's model field, and the X-DIAL-OVERRIDE-NAME header, to this value before the request reaches the adapter. It does not change routing. |
upstreams | The provider endpoints Core balances across. See Load balancing and upstreams. |
maxRetryAttempts | How many upstreams Core tries for one request. See Load balancing and upstreams. |
interceptors | The interceptors that process this model's requests and responses, in order. See Interceptors. |
forwardAuthToken | Forwards the caller's Authorization header to the model. Without it, Core strips that header. |
defaultHeaders | Headers Core adds to a request that does not carry them. See Default headers. |
defaults | Body parameters Core adds to a Chat Completions or Embeddings request that does not carry them. See Defaults. |
responsesDefaults | Body parameters Core adds to a Responses API request that does not carry them. |
features | Optional capabilities of the model. See Features. |
limits | Token limits of the model. See Limits. |
pricing | The cost of using the model, for cost tracking and cost limits. See Pricing. |
tokenizerModel | The model whose tokenization matches this one, usually the earliest model of a series, for example gpt-4-0314. For clients that tokenize on their side instead of calling the model's tokenize endpoint. |
embeddingDimensions | The size of the vector an embedding model returns, for example 1536. Omit for chat models. |
inputAttachmentTypes | The MIME types allowed for input attachments. |
maxInputAttachments | The maximum number of input attachments. Zero when inputAttachmentTypes is unset; otherwise unlimited by default. |
fieldsHashingOrder | Deprecated. Accepted for backward compatibility but has no effect. See Prompt cache pinning. |
Routing
A model declares its routing targets in one of two shapes. Both are fully supported; choose one per model. There is no migration between them, and declaring interfaces never removes the older fields.
endpointandresponsesEndpointare used as is: Core sends the request to the configured URL and does not append the path it received.- An
interfacesentry is served by a base URL: Core sends the request to the base URL plus the exact path it received. For example,POST /openai/v1/responsesgoes to<base_url>/openai/v1/responses. A trailing slash is normalized.
Interfaces
interfaces is a map keyed by the AI API the model serves:
| Interface | API |
|---|---|
openaiChatCompletions | OpenAI Chat Completions: chat/completions and completions under /openai/deployments/{name}. The peer of endpoint. |
openaiEmbeddings | OpenAI Embeddings: embeddings under /openai/deployments/{name}. |
openaiResponses | OpenAI Responses API. The peer of responsesEndpoint. |
anthropicMessages | Anthropic Messages: /anthropic/v1/messages and /anthropic/v1/messages/count_tokens. |
The map is a whitelist of what the model serves:
- A model-level
baseUrlalone declares no interface. - An interface listed with no base URL anywhere answers
503. - An interface mapped to
nullis the same as an absent one, so"openaiResponses": nulldocuments that the model does not serve the Responses API. openaiChatCompletionsandopenaiEmbeddingsnever stand in for each other. The olderendpointstill servesembeddingsrequests, so models configured before the split keep working.- When
interfacesand an older field both cover the same API,interfaceswins and the older field is ignored for routing.
Core resolves the URL that serves an interface in this order:
- The entry's own
base_url. - The model-level
baseUrl. A single root usually serves every interface, so declare it once and list the interfaces without their ownbase_url. - The translator, when the entry's
modeistranslator. A translated interface is served by its translator only. endpointorresponsesEndpoint, for an API theinterfacesmap does not declare.
Interface entry fields
| Field | Description |
|---|---|
base_url | The root URL the request path is appended to. Optional when the model has a baseUrl. |
mode | passthrough (default) forwards the request in the shape it arrived in. translator hands it to a translator that converts it into an API the model serves. |
translator | Required with mode: translator: the name of a translator, or an inline definition {"out": ..., "baseUrl": ...}. An interface is served by a base URL or by a translator, never both. |
defaultHeaders | Headers for this interface only, laid over the model-level defaultHeaders. |
features | Features for this interface only. See Features per interface. |
defaults | Body parameters for this interface only. They replace the model-level defaults for it. See Defaults. |
overridePaths | Upstream paths per operation that replace "base URL plus request path". See Override paths. |
{
"models": {
"gpt-5.4-mini": {
"type": "chat",
"overrideName": "gpt-5.4-mini",
"baseUrl": "http://model-provider:5000/compat/openai",
"interfaces": {
"openaiChatCompletions": { "mode": "passthrough" },
"openaiResponses": null,
"anthropicMessages": {
"mode": "translator",
"translator": "anthropicMessagesToOpenaiChatCompletions"
}
}
},
"text-embedding-3-small": {
"type": "embedding",
"interfaces": {
"openaiEmbeddings": { "base_url": "http://model-provider:5000/compat/openai" }
}
}
}
}
Override paths
overridePaths lets Core front a service that does not follow the DIAL path contract. Each key names a Core operation, and its value is the path appended to the base URL instead of the request path.
| Key | Core operation |
|---|---|
postAzureOpenaiChatCompletions | POST /openai/deployments/{id}/chat/completions |
postAzureOpenaiEmbeddings | POST /openai/deployments/{id}/embeddings |
postOpenaiResponses | POST /openai/v1/responses |
getOpenaiResponsesById | GET /openai/v1/responses/{id} |
deleteOpenaiResponsesById | DELETE /openai/v1/responses/{id} |
postOpenaiResponsesCancel | POST /openai/v1/responses/{id}/cancel |
postAnthropicMessages | POST /anthropic/v1/messages |
postAnthropicMessagesCountTokens | POST /anthropic/v1/messages/count_tokens |
- A key belongs under the interface that owns it. A known key under another interface is rejected; an unknown key is ignored.
- Operations without an override keep the default routing, and query strings are appended as usual.
- Two tokens are substituted, by their exact spelling:
{id}and{overrideName}. Any other text, braces included, is sent as written, so{Id}reaches the upstream literally. {id}is the deployment name for the Chat Completions and Embeddings operations, and the response ID for the Responses item operations. Other operations carry no ID, so{id}there is rejected.{overrideName}is the URL-encodedoverrideName, or the deployment name when none is set.overridePathsdoes not apply toendpointorresponsesEndpoint, and is rejected on atranslatorinterface.override_pathsis accepted as an alias.
"interfaces": {
"openaiChatCompletions": {
"overridePaths": { "postAzureOpenaiChatCompletions": "/v1/chat/completions" }
}
}
With baseUrl https://dm-switchyard/, a request to /openai/deployments/gpt_switchyard/chat/completions goes to https://dm-switchyard/v1/chat/completions.
Responses API
When a model serves the OpenAI Responses API, through responsesEndpoint or interfaces.openaiResponses, Core proxies these operations:
POST /openai/v1/responses— create a response, streaming or not, including background mode.GET /openai/v1/responses/{id}— retrieve a response by its DIAL ID, with streaming over SSE.DELETE /openai/v1/responses/{id}— delete a response and its stored ID mapping.POST /openai/v1/responses/{id}/cancel— cancel a background response that is in progress.
Core rewrites upstream response IDs to stable resp_dial_* IDs and routes follow-up requests to the upstream that handled the original one, so each upstream needs an id. previous_response_id, conversations, prompts, and files are not supported. For the API support of each adapter, see AI API overview.
Default headers
defaultHeaders is a map of header names and values that Core adds to a request without a header of that name. Names match case-insensitively.
- A header sent by the client wins, and so does one Core sets itself, such as
Api-Key,X-UPSTREAM-*, orX-DIAL-DEPLOYMENT-ID. - A default header behaves as if the client had sent it. Core reads it, so
X-DIAL-CACHE-POLICYset this way drives upstream cache pinning, and forwards it under the same rules. A header Core strips on the way to the model is stripped from the defaults too: hop-by-hop headers,Api-Keyandx-api-key,traceparentandtracestate, andAuthorizationunlessforwardAuthTokenis set. - Model-level headers apply to every interface.
interfaces.<type>.defaultHeadersoverrides a name it repeats and adds new names, for that interface only. - With interceptors, the defaults are applied on the hop to the first interceptor and travel down the chain. An interceptor's own
defaultHeaderswin on the hop that calls it.
Defaults
Defaults are body parameters that fill in what a request leaves out. A parameter the request carries is never replaced. Unlike headers, model-level defaults are not shared across APIs, and the two levels are not merged:
| Interface | Model-level fallback | Interface-level, when declared |
|---|---|---|
openaiChatCompletions | defaults | interfaces.openaiChatCompletions.defaults |
openaiEmbeddings | defaults | interfaces.openaiEmbeddings.defaults |
openaiResponses | responsesDefaults | interfaces.openaiResponses.defaults |
anthropicMessages | None | interfaces.anthropicMessages.defaults |
An interface entry that declares defaults states the whole set for that interface; the model-level fallback applies only where the entry declares none. defaults and responsesDefaults hold OpenAI parameters, so neither reaches an Anthropic request.
Features
Features declare optional capabilities, so Core and DIAL clients turn behavior on when the model supports it and off when it does not. Endpoint features point Core at specialized adapter endpoints.
| Feature | Default | Description |
|---|---|---|
rateEndpoint | — | The URL of the model's rating API. Core exposes it as <deployment name>/rate. |
tokenizeEndpoint | — | The URL of a tokenization service, for exact token counts. Core exposes it as <deployment name>/tokenize. Models without built-in tokenization need it. |
truncatePromptEndpoint | — | The URL of a prompt truncation API that cuts a prompt to the context length. Core exposes it as <deployment name>/truncate_prompt. |
configurationEndpoint | — | The URL of a JSON Schema for the model's settings. Core exposes it as GET /v1/deployments/<deployment name>/configuration; clients send matching values in custom_fields.configuration. |
systemPromptSupported | true | Whether the model accepts a system message. |
toolsSupported | false | Whether the model accepts tools (function calling). |
seedSupported | false | Whether the model accepts seed for reproducible output. |
urlAttachmentsSupported | false | Whether the model accepts URLs as attachments. |
folderAttachmentsSupported | false | Whether the model accepts folders as attachments. |
accessibleByPerRequestKey | true | Whether applications can call the model with a per-request API key. |
contentPartsSupported | false | Whether the model accepts requests with content parts. |
maxTokensSupported | true | Whether the upstream accepts the older max_tokens parameter in Chat Completions. |
maxCompletionTokensSupported | false | Whether the upstream accepts max_completion_tokens in Chat Completions. |
customTemperatureSupported | true | Whether any temperature value is accepted. When false, clients should not send temperature. |
cacheSupported | false | Whether the model supports prompt caching. |
autoCachingSupported | false | Whether the model supports automatic caching where possible. |
parallelToolCallsSupported | true | Whether the model accepts parallel_tool_calls in Chat Completions. |
assistantAttachmentsInRequestSupported | false | Whether the model accepts DIAL attachments in assistant messages, for example an image-editing model. When true, DIAL Chat keeps those attachments instead of removing them. |
supportCommentInRateResponse | — | Whether the model accepts a comment in the rate payload. |
reasoningEfforts | [] | The effort values the model accepts in Chat Completions, for example low, medium, high. An empty list means effort is not supported. |
Features per interface
interfaces.<type>.features overrides model-level features for one interface, field by field:
- The interface's value, when it is not
null. - The model-level value.
- Core's default.
An explicit false overrides true, and an array replaces the inherited array, so "reasoning_efforts": [] clears it. Snake case and camel case names are both accepted. Core sends the effective features to the adapter in X-DIAL-DEPLOYMENT-FEATURES, and uses the requested interface's features for caching, per-request key access, and consent checks.
"features": { "tools_supported": true, "reasoning_efforts": ["low", "medium", "high"] },
"interfaces": {
"openaiChatCompletions": { "mode": "passthrough" },
"anthropicMessages": {
"mode": "passthrough",
"features": { "reasoning_efforts": ["low", "medium", "high", "xhigh", "max"] }
}
}
Limits
| Field | Description |
|---|---|
maxPromptTokens | The maximum tokens in a request. |
maxCompletionTokens | The maximum tokens in a response. |
maxTotalTokens | The maximum tokens in a request and its response together. Set either this or the two fields above. |
These are the model's own limits. Usage limits per user or key are set on Roles.
Pricing
Pricing lets Core estimate cost in real time and enforce cost limits.
| Field | Description |
|---|---|
unit | token counts every token sent or received. char_without_whitespace counts only non-whitespace characters. none turns cost tracking off for the model. |
prompt | The cost per unit of the prompt, as a string. |
completion | The cost per unit of the completion, as a string. |
cacheRead, cacheWrite | With unit: token only. The cost per cache-read and cache-write token. Unset, cache tokens are billed at the prompt rate. |
A rate can be a flat string or a decision tree that picks a rate from the call's own usage. A tree tests a field, which is a standard name (cachedReadTokens, cachedWriteTokens, promptTokens, serviceTier, ttl) or a JSON Path that starts with $. Decision trees for prompt and completion rates are supported since DIAL Core 0.49.0.
"pricing": {
"unit": "token",
"prompt": "0.000003",
"completion": "0.000015",
"cacheRead": "0.0000003",
"cacheWrite": {
"test": { "field": "ttl", "operator": "==", "value": "1h" },
"ifTrue": "0.000006",
"ifFalse": "0.00000375"
}
}
Example
{
"models": {
"gpt-4o": {
"type": "chat",
"displayName": "GPT-4o",
"endpoint": "http://model-provider:5000/compat/openai/openai/deployments/gpt-4o/chat/completions",
"upstreams": [
{ "endpoint": "https://<RESOURCE_1>.openai.azure.com/openai/deployments/gpt-4o/chat/completions", "key": "<API_KEY_1>" },
{ "endpoint": "https://<RESOURCE_2>.openai.azure.com/openai/deployments/gpt-4o/chat/completions", "key": "<API_KEY_2>", "tier": 1 }
],
"maxRetryAttempts": 2,
"userRoles": ["analyst"],
"inputAttachmentTypes": ["image/png", "image/jpeg"],
"maxInputAttachments": 10,
"features": { "toolsSupported": true, "seedSupported": true },
"limits": { "maxPromptTokens": 128000, "maxCompletionTokens": 16384 },
"pricing": { "unit": "token", "prompt": "0.0000025", "completion": "0.00001" },
"interceptors": ["pii-redaction"]
}
}
}
Further reading
- Load balancing and upstreams — spread a model's traffic over several provider endpoints
- DIAL Core configuration: Translators — serve an AI API the model does not speak
- DIAL Admin: Models — register models and set their endpoints in DIAL Admin
- DIAL Model Provider — the service that runs the OpenAI, Bedrock, and Vertex AI adapters
- Migrate from the standalone adapters — move models to DIAL Model Provider with
interfaces