8.2 KiB
Models & Preferences
What models are available to the current user and how they control visibility.
Enabled Models
The primary endpoint for populating model selectors:
GET /models/enabled
Returns a composite response:
{
"data": [ UserModel, ... ],
"default_model": "claude-sonnet-4-20250514"
}
default_model is the admin-configured default model ID (from the
default_model policy). Empty string if unset.
UserModel object:
{
"id": "composite-id",
"display_name": "Claude Sonnet 4",
"model_id": "claude-sonnet-4-20250514",
"model_type": "chat",
"source": "catalog",
"provider_config_id": "uuid",
"config_id": "uuid",
"provider_name": "Anthropic",
"provider_type": "anthropic",
"capabilities": {
"streaming": true,
"tool_calling": true,
"vision": true,
"thinking": true,
"reasoning": false,
"code_optimized": false,
"web_search": false,
"max_context": 200000,
"max_output_tokens": 8192
},
"is_persona": false,
"persona_id": "",
"persona_handle": "",
"persona_scope": "",
"persona_avatar": "",
"persona_team_name": "",
"description": "",
"icon": "",
"avatar": "",
"system_prompt": "",
"temperature": null,
"max_tokens": null,
"tool_grants": [],
"pricing": {
"input_per_m": 3.00,
"output_per_m": 15.00,
"currency": "USD"
},
"scope": "global",
"owner_id": null,
"team_name": "",
"hidden": false,
"sort_order": 0,
"provider_status": "healthy"
}
Field reference:
| Field | Type | Description |
|---|---|---|
id |
string | Composite key. Catalog: {config_id}:{model_id}. Persona: persona UUID. |
display_name |
string | Human-readable name (from catalog or persona). |
model_id |
string | Raw model identifier (e.g. claude-sonnet-4-20250514). |
model_type |
string | "chat", "embedding", "image", etc. |
source |
string | "catalog" (DB catalog entry) or "persona". |
provider_config_id |
string | UUID of the provider config that serves this model. |
config_id |
string | Alias of provider_config_id (frontend compat). |
provider_name |
string | Display name of the provider config. |
provider_type |
string | Provider type slug (e.g. "anthropic", "openai"). |
capabilities |
object | Nested ModelCapabilities — see below. |
is_persona |
bool | true if this entry is a Persona, not a raw model. |
persona_id |
string | Persona UUID (omitted if not a persona). |
persona_handle |
string | @handle for mention routing (omitted if not a persona). |
persona_scope |
string | Persona scope: "global", "team", "personal" (omitted if not). |
persona_avatar |
string | Avatar URL (omitted if not a persona or unset). |
persona_team_name |
string | Owning team name for team-scoped personas (omitted if N/A). |
description |
string | Persona description (omitted if empty). |
icon |
string | Persona icon (omitted if empty). |
avatar |
string | Avatar URL (omitted if empty). |
system_prompt |
string | Persona system prompt (omitted if empty). |
temperature |
float|null | Persona temperature override. |
max_tokens |
int|null | Persona max-tokens override. |
tool_grants |
string[] | Tool IDs granted to this persona. |
pricing |
object|null | Nested ModelPricing — see below. Omitted if unavailable. |
scope |
string | "global", "team", or "personal". |
owner_id |
string|null | Owner user/team ID for team/personal scoped entries. |
team_name |
string | Team name (persona entries only). |
hidden |
bool | true if the user has hidden this model via preferences. |
sort_order |
int | User's custom sort position (0 = default). |
provider_status |
string | Health status: "healthy", "degraded", "down", "unknown", or empty. |
ModelCapabilities:
| Field | Type | Description |
|---|---|---|
streaming |
bool | Supports streaming responses. |
tool_calling |
bool | Supports function/tool calling. |
vision |
bool | Supports image inputs. |
thinking |
bool | Supports extended thinking. |
reasoning |
bool | Reasoning-optimized model. |
code_optimized |
bool | Code-optimized model. |
web_search |
bool | Has built-in web search. |
max_context |
int | Context window size in tokens. |
max_output_tokens |
int | Maximum output tokens. |
Capabilities are resolved through the three-tier chain: catalog DB →
heuristic inference → admin overrides (see providers.md §capabilities).
ModelPricing:
| Field | Type | Description |
|---|---|---|
input_per_m |
float | Input cost per million tokens. |
output_per_m |
float | Output cost per million tokens. |
currency |
string | Currency code (e.g. "USD"). |
Persona inheritance: When is_persona is true, the capabilities
and pricing objects are inherited from the persona's underlying base
model. The persona adds identity (name, handle, avatar, system prompt,
tool grants) — not capability restrictions. Persona entries always have
hidden: false; persona visibility is controlled by the grant system
and the is_active flag, not by model preferences.
Model allowlist filtering (v0.24.2): Non-admin users whose groups
define model restrictions will only see models in their allowlist.
Persona entries whose underlying model_id is not in the allowlist are
also filtered. Admins bypass this filter entirely.
Visibility resolution order:
- Global catalog: enabled models → all authenticated users
- Team catalog: enabled models → team members
- Personal BYOK: enabled models → owner (requires
allow_user_byokpolicy) - Personas: global + team + personal + shared-via-grants
- User hidden preferences applied last (sets
hiddenflag, does not remove) - Model allowlist filtering (removes entries entirely for non-admins)
User Model Preferences
Users can hide models they don't want to see and set per-model
defaults. Preferences are keyed on the composite identity
provider_config_id:model_id — the same model from different
providers can have independent visibility.
GET /models/preferences → { "data": [PreferenceEntry, ...] }
PUT /models/preferences ← { "model_id": "...", "provider_config_id": "uuid", ... }
POST /models/preferences/bulk ← { "entries": [...], "hidden": bool }
GET /models/preferences
Returns all preference entries for the authenticated user.
PreferenceEntry:
{
"id": "uuid",
"user_id": "uuid",
"model_id": "grok-4.1-fast",
"provider_config_id": "uuid",
"hidden": true,
"preferred_temperature": 0.7,
"preferred_max_tokens": 4096,
"sort_order": 0,
"created_at": "2025-06-15T14:30:00Z",
"updated_at": "2025-06-15T14:30:00Z"
}
PUT /models/preferences
Upserts a single preference entry. All fields except model_id are
optional — only provided fields are updated. If no entry exists, one
is created.
Request body:
{
"model_id": "claude-sonnet-4-20250514",
"provider_config_id": "uuid",
"hidden": true,
"preferred_temperature": 0.7,
"preferred_max_tokens": 4096,
"sort_order": 1
}
model_id and provider_config_id are required. All other fields are
optional — only provided fields are updated. If no entry exists, one
is created.
Returns { "message": "preference updated" }.
POST /models/preferences/bulk
Sets the hidden state for multiple model+provider pairs at once. The
hidden value is applied to all entries in the batch — this is
not per-entry hidden control.
Request body:
{
"entries": [
{ "model_id": "grok-4.1-fast", "provider_config_id": "uuid" },
{ "model_id": "llama-3.1-70b", "provider_config_id": "uuid" }
],
"hidden": true
}
Returns { "message": "preferences updated", "count": 2 }.
Identity rule: provider_config_id is required on write. The same
bare model_id from two different provider configs (e.g. global Venice
vs personal BYOK Venice) are independent preference entries. The
frontend composite ID format is {provider_config_id}:{model_id}.
Persona preferences: Personas are not in this table. A persona's
visibility is controlled by the grant system and the is_active flag,
not by model preferences.