Models registry
The Models registry screen lets you list the models of the tenant with their capabilities, limits, residency and lifecycle status, change their status, edit their sheet, manage the model categories and register models by manifest or by hand. Portal path: /llm/models, and /llm/models/<model_id> for the detail page. It is used by the AI platform administrators, the security officers who block or retire a model, and every LLM reader who checks what is available. The screen is built in portal/src/screens/llm.tsx (Models, ModelList, ModelDetail, Categories, ManualModel, ManifestApply).
What the screen shows
The list page has three tabs: Registry, Categories (with the number of categories) and Manifest (administrators only). The header button Add manually is shown to the administrators.
Registry tab: the table Models (GET /v1/models), a refresh button and the filters Provider (text), Category (the categories visible to the tenant) and Status (approved, restricted, deprecated, blocked), applied with Filter.
| Column | Content |
|---|---|
| Model id | Registry identifier (model_id). |
| Display name | Name shown to users. |
| Category | Category of the model (badge). |
| Provider | Provider type. |
| Provider model id | Identifier of the model at the provider. |
| Deployment id | Deployment identifier, for example an Azure deployment. |
| Capabilities | List such as chat, tools, streaming, vision_input. |
| Context window | Input tokens accepted. |
| Max output tokens | Output limit. |
| Reasoning modes | Supported reasoning effort levels. |
| Streaming, Caching, Batch | Yes or no. |
| Max classification | Highest data classification the model accepts. |
| Pricing version | Version of the price card. |
| Provider configured | Whether the provider of the model is configured. |
| Status | approved, restricted, deprecated or blocked. |
When the registry is empty: "No model registered. Apply a Model manifest below to register a model." Clicking a row opens the detail page.
Categories tab: one card per category (GET /v1/llm/categories) with its label, its identifier and icon, the badge Predefined or Custom, its description and n model(s). Predefined categories are read only.
Manifest tab: a YAML or JSON editor pre-filled with a sample Model manifest, the buttons Reset example and Apply, and on the right the validation errors returned by the API or Manifest applied with the JSON answer.
Detail page /llm/models/<model_id>: Back, the model id as title, the section Lifecycle (status badge and, for the roles that may change it, the selector Choose a status with Change status), cards for display name, category, provider, provider model id, deployment id, context window, max output tokens, knowledge cutoff, max classification, pricing version and wire format, then the tabs Model sheet (administrators), Registry record (JSON) and Exported manifest (GET /v1/manifests/Model/<model_id>).
Actions
| Button or action | What it does | API call | Roles |
|---|---|---|---|
| Filter (Registry) | Applies the provider, category and status filters. | GET /v1/models | LLM readers |
| Change status (row menu) | Form with Status; approved in a tenant opens an approval request (answer 202), the other statuses apply at once. | POST /v1/models/{model_id}/status | tenant_admin, platform_admin, ai_platform_engineer, security_officer |
| Disable (row menu, enabled model) | Kill switch of the model, after the destructive confirmation (type the resource name). | POST /v1/models/{model_id}/disable | tenant_admin, platform_admin, ai_platform_engineer, security_officer |
| Enable (row menu, disabled model) | Enables the model again. | POST /v1/models/{model_id}/enable | tenant_admin, platform_admin, ai_platform_engineer |
| Edit (row menu) | Form with Display name, Category, Context window, Max output tokens, Max classification. | PATCH /v1/models/{model_id} | tenant_admin, platform_admin, ai_platform_engineer |
| Delete (row menu) | Deletes the model after the destructive confirmation. | DELETE /v1/models/{model_id} | tenant_admin, platform_admin, ai_platform_engineer |
| Add manually (header) | Drawer Add a model manually: Provider (enabled providers), Provider model id, Registry id, Display name, Category, limits, modalities, Capabilities, reasoning levels, Default reasoning effort, Knowledge cutoff, Status, prices per 1M tokens, unit prices, Currency. Toast Model <id> added or "This model is already registered: nothing was added." | GET /v1/providers, GET /v1/llm/categories, POST /v1/models/import | tenant_admin, platform_admin, ai_platform_engineer |
| New category (Categories) | Drawer with Identifier, Label (English), Label (French), Description (English), Description (French), Icon name. | POST /v1/llm/categories | tenant_admin, platform_admin, ai_platform_engineer |
| Edit (custom category menu) | Loads the category, then saves the labels, descriptions and icon. | GET /v1/llm/categories/{slug}, PATCH /v1/llm/categories/{slug} | tenant_admin, platform_admin, ai_platform_engineer |
| Delete (custom category menu) | Deletes an unused category after confirmation; greyed while models use it. | DELETE /v1/llm/categories/{slug} | tenant_admin, platform_admin, ai_platform_engineer |
| Reset example (Manifest) | Puts the sample manifest back in the editor. | none | administrators |
| Apply (Manifest) | Parses the YAML or JSON, then validates and stores the manifest. | POST /v1/manifests/apply | server: tenant_admin, developer (and platform_admin); tab shown to tenant_admin, platform_admin, ai_platform_engineer |
| Row click | Opens the detail page. | GET /v1/models/{model_id}, GET /v1/manifests/{kind}/{name} | LLM readers |
| Change status (detail, Lifecycle) | Same as the row action, from the selector Choose a status. | POST /v1/models/{model_id}/status | tenant_admin, platform_admin, ai_platform_engineer, security_officer |
| Save the sheet (detail, Model sheet) | Sends only the changed fields. Toast Model sheet saved or Nothing changed. | PATCH /v1/models/{model_id} | tenant_admin, platform_admin, ai_platform_engineer |
| Back (detail) | Returns to the list. | none | everyone |
Roles
- Reading (
GET /v1/models,GET /v1/models/{model_id},GET /v1/llm/categories): the LLM readers (ROLES.llmReadersinportal/src/lib/kit.ts,READinservices/control-plane/src/eai/domains/llm/__init__.py):tenant_admin,platform_admin,security_officer,finops,developer,auditor,viewer,agent,ai_platform_engineer,ai_governance_officer,support_engineer. - Administration (edit, enable, delete, import, categories, model sheet):
tenant_admin,platform_admin,ai_platform_engineer(ROLES.llmAdmins). - Status and kill switch (
status,disable): the administrators plussecurity_officer(ROLES.llmDisablers). - Approval of a promotion to
approved:tenant_adminorsecurity_officer, in the Approvals inbox. - Manifest: the server accepts
tenant_adminanddeveloperonPOST /v1/manifests/apply; the portal shows the tab to the LLM administrators, so anai_platform_engineergetsforbiddenthere.platform_adminpasses every role check.
Typical tasks
Register a model the provider cannot list
- Check the provider. The model must belong to an enabled provider of the Providers screen. Expected result: the provider card shows Configured. If it fails: the drawer says "Configure a provider first on the Providers page."
- Open the form. Click Add manually, pick the Provider and type the Provider model id (for example
gpt-4.1-mini); leave Registry id empty to derive it. Expected result: the form shows the sheet fields. If it fails: a field marked Required is empty. - Describe the model. Set Category, Context window (input tokens), Max output tokens, the Capabilities and the prices, so that routing and cost accounting are right. Expected result: no validation message. If it fails: "Price
<field>is invalid: it must be a positive or zero amount." - Submit. Click Add manually. Expected result: toast
Model <id> addedand the model in the Registry tab. If it fails: "This model is already registered: nothing was added." means the model exists already.
Retire or block a model
- Find the model. In Registry, filter on Status or Provider and click Filter. Expected result: the row of the model. If it fails: clear the filters and filter again.
- Change its status. Open the row menu > Change status, choose
deprecatedorblocked, then click Change status in the form. A blocked model cannot be invoked. Expected result: toast Done, the Status column shows the new value. If it fails: "Invalid model status" lists the allowed values. - Stop it at once if needed. For an incident, use Disable, type the resource name in the confirmation and click Confirm. Expected result: the gateway answers "This model is disabled (kill switch)." for this model. If it fails:
forbiddenmeans your role is not among the status roles.
Apply a Model manifest
-
Open the tab. Click Manifest. The editor holds a sample manifest you can adapt:
apiVersion: enterprise-ai.io/v1kind: Modelmetadata:name: gpt-4o-euversion: 1.0.0spec:model_id: gpt-4o-euprovider: azure_openaiprovider_model_id: gpt-4ocontext_window: 128000max_output_tokens: 16384data_classification_max: confidentialstatus: approvedExpected result: the editor shows your YAML. If it fails: click Reset example to start again from the sample.
-
Apply. Click Apply: the document is parsed, validated, checked by policy and stored in the registry. Expected result: Manifest applied and the JSON answer. If it fails: "Cannot parse the document" points to a YAML or JSON syntax error; the validation errors of the API are listed in red.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
"Model <model_id> not found." (model_not_found) | The id does not exist in this tenant. | Check the id in the Registry tab. |
"Model <model_id> already exists." (model_exists, 409) | Same registry id already registered. | Use another model_id or edit the existing model. |
"Invalid model status <status>." (status_invalid, 422) | Status outside approved, restricted, deprecated, blocked. | Choose one of the four values. |
Change status to approved answers but the status does not change | A promotion opens an approval request (202). | Have a tenant_admin or security_officer decide it in the Approvals inbox. |
"Field <field> of the model sheet is invalid." (sheet_invalid) or "Price <field> is invalid" (pricing_invalid) | A value of the sheet does not pass the checks. | Fix the field named in the message. |
"Category <slug> is predefined: it cannot be changed or deleted." (category_builtin, 409) | Predefined categories are read only. | Create a custom category instead. |
"Category <slug> is used by <n> model(s): move them to another category first." (category_in_use, 409) | Models still use the category. | Change the category of those models with Edit, then delete. |
"A category with the identifier <slug> already exists." (category_exists, 409) | Duplicate identifier. | Choose another Identifier. |
"Only a platform administrator can change platform level entries." (platform_only, 403) | The model or category is defined at platform level. | Ask a platform_admin. |
"The model manifest is invalid." (invalid_manifest) or the red list under Apply | The manifest does not match the Model contract. | Fix the fields listed, then Apply again. |
forbidden (403) on Apply | Role not accepted by POST /v1/manifests/apply. | Ask a tenant_admin or a developer. |