Technical docs
Models and Voices
Overview
Reference for the developer-only model and voice catalog pages, plus the wider authenticated catalog endpoints consumed by staff tooling.
Access scope
- Routes:
- `/models`
- `/voices`
- Sidebar menu metadata marks both as developer-only (`isDeveloper: true`).
- The pages render `AccessDenied` for non-developer users.
- Frontend `isDeveloper` is populated by mapping backend `is_admin` to frontend `is_developer` in `AuthContext`.
- Backend CRUD endpoints are under `/api/admin/*` and protected by `adminMiddleware`.
- Separate read-only catalog endpoints exist for any authenticated user:
- `GET /api/init/models`
- `GET /api/init/ai-voices`
- Those init endpoints are what AI teammate profile forms and other non-admin flows use.
Models (`/models`)
- UI supports list/search, detail view, and create/edit/delete.
- Current dialog fields:
- display name
- model identifier
- provider
- `is_multimodal`
- `is_realtime`
- `is_tts`
- `is_stt`
- `Input Cost`
- `Output Cost`
- `Cached Input Cost`
- Provider options shown in the dialog:
- `OpenAI`
- `OpenRouter`
- `Google`
- `DeepSeek`
- `Anthropic`
- Pricing fields are optional numeric USD values stored per 1M tokens.
- If `Cached Input Cost` is left empty, runtime cost calculation falls back to the normal input cost.
- Backend model records also support a `voices` array, but the current models dialog does not expose that field.
- Current uniqueness constraint is effectively global on `model` itself, not on `(provider, model)`.
Admin API
- `GET /api/admin/ai-models`
- `GET /api/admin/ai-models/{id}`
- `POST /api/admin/ai-models`
- `PUT /api/admin/ai-models/{id}`
- `DELETE /api/admin/ai-models/{id}`
Authenticated catalog API
- `GET /api/init/models`
- Returned fields include:
- `id`
- `model`
- `name`
- `provider`
- `is_multimodal`
- `is_realtime`
- `is_tts`
- `is_stt`
- `voices`
- Frontend consumers use this endpoint to populate chat/TTS/STT selectors outside the admin pages.
Voices (`/voices`)
- UI supports list/search, detail view, and create/edit/delete.
- Current dialog fields:
- provider
- voice identifier
- gender
- Provider options shown in the dialog:
- `OpenAI`
- `OpenRouter`
- `Google`
- Backend/provider model supports more than the current dialog exposes:
- backend validation/model enum accepts `OpenAI`, `OpenRouter`, `Google`, `DeepSeek`, and `Anthropic`
- the current create/edit dialog only offers `OpenAI`, `OpenRouter`, and `Google`
- the list page can still display voices from any stored provider
- Voice uniqueness is `(provider, voice)`.
Admin API
- `GET /api/admin/ai-voices`
- `GET /api/admin/ai-voices/{id}`
- `POST /api/admin/ai-voices`
- `PUT /api/admin/ai-voices/{id}`
- `DELETE /api/admin/ai-voices/{id}`
Authenticated catalog API
- `GET /api/init/ai-voices`
- Optional query filters:
- `provider`
- `gender`
- `search`
- AI teammate voice selectors filter this list by the currently selected TTS model provider.
Validation impact on AI teammates
- Chat `model` must not be a realtime, TTS, or STT model.
- `tts_model` must be TTS-capable or realtime-capable.
- `stt_model` must be STT-capable.
- `voice` cannot be set without a `tts_model`.
- When `tts_model` is set, `voice` is required and must exist for that TTS model's provider.
- Current frontend filtering matches the backend validation:
- chat model dropdown excludes `is_realtime`, `is_tts`, and `is_stt`
- TTS dropdown includes `is_tts` or `is_realtime`
- STT dropdown includes `is_stt`
Fallback model settings
- Developer-only system settings in `/defaults` can define:
- `AI Model Fallback 1`
- `AI Model Fallback 2`
- Runtime execution retries those fallback models in order before the run is marked failed.