Model or dataset
epam/ai-dial-core avatar
epam/ai-dial-core

DIAL Core puts one HTTP endpoint in front of many chat and embedding models

The main component of AI DIAL, which provides unified API to different chat completion and embedding models, assistants, and applications

663 stars43 forksJavaApache-2.0

At a glance

What is it?
epam/ai-dial-core is a Java 21 HTTP proxy that gives chat completion and embedding models a single REST surface, with an OpenAPI contract, hot reloaded configuration and a Helm chart for Kubernetes. It is a gateway first, and it assumes you already have model backends to point it at.
Who is it for?
DIAL Core fits teams that already run several model backends and want one documented REST surface in front of them, and it fits Kubernetes shops that would rather consume the dial-core Helm chart than hand-roll a service. It does not fit a team that wants a hosted chat product, a no credential setup path, or a guarantee of stable preview endpoints, since endpoints marked x-preview: true carry no backward compatibility promise.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

DIAL Core is a proxy layer, not a model host

The scope is narrow and worth stating up front. The project documentation describes DIAL Core as an HTTP proxy that provides a unified API to different chat completion and embedding models and applications. The repository description adds assistants and applications to that list. What is not in scope is hosting the models. The point is the translation layer between clients that expect a stable contract and backends that speak different dialects. That makes the target user a platform team with more than one model endpoint to expose, not an application developer who simply wants to call one model. The stack underneath is specific: Java 21 on Eclipse Vert.x, which is where the event loop and the HTTP server live. The Docker image confirms the runtime choices, since the builder stage is gradle:8.10-jdk21-alpine and the runtime stage is eclipse-temurin:21-jdk-alpine. Two ports are exposed, 8080 and 9464, and the health check probes the first of them.

dockerfile
EXPOSE 8080 9464

The container runs as a non root user created with adduser, and the entrypoint is a script named docker-entrypoint.sh rather than the jar directly, which gives you a place to inject configuration at start time.

The OpenAPI spec is generated, so editing it by hand is pointless

DIAL Core exposes an OpenAPI specification that describes all available REST endpoints, request and response models, and common error responses. The important detail is provenance. The specification is generated automatically from the source code using the openapi-generator module, and the documentation warns against editing the generated OpenAPI files by hand because changes will be overwritten during the next generation. The repository layout backs this up: there are separate openapi-annotations/ and openapi-generator/ directories, so the contract lives in two halves, annotations in code and generation into docs/. The published artefact is an OpenAPI 3.0 file at docs/open_api_core.yaml on the development branch. Endpoints that are still under development carry a vendor extension, x-preview: true, and the documentation states plainly that such endpoints are experimental and may change or be removed in future releases without backward compatibility guarantees. If you are generating a client from the spec, that marker is the one field worth reading before you pin a version.

yaml
x-preview: true

Building needs GitHub package credentials before anything compiles

The build has an unusual dependency on GitHub Packages. DIAL Core depends on GitHub packages of JClouds, and the documentation explains the reason: GitHub does not provide anonymous access to packages. That forces every builder to authenticate. The Gradle build expects two environment variables, GPR_USERNAME for a GitHub username and GPR_PASSWORD for a GitHub personal access token, and the token needs the read:packages permission. The token can also be passed as Gradle project properties gpr.user and gpr.key. The Dockerfile shows the same requirement expressed for container builds, where the credentials are mounted as build secrets rather than baked into the image.

bash
./gradlew build

The Dockerfile passes the extra flag -PdisableCompression=true and skips the test task with -x test inside its builder stage. That is a packaging choice for the image, and it does not tell you what the plain build does. The build itself needs Java 21 and the Gradle wrapper that ships in the repository.

Running locally means one Gradle task and an IDE entry point

The quickest first look is the run task.

bash
./gradlew :server:run

Alternatively the documentation points you at a specific class, com.epam.aidial.core.server.AiDial, which you can launch from an IDE of your choice. That naming tells you the module layout: the runnable code lives under server/, and the project ships separate directories for storage/ and config/ alongside the source. A container path exists too, since docker-entrypoint.sh is copied to /usr/local/bin and made executable, and the image sets STORAGE_DIR=/app/data and LOG_DIR=/app/log. Both directories are created and chowned to the appuser before startup, which is a hint that local disk state is expected by default. The health check is a wget spider against http://localhost:8080/health with a thirty second start period, one minute interval and three second timeout, so a container that takes a while to warm up will not be killed immediately.

Static settings freeze at startup, dynamic settings reload every sixty seconds

Configuration is split in two, and the distinction has operational consequences. Static settings are used on startup and cannot be changed while the application is running. They resolve in a stated priority order: environment variables carrying an extra aidial. prefix, such as aidial.server.port or aidial.config.files; then a file named by the AIDIAL_SETTINGS environment variable; then the default resource file src/main/resources/aidial.settings.json. The sample directory contains an example of each file, aidial.settings.json and aidial.config.json. Dynamic settings are pointed at by the config.files setting, whose default value is aidial.config.json, and the config.reload setting controls the reload interval in milliseconds with a default of 60000. So the model backend list and other runtime values can change without a restart, on a one minute cycle, while anything under server.* or vertx.* is fixed at boot. The docs defer to Vert.x documentation for the vertx.* and server.* keys rather than enumerating them, which means you need to know the Vert.x option names to configure the HTTP server at all.

Helm charts exist for Core alone and for the wider DIAL stack

Deployment options come from the ai-dial-helm repository rather than from this one. There are two charts. The umbrella dial chart also deploys other DIAL components, while the dial-core chart deploys only Core, which is the one to pick if you are integrating the proxy into an existing stack that already provides assistants or applications. The documentation points to the examples directory in the chart repository for guidelines, and it makes one requirement explicit: whatever chart you choose, you must supply the application configurations described in the Configuration section through your Helm values file. There is no default deployment that runs without them. For a Kubernetes team, the practical read is that Core is one component of a wider platform and is expected to be configured, not dropped in and left alone. The repository also carries SECURITY.md, CONTRIBUTING.md, CLAUDE.md and a .claude/ directory, plus trivy.yaml and an .ort.yml dependency policy file, which indicate that image scanning and dependency review are part of the build tooling rather than afterthoughts.

The build gate is real: no GitHub token means no artifact

The limitation worth planning around is the credential dependency. Anonymous access to the GitHub Packages hosting JClouds is not available, so a CI system, a container registry builder, or a developer laptop cannot compile DIAL Core without a personal access token that carries read:packages. That token has to be provisioned outside the repository, and it has to reach the build either as GPR_USERNAME and GPR_PASSWORD or as the gpr.user and gpr.key project properties. The second limitation is the stability of the contract. Any endpoint carrying x-preview: true can change or vanish between releases, so a client pinned to a preview endpoint will break at some point without warning, and the generated spec means you cannot patch the contract locally to keep it alive. A third is the scope itself: DIAL Core normalises access to models and applications, but it does not supply them, so an empty upstream list yields a proxy with nothing behind it.

Editorial conclusion

DIAL Core fits teams that already run several model backends and want one documented REST surface in front of them, and it fits Kubernetes shops that would rather consume the dial-core Helm chart than hand-roll a service. It does not fit a team that wants a hosted chat product, a no credential setup path, or a guarantee of stable preview endpoints, since endpoints marked x-preview: true carry no backward compatibility promise. Before adopting it, read docs/open_api_core.yaml for the contract, confirm the version of each upstream model adapter you depend on, and check what the dynamic settings in aidial.config.json expect for storage and upstream credentials.

Frequently asked questions

How do I build epam/ai-dial-core from source?

The documentation says to build with Gradle and Java 21 using ./gradlew build. Because the project depends on GitHub packages of JClouds and GitHub does not offer anonymous package access, you first need GPR_USERNAME and GPR_PASSWORD set to a GitHub username and a personal access token with the read:packages permission.

Where is the REST API specification for DIAL Core?

The latest OpenAPI 3.0 specification is published at docs/open_api_core.yaml on the development branch. It is generated from the source code using the openapi-generator module, so manual edits to the generated files will be overwritten on the next generation.

How do I know which DIAL Core endpoints are stable?

Endpoints still under development are marked with the x-preview: true vendor extension in the OpenAPI specification. The documentation states that these endpoints are experimental and may change or be removed in future releases without backward compatibility guarantees.

Can I change DIAL Core configuration without restarting it?

Only the dynamic settings. Static settings are used on startup and cannot be changed while the application runs. Dynamic settings live in the files listed under config.files, with a default of aidial.config.json, and they reload on the config.reload interval, which defaults to 60000 milliseconds.

What licence is DIAL Core released under?

The project is licensed under Apache-2.0, and the LICENSE file sits at the top level of the repository alongside build.gradle and the SECURITY.md and CONTRIBUTING.md files.

Official sources

  1. epam/ai-dial-core on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/epam-ai-dial-core.svg)](https://hysenlabs.com/projects/epam-ai-dial-core)

Was this useful?