Migrate from the standalone adapters
Move a DIAL deployment from the standalone OpenAI, Bedrock, Vertex AI, and DIAL-to-DIAL adapters to DIAL Model Provider. This guide is for platform engineers who maintain the DIAL Core configuration. It assumes you know how a model declares interfaces and how upstreams work. It is checked against DIAL Model Provider 0.1.0-rc.0 and DIAL Core 0.49.4.
Prerequisites
- The environment variables of every standalone adapter you run.
- Access to the DIAL Core configuration: the config file, the Configuration API, or DIAL Admin.
How routing changes
The migrated models use interfaces instead of endpoint. A model's baseUrl becomes the DIAL Model Provider root of its adapter:
| Standalone adapter | Model baseUrl with DIAL Model Provider |
|---|---|
http://adapter-openai:5000 | http://model-provider:5000/compat/openai |
http://adapter-vertexai:5000 | http://model-provider:5000/compat/vertexai |
http://adapter-bedrock:5000 | http://model-provider:5000/compat/bedrock |
http://adapter-dial:5000 | http://model-provider:5000/compat/dial |
endpoint is a complete URL that Core uses as is, so it carried the adapter's deployment ID in its path. An interfaces entry works differently. Core appends the path it received to the base URL, and rewrites the /deployments/<id>/ segment to the model's overrideName, or to the model name when none is set. So when the deployment ID in the old endpoint differs from the model name, set overrideName to that ID.
Step 1: Deploy DIAL Model Provider
- Merge the environment variables of your standalone adapters into one environment. Check the shared variables: a variable that several adapters read now takes one value for all of them. If the Bedrock adapter used
DEFAULT_REGION, rename it toAWS_DEFAULT_REGION; see Region variables. - Deploy the
epam/ai-dial-model-provider:0.1.0-rc.0image next to the standalone adapters. See Deployment. - Check that
GET http://<MODEL_PROVIDER_HOST>:5000/healthanswers{"status": "ok"}.
The standalone adapters keep serving traffic until you change the models.
Step 2: Rewrite each model
For each model whose endpoint points at a standalone adapter:
- Remove
endpointandresponsesEndpoint. - Set
baseUrlto the DIAL Model Provider root of its adapter, from the table above. - Declare the APIs the model serves under
interfaces. An empty entry,{}, is a pass-through interface served by the model'sbaseUrl. - Set
overrideNameto the deployment ID from the oldendpointpath, when it differs from the model name.
| Old field | Interface |
|---|---|
endpoint on a chat model | openaiChatCompletions |
endpoint on an embedding model | openaiEmbeddings |
responsesEndpoint | openaiResponses |
openaiChatCompletions and openaiEmbeddings never stand in for each other, so declare openaiEmbeddings for an embedding model. A model that already serves an interface through its own base_url, such as anthropicMessages, keeps the entry: change its base_url to the matching /compat/<adapter> root.
Step 3: Rewrite the upstreams
For each upstream of a migrated model:
- Give the upstream an
id. Core rejects a model whose upstream declaresinterfaceswithout one. - Move
endpointtointerfaces.<interface>.endpoint, andresponsesEndpointtointerfaces.openaiResponses.endpoint. - Keep
key,extraData, andsecretExtraDataon the upstream. Every interface entry inherits them unless it sets its own.
Core passes the URL of the requested interface to the adapter in the X-UPSTREAM-ENDPOINT header, as it does for endpoint. A model without upstreams, such as the Bedrock and Vertex AI models in the example, needs no change here.
Warning
Feature calls (
tokenize,truncate_prompt, andconfiguration) send the adapter the first upstream's top-levelendpoint, not itsinterfaces. The OpenAI adapter's feature endpoints fail without it. On a model that setsfeatures.tokenizeEndpoint,features.truncatePromptEndpoint, orfeatures.configurationEndpoint, keependpointon its upstreams as well.
Step 4: Repoint feature endpoints and translators
These fields are complete URLs, so insert the /compat/<adapter> prefix after the host:
| Field | Before | After |
|---|---|---|
features.tokenizeEndpoint | http://adapter-openai:5000/openai/deployments/gpt-4o/tokenize | http://model-provider:5000/compat/openai/openai/deployments/gpt-4o/tokenize |
features.truncatePromptEndpoint, features.configurationEndpoint, features.rateEndpoint | http://adapter-<adapter>:5000/… | http://model-provider:5000/compat/<adapter>/… |
Translator baseUrl | http://adapter-bedrock:5000/openaiChatCompletions | http://model-provider:5000/compat/bedrock/openaiChatCompletions |
See Features and Translators.
Example
Three models before the migration, on the standalone adapters:
{
"models": {
"gpt-4o": {
"type": "chat",
"endpoint": "http://adapter-openai:5000/openai/deployments/gpt-4o/chat/completions",
"upstreams": [
{
"endpoint": "https://contoso.openai.azure.com/openai/deployments/gpt-4o/chat/completions",
"key": "<AZURE_OPENAI_KEY>"
}
]
},
"gemini-2.5-pro": {
"type": "chat",
"endpoint": "http://adapter-vertexai:5000/openai/deployments/gemini-2.5-pro/chat/completions"
},
"anthropic.claude-sonnet-4-5": {
"type": "chat",
"endpoint": "http://adapter-bedrock:5000/openai/deployments/anthropic.claude-sonnet-4-5-20250929-v1:0/chat/completions"
}
}
}
The same models after the migration, on DIAL Model Provider with interfaces:
{
"models": {
"gpt-4o": {
"type": "chat",
"baseUrl": "http://model-provider:5000/compat/openai",
"interfaces": {
"openaiChatCompletions": {}
},
"upstreams": [
{
"id": "contoso",
"key": "<AZURE_OPENAI_KEY>",
"interfaces": {
"openaiChatCompletions": {
"endpoint": "https://contoso.openai.azure.com/openai/deployments/gpt-4o/chat/completions"
}
}
}
]
},
"gemini-2.5-pro": {
"type": "chat",
"baseUrl": "http://model-provider:5000/compat/vertexai",
"interfaces": {
"openaiChatCompletions": {}
}
},
"anthropic.claude-sonnet-4-5": {
"type": "chat",
"overrideName": "anthropic.claude-sonnet-4-5-20250929-v1:0",
"baseUrl": "http://model-provider:5000/compat/bedrock",
"interfaces": {
"openaiChatCompletions": {}
}
}
}
}
Chat Completions requests for these models go to:
| Model | DIAL Model Provider URL |
|---|---|
gpt-4o | http://model-provider:5000/compat/openai/openai/deployments/gpt-4o/chat/completions |
gemini-2.5-pro | http://model-provider:5000/compat/vertexai/openai/deployments/gemini-2.5-pro/chat/completions |
anthropic.claude-sonnet-4-5 | http://model-provider:5000/compat/bedrock/openai/deployments/anthropic.claude-sonnet-4-5-20250929-v1:0/chat/completions |
The Bedrock model name differs from its Bedrock model ID, so overrideName carries the ID.
Result
Send a request through DIAL Core for each migrated model:
curl -X POST "http://0.0.0.0:8080/openai/deployments/gpt-4o/chat/completions" \
-H "Api-Key: <DIAL_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "What is 2 + 3?"}]}'
When every model answers, stop the standalone adapter containers.
| Symptom | What to check |
|---|---|
| Core rejects the model | Each interface needs a base URL: its own base_url or the model's baseUrl. Each upstream that declares interfaces needs an id. |
The Bedrock adapter answers 404 | The deployment segment carries the model name, not the Bedrock model ID. Set overrideName. |
A tokenize or truncate call fails with X-UPSTREAM-ENDPOINT header is missing | Keep the top-level endpoint on the model's upstreams. See Step 3. |
Requests fail with Connection was closed | TIMEOUT_KEEP_ALIVE is not above DIAL Core's client.keepAliveTimeout. See Keep-alive timeout. |
Further reading
- DIAL Model Provider configuration — shared variables and process settings
- DIAL Core configuration: Models — how
endpointandinterfacesroute a request - Load balancing and upstreams — per-interface provider URLs on an upstream
- DIAL Core configuration: Translators — serve an AI API a model does not speak