Configure the System Models (CLI)
The system models are your deployment's own language models: the ones every tenant uses for splitting, classification, extraction, redaction, translation and the AI assistant, unless it has added models of its own on its Models page. You add, change and remove them live with the CLI. Each change takes effect at once on every replica, with no restart, and is recorded in the audit log.
This assumes the CLI is installed and pointed at your deployment (System Administration).
A tenant's own models belong to that tenant. The admin key neither reads nor changes them.
Where the models come from
The models can be set in two places, and the deployment keeps one stored set:
- The deployment's configuration, which your deployment pipeline or
docker-compose.ymland.envcarry: a model file named bySYSTEM_MODELS_FILE(below), or theLLM_*variables in.env(orAZURE_OPENAI_ENDPOINTSfor several endpoints), as described in Standalone (Single Node). The deployment writes its models from it on the first start, and again only when you changeSYSTEM_MODELS_OVERRIDE. - The CLI,
da admin models, which changes the stored set live, as this page shows.
From the first start on, the deployment runs the models it stored. A routine update or restart never replaces them, so what you changed with the CLI stays.
.envChanging LLM_BASE_URL or LLM_MODEL in .env and restarting changes no
model. Change the model with da admin models as shown below.
One thing still comes from .env: the model the first start created from it
(its endpoint is named default) reads its key from LLM_API_KEY at every
start. Keep LLM_API_KEY in .env while that endpoint uses it; changing it
there and restarting changes the key. To give that endpoint a key of its own,
run da admin models update <model-id> --set-key default first (or move it to
a variable with -f); after that, LLM_API_KEY no longer matters.
A deployment started with no model configuration starts with no models. It runs, but a document reaching a step that needs a model fails with a message saying to add one. Add a model and set its defaults (below), then reprocess the document.
See what is configured
da admin models list # each model, its tasks, endpoints and when it was last tested
da admin models export -o models.json # the whole set as a file, without keys
Add a model
1. Pick its profile
A profile says how to call a model: which request parameters it refuses, how it returns JSON, and settings per task (for example the reasoning effort for classification). The catalog ships with profiles for the models we test; the generic one sends the request unchanged.
da admin profiles list --for gpt-6-luna # marks the profile proposed for that name
da admin profiles show gpt-6-luna # what it sets
If you leave --profile out when you add a model, the CLI tells you which one
the catalog proposes for it.
2. Choose how it authenticates
| Way | Option | When |
|---|---|---|
| A key you type | none: the CLI asks for it, with the input hidden | The common case. The key is stored encrypted with CREDENTIAL_ENCRYPTION_KEY. |
| No key | --no-key | A server that takes none, such as Ollama, or vLLM started without --api-key. |
| A variable the deployment holds | --key-env MODEL_KEY_<NAME> (or AZURE_OPENAI_KEY_<NAME>) | Keys kept in a vault or in .env. On Docker, also add - MODEL_KEY_<NAME>=${MODEL_KEY_<NAME>:-} to the docaifabric service's environment: block, then docker compose up -d. The Compose file passes only the variables it names. |
| The deployment's Azure identity | --managed-identity | Azure OpenAI and Azure AI Foundry endpoints, when the deployment runs on Azure with a managed identity. No key at all (see below). |
Keys are never written on the command line or in a file.
3. Add it
An on-premises model server (vLLM, Ollama, or any OpenAI-compatible server):
da admin models add qwen-3.6 \
--url http://gpu-01.internal:8000/ --deployment qwen-3.6 \
--variant openai_compatible --no-key \
--tasks split,classify,extract,redact,translate,assistant
--tasks lists what the model may be used for. Without it a model serves
split, classify, extract, redact and translate; add assistant (and
assistant_utility) for the AI assistant to use it.
--modalities says what the model reads: text, image or text,image (the
default). Give --modalities text for a model that does not read images, as
most local models do (DeepSeek, Qwen3 without -vl): the AI assistant sends a
model the page images its tools return whenever its Image modality is on, and a
text-only model refuses them.
An Azure OpenAI deployment:
da admin models add gpt-6-luna \
--url https://my-account.openai.azure.com/ --deployment gpt-6-luna \
--profile gpt-6-luna --key-env AZURE_OPENAI_KEY_EASTUS
--variant is azure (the default), azure_ai_inference, openai_compatible
or anthropic. A model with several endpoints, for failover or for several
regions, is added from a file (da admin models add -f model.yaml):
model_id: gpt-6-luna
display_name: GPT-6 Luna
profile: gpt-6-luna
tasks: [split, classify, extract, redact, translate]
endpoints:
- name: luna-eastus
url: https://my-account-eastus.openai.azure.com/
deployment: gpt-6-luna
region: eastus
auth: {api_key_env: AZURE_OPENAI_KEY_EASTUS}
- name: luna-westus
url: https://my-account-westus.openai.azure.com/
deployment: gpt-6-luna
region: westus
priority: 2 # used when the first is unavailable
auth: {managed_identity: true}
To type a key for one of a file's endpoints, add --prompt-key <endpoint> once
for each.
4. Read its Test
Adding a model ends with its Test: one call per operation the model's tasks need (text, structured output, page images, tool calling, streaming) on every endpoint, and a verdict per task: supported, limited or unsupported. A failed operation is named, and that is what to fix. See Test and Measure Models.
5. Set the defaults
A default is the model a task uses where neither the step nor the tenant's own defaults name one. Set one for every task your tenants use:
da admin models set-default extract gpt-6-luna
da admin models set-default classify gpt-6-luna
The tasks are split, classify, extract, redact, translate,
assistant (the AI assistant) and assistant_utility (its background work,
such as conversation titles). A default must name a model that is enabled and
serves the task.
Setting the assistant default also turns the AI assistant on, without a
restart (users who have the application open see it after reloading the
page), unless ASSISTANT_ENABLED=false turned it off. A deployment with no
model for the assistant has it off until you set one.
Change a model
da admin models update gpt-6-luna --display-name "GPT-6 Luna"
da admin models update gpt-6-luna --tasks split,classify,extract
da admin models update gpt-6-luna --profile gpt-6-luna
da admin models update gpt-6-luna --set tasks.classify.set.reasoning_effort=low # --unset to take it away
da admin models update gpt-6-luna --set-key luna-eastus # type a new key for one endpoint
da admin models update gpt-6-luna --managed-identity luna-eastus # move an endpoint to the Azure identity
da admin models update gpt-6-luna --license-name gpt-6-luna # the name a license uses for it
da admin models update gpt-6-luna --location luna-au=region:australiaeast # where an endpoint processes
da admin models update deepseek-v4 --modalities text # a model that does not read images
If the AI assistant's requests fail with the message that the model may not
read images, its model's Image modality is on and the model does not read
them: da admin models test <model-id> shows Image input failing, and
--modalities text fixes it. A model the LLM_* variables set up always
starts with the Image modality on.
A license can hold a tenant to named system models for each task. It names a
model by its license name, not its id, so give every model one, the same for
the same model and settings on every deployment you run. A model without one
is open only to licenses that allow every system model. --availability listed keeps a model to the licenses that name it. An endpoint's location
is global (the default), dz-us, dz-eu, dz-apac or
region:<azure-region>: where the provider may process its calls, from its
deployment type.
To add an endpoint, give the model's whole endpoint list in a JSON file,
{"endpoints": [...]}: this model's endpoints from da admin models export,
plus the new one. Export right before the update: the list replaces the
model's, so an endpoint someone added since an older export would go. When the new endpoint takes a typed key, leave the key out of the
file and name the endpoint with --set-key, which prompts for it:
da admin models update gpt-6-luna -f endpoints.json --set-key luna-westeurope
Each change ends with the model's Test again.
Stop using a model
A step that names a model it cannot use fails: it never runs on another model in its place. So before you disable or remove a model, or take a task from it, see what names it:
da admin models who gpt-6-luna # the defaults, tenants' defaults and project steps that name it
Move those steps and defaults to another model first. Then:
da admin models disable gpt-6-luna # no call reaches it; enable brings it back
da admin models remove gpt-6-luna # gone; adding it back means its settings and keys again
Both are refused while the model is a default, and while steps or tenants'
defaults name it unless you add --force (they then fail). When some projects
could not be read, the change is refused until they are fixed or you add
--ignore-unreadable.
Your own profiles
When the catalog has no profile for a model you run, set single fields on the model itself:
da admin models update qwen-3.6 --set drop=temperature,top_p --set set.reasoning_effort=none
When several models need the same settings, or your tenants should be able to pick them on their Models page, add a profile to your deployment's own catalog instead. Write it as a file, in the same shape as the profiles we ship:
# qwen-fast.yaml
id: qwen-fast
adapter: chat_completions
drop: [temperature, top_p]
set: {reasoning_effort: none}
tasks:
classify:
set: {reasoning_effort: low}
da admin profiles add -f qwen-fast.yaml
da admin models update qwen-3.6 --profile qwen-fast
da admin profiles update qwen-fast -f qwen-fast.yaml # every model naming it gets the change on its next call
da admin profiles who qwen-fast # the models, yours and the tenants', that name it
da admin profiles remove qwen-fast
- Every model of the deployment can name it, the tenants' own models included. Other replicas pick up a change within about half a minute.
- Its id may not be one a release ships. If a later release ships a profile
of the same id, yours keeps its place, so the upgrade changes no request;
da admin profiles listpoints it out, and you remove yours to use ours (refused only when the two go out on different APIs). - Otherwise a profile is not removed, nor its
adapterchanged, while a model names it. Move those models to another profile first. - A model must name a profile the catalog has: add the profile, then the model.
- Before rolling back to a version without this feature, move the models that name your profiles to a shipped profile: that version does not know yours and calls such models with the generic profile.
On our SaaS service, profiles come with a release, and these commands are refused there.
Keep the models in a file
To review model changes like code, keep the set in a file and apply it:
da admin models export -o models.json # start from what runs today
da admin models apply -f models.json --dry-run # what would change
da admin models apply -f models.json # add and update what the file lists
da admin models apply -f models.json --prune # and remove what it does not
The file is JSON as export writes it, or YAML. It lists models and
defaults, each model in the shape shown above.
It never holds a key: an endpoint names api_key_env, uses managed_identity,
or keeps the key typed for it earlier. A key typed earlier survives an apply
as long as the endpoint keeps its name.
da admin models backups lists the copies taken before each restore, and
before each time the deployment's configuration was applied over the stored
set; da admin models restore <backup> puts one back.
Let the deployment apply the file
The same file can be part of the deployment, so a pipeline or a
docker-compose.yml sets the models instead of a person at the CLI. Mount it
and name it in .env (the standalone docker-compose.yml mounts the config
folder next to it):
SYSTEM_MODELS_FILE=/app/config/models.yaml
A file for a local model that does not read images, serving every task:
models:
- model_id: deepseek-v4
tasks: [split, classify, extract, redact, translate, assistant]
supports_image: false
endpoints:
- name: ollama-1
url: http://gpu-01.internal:11434
deployment: deepseek-v4:32b
variant: openai_compatible
region: on-prem
auth: {key_required: false}
defaults:
split: deepseek-v4
classify: deepseek-v4
extract: deepseek-v4
redact: deepseek-v4
translate: deepseek-v4
assistant: deepseek-v4
When the deployment reads it:
| The stored models | SYSTEM_MODELS_OVERRIDE | At start |
|---|---|---|
| None yet (the first start) | any | Stored from the file |
| Stored | unset, or the value it had at the last start | Kept as they are; the log says when the file differs |
| Stored | a new value (any text, such as today's date) | Replaced by the file once, after a backup |
SYSTEM_MODELS_OVERRIDE_MODE=upsert replaces only the models the file lists
and the defaults it names, and keeps the models added with the CLI; the
default, replace, makes the set exactly the file's. Before changing the
value, da admin models diff --deploy shows what it would change. Without
SYSTEM_MODELS_FILE, the LLM_* variables are what the deployment applies.
Azure endpoints without a key
When the deployment runs on Azure with a managed identity (on Azure
Container Apps, the identity whose client id is AZURE_CLIENT_ID), an Azure
OpenAI or Azure AI Foundry endpoint can be called with that identity instead of
a key. Grant the identity the Cognitive Services OpenAI User role on each
Azure OpenAI or AI Services resource it calls:
az role assignment create \
--assignee <the identity's principal id> \
--role "Cognitive Services OpenAI User" \
--scope <the resource id of the Azure OpenAI account>
Then add or update the endpoint with --managed-identity. A new role assignment
can take a few minutes to apply. Until it does, the Test reports a 401 or 403
on that endpoint and its hint names the role.
The identity is used only over HTTPS on Azure OpenAI and Azure AI Foundry hosts
(*.openai.azure.com, *.cognitiveservices.azure.com, *.services.ai.azure.com),
in the Azure public cloud. A tenant's own models can never use it.
With an AI agent
An agent connected to the admin MCP server can do
all of this except typing a key and the file commands (apply, export,
diff, backups, restore), which stay the CLI's. It reads the
system-administration skill first, which gives the same order as this page.