Service Litellm - thekaveh/atlas GitHub Wiki
LiteLLM is the always-on OpenAI-compatible front door for every LLM provider in the stack. The default consumers (Backend, Open WebUI, n8n, JupyterHub, Local Deep Researcher, OpenClaw, Weaviate vectorization) use one URL and one API key: LITELLM_BASE_URL and LITELLM_API_KEY. LiteLLM routes each request to the upstream for its model name. Services with a documented native-provider override, such as LightRAG role bindings, can bypass this path.
To open the dashboard or call the API, see Β§5 Access. To check a running gateway, see Β§10 Smoke tests.
When Hermes Agent is enabled, services/litellm/init/scripts/init.py appends a hermes-agent row to model_list, with api_base ${HERMES_ENDPOINT}/v1 and the os.environ/HERMES_API_KEY bearer token. The row does not come from the YAML model catalogs, because Hermes is a service, not a model provider. Open WebUI, n8n, backend, jupyterhub and openclaw see hermes-agent in their model lists with no per-consumer wiring.
- Image:
ghcr.io/berriai/litellm:v1.83.14-stable.patch.2(override viaLITELLM_IMAGE). Pinned to avX.Y.Z-stabletag; LiteLLM's prod docs explicitly warn againstmain-latest/main-stable. - Internal port:
4000. Host port:LITELLM_PORT(default63040). See.env.examplefor the current default. - Internal port
4000is also used bysupabase-realtime; not a collision (different container hostnames).
Consumers βββΊ litellm:4000 βββΊ Ollama / vLLM Metal / Cloud providers
β
βββΊ supabase-db:5432/litellm (DATABASE_URL)
βββΊ redis:6379 (REDIS_HOST/PORT/PASSWORD)
-
Ollama upstream is a single-select choice (
LLM_PROVIDER_SOURCE):-
ollama-container-cpu/ollama-container-gpuβ Docker Ollama upstream -
ollama-localhostβ Ollama running on the host machine -
noneβ no Ollama upstream
-
-
vLLM Metal is an independent managed-host choice:
-
VLLM_METAL_SOURCE=managed-localhostβ native Apple-silicon vLLM upstream -
VLLM_METAL_SOURCE=disabledβ default
-
-
Cloud providers are independent toggles (each
enabled/disabled):-
CLOUD_OPENAI_SOURCE(requiresOPENAI_API_KEY) -
CLOUD_ANTHROPIC_SOURCE(requiresANTHROPIC_API_KEY) -
CLOUD_OPENROUTER_SOURCE(requiresOPENROUTER_API_KEY)
-
- Bootstrapper refuses to start only when
LLM_PROVIDER_SOURCE=none, vLLM Metal is disabled, AND every cloud source is disabled.
-
Database: dedicated
litellmdatabase on the existing Supabase Postgres server. Created on first start by thelitellm-initcontainer (services/litellm/init/scripts/init.py). Same host (supabase-db) with a dedicated role (LITELLM_DB_USER/LITELLM_DB_PASSWORD) β separate logical database, so LiteLLM'sLiteLLM_*Prisma-managed tables stay isolated from Supabase's schema. Override the database name viaLITELLM_DB_NAME. -
Redis: response cache and rate-limit state, on the stack's Redis at
redis:6379withREDIS_PASSWORD.- The response cache serves embeddings, reranks and transcriptions for
LITELLM_CACHE_TTL, because a fixed model returns the same result for the same input. - Chat, text-completion and Responses API calls are cached only when
LITELLM_CACHE_CHAT=true. Then an identical request tohermes-agentorlightragreturns the cached reply for the TTL. It does not run the agent or see newly ingested documents. Send"cache": {"no-cache": true}in the request body for those calls.
- The response cache serves embeddings, reranks and transcriptions for
-
Master key:
LITELLM_MASTER_KEY(must start withsk-) is auto-generated by the bootstrapper on first start and written into.env. Never overwritten on subsequent runs β virtual keys and spend history persist.
In the URLs and commands on this page, replace each ${VAR} with the value of that variable in .env.
| Surface | URL | Notes |
|---|---|---|
| Admin dashboard (Kong alias) | http://litellm.localhost:${KONG_HTTP_PORT}/ui/ |
Use this from your browser. A bare visit to http://litellm.localhost:${KONG_HTTP_PORT}/ 302-redirects to /ui/. Requires ./start.sh --setup-hosts so litellm.localhost resolves. |
| Admin dashboard (direct port) | http://localhost:${LITELLM_PORT}/ui/ |
Equivalent. On the direct port, the proxy root (/) serves the Swagger UI API explorer and does not redirect. The dashboard is always under /ui/. |
| Proxy API (Kong alias) | http://litellm.localhost:${KONG_HTTP_PORT}/v1/* |
GET /v1/models, POST /v1/chat/completions, POST /v1/embeddings, etc. Bearer token = ${LITELLM_MASTER_KEY}. |
| Proxy API (direct port) | http://localhost:${LITELLM_PORT}/v1/* |
Same surface, no Kong in the path. |
| Usage telemetry | http://litellm.localhost:${KONG_HTTP_PORT}/spend/{logs,users} |
Raw JSON rollups backing the dashboard's spend pages. Master-key auth. |
| In-network DNS (sibling containers) | http://litellm:4000 |
What backend, open-web-ui, jupyterhub, local-deep-researcher, hermes, and weaviate actually call. Not reachable from the host. |
The dashboard at /ui/ needs a login. Two env vars set the credentials on the LiteLLM container:
| Env var | Default | Meaning |
|---|---|---|
LITELLM_UI_USERNAME |
admin |
Username for the dashboard login form. Override in .env to change. |
LITELLM_MASTER_KEY |
auto-generated | Doubles as the dashboard password. The same sk-β¦ value used as the proxy Bearer token. |
To recover the password, run from the repository root with the bootstrapper dependencies available through uv.
The parser reads .env by default; use ATLAS_ENV_FILE for a custom active file.
It prints the literal value and stops if the key is missing or blank:
PYTHONPATH=bootstrapper uv run --project bootstrapper python - <<'PYKEY'
import sys
from core.config_parser import ConfigParser
parser = ConfigParser(root_dir=".")
if not parser.env_file_path.is_file():
sys.exit("The active Atlas env file does not exist.")
env = parser.parse_env_file()
key = env.get("LITELLM_MASTER_KEY", "")
if not key:
sys.exit("Set a nonempty LITELLM_MASTER_KEY in the active Atlas env file.")
print(key)
PYKEYCompose maps LITELLM_UI_USERNAME β UI_USERNAME and LITELLM_MASTER_KEY β UI_PASSWORD. LiteLLM requires both.
The Kong route at litellm.localhost is always on; there is no toggle. bootstrapper/utils/kong_config_generator.py::generate_litellm_service() generates it. It proxies the whole LiteLLM surface, not only /ui/, so every endpoint works on the direct port and on the alias. The route uses preserve_host: True. LiteLLM's SPA then builds login redirects to litellm.localhost:${KONG_HTTP_PORT}, which the browser can resolve, and not to litellm:4000.
The YAML model catalogs and the wizard selections in .env decide which provider models LiteLLM exposes.
services/ollama/models.yaml ββ
services/litellm/models.yaml ββββΊ model_resolver.active_models(env) βββΊ litellm-init renders /app/config.yaml βββΊ litellm reads model_list
wizard selections in .env ββ
Whenever litellm-init starts, it calls model_resolver.active_models(). It reads the YAML catalogs and the wizard's env vars: LLM_PROVIDER_SOURCE, OLLAMA_USER_MODELS, OLLAMA_CUSTOM_MODELS, LITELLM_*_ENABLED, cloud *_API_KEY and *_USER_MODELS. It then renders volumes/litellm/config.yaml with the per-provider routing rules below. Config rendering uses no database query.
- For
ollama-localhostwithOLLAMA_AUTO_IMPORT_LOCAL_MODELS=true,litellm-initalso reads the upstream/api/tagsand adds host-pulled models to the active set. If the host daemon does not answer within 10 s, the init log printsauto-import: failed to fetch /api/tags. Host-pulled tags are then not registered for this run. - Before
docker compose up, the bootstrapper writes only a stub, for the bind mount.services/litellm/init/scripts/init.pyfills in the realmodel_listbefore the LiteLLM proxy starts.
Change exposed models through the wizard (./start.sh), or edit their selection variables in .env before running it. For a model outside the curated catalog, set OLLAMA_CUSTOM_MODELS or add a YAML entry. For an embedding entry, declare its output dimension with dim:. The wizard lists models with dim: 768 first, and the chosen model's dim sets LANGMEM_EMBEDDING_DIM (see Ollama Β§5).
At selection and warm repair, memory dimensions use the first active alias from catalog and explicit model selections. The order is Ollama, OpenAI, Anthropic, then OpenRouter. A custom winner without dimension metadata requires an explicit LANGMEM_EMBEDDING_DIM. Initβs host auto-import happens later.
volumes/litellm/config.yaml is rebuilt on every run, so direct edits there are overwritten. Per-provider routing rules baked into litellm-init:
-
Ollama rows:
model: ollama/<name>,api_base: $LITELLM_OLLAMA_UPSTREAM.render_model_listregisters two aliases per Ollama model:ollama/<name>and the bare<name>. Chat models use theollama_chat/adapter and embeddings useollama/(Β§7). -
OpenAI rows:
model: openai/<name>,api_key: $OPENAI_API_KEY. -
Anthropic rows:
model: anthropic/<name>,api_key: $ANTHROPIC_API_KEY. -
OpenRouter rows:
model: openrouter/<name>,api_key: $OPENROUTER_API_KEY.
Each cloud row gets its provider prefix once. A name that already has it (the catalog's openrouter/... ids, a wizard-saved row) is kept. A bare vendor/model OpenRouter id from a flag or manifest therefore still routes through OpenRouter. Clients always use the configured name as model_name.
The wizard's multiselect choices persist as comma-separated lists in .env so they survive across runs:
| Env var | Set by | Notes |
|---|---|---|
OLLAMA_USER_MODELS |
The Ollama models multiselect (Ollama Β§5). |
model_resolver computes the active set (every source); ollama-pull then pulls those models for container sources. |
OLLAMA_CUSTOM_MODELS |
Ollama "additional models to pull" free-text step. | Merged into the active set by model_resolver for every Ollama source. ollama-pull fetches them for container sources. For ollama-localhost, the bootstrapper pulls OLLAMA_USER_MODELS βͺ OLLAMA_CUSTOM_MODELS onto the host daemon at every start. |
OPENAI_USER_MODELS |
OpenAI multiselect (after live /v1/models fetch). |
model_resolver activates matching catalog entries; names not in the curated catalog are synthesized with generic capability defaults. |
ANTHROPIC_USER_MODELS |
Anthropic multiselect (after live /v1/models fetch). |
Same synthesize-on-missing handling as OpenAI. |
OPENROUTER_USER_MODELS |
OpenRouter multiselect (after live /api/v1/models fetch). |
Same synthesize-on-missing handling. |
To add a model outside the catalogs without the model picker, set *_USER_MODELS or OLLAMA_CUSTOM_MODELS in .env. Then run ./start.sh --no-tui and select the intended track when prompted. Atlas recreates init and the gateway so the generated model list takes effect. Plain docker compose up can leave an unchanged gateway running with its previous model list.
Note:
model_resolveractivates a provider only when it is enabled and keyed. Enabled meansCLOUD_<PROVIDER>_SOURCE=enabled; the bootstrapper derivesLITELLM_<PROVIDER>_ENABLEDfrom it at every start. Keyed means<PROVIDER>_API_KEYis set. To stop routing to a provider, setCLOUD_<PROVIDER>_SOURCE=disabled. Do not editLITELLM_<PROVIDER>_ENABLED; the next start overwrites it.
Default models follow the routed set. Before each launch, the bootstrapper checks defaults against this launch's registered models.
The defaults are LITELLM_DEFAULT_MODEL, LITELLM_VISION_MODEL and the embedding pair (LITELLM_EMBEDDING_MODEL, LANGMEM_EMBEDDING_MODEL).
If a default is known to be unrouted, Atlas selects model_resolver's best active replacement.
It prints Default model KEY: old -> new (reason). The embedding pair moves together.
Known unrouted cases include:
- an
ollama/*model while Ollama is not the engine; - an Ollama tag that is not selected;
- a model of a disabled cloud provider;
- a cloud model that is no longer selected.
It never replaces a routed default. It also leaves a consumer-declared model, the managed vLLM Metal model, and an Ollama tag under ollama-localhost with host auto-import on. A model of an enabled provider whose API key is missing is kept too; fix the key. A stale default with no replacement is a warning.
litellm-init renders volumes/litellm/config.yaml at startup. Two things are bind-mounted into the container, deliberately kept in separate dirs:
| Mount | Holds | Env var (default) | Resolved by |
|---|---|---|---|
bootstrapper/utils β /catalog:ro
|
resolver modules (model_resolver.py, llm_catalog.py, cloud_providers.py, litellm_settings.py, β¦) |
ATLAS_CATALOG_DIR (/catalog) |
init.py::_catalog_dir() |
services/{ollama,litellm}/models.yaml β /atlas-models/<svc>-models.yaml:ro
|
model catalogs (flat <svc>-models.yaml layout) |
ATLAS_MODELS_DIR (/atlas-models) |
llm_catalog._find_models_dir() β _find_yaml()
|
The mounts are separate because catalogs cannot be nested inside the read-only /catalog mount, and /catalog must be on sys.path for litellm-init's loose sibling imports. Read init.py::_catalog_dir() before you change this wiring. A new resolver module that litellm-init loads must use try: from utils import X / except ImportError: import X. It then works in the bootstrapper venv and in the container. Coverage: bootstrapper/tests/test_litellm_init_loose_imports.py and test_compose_nested_mounts.py.
A downstream integration can expose its own OpenAI-compatible routes, usually served by a backend plugin, as LiteLLM models. Declare a litellm_models block in atlas.consumer.yml; Consumer Manifest Reference Β§9 has the merge, validation and secret-handling contract.
Atlas merges these rows into model_list at every start; it does not call the LiteLLM admin API. The consumer's aliases appear in /v1/models with no registration script. Removing the manifest removes only that consumer's rows on the next start. Coverage: bootstrapper/tests/test_consumer_litellm_models.py, test_litellm_init_render.py::TestConsumerModelMerge, test_consumer_doctor.py.
LiteLLM ships two Ollama integrations and they are not interchangeable:
| Adapter | Hits Ollama at | Use for | Notes |
|---|---|---|---|
ollama_chat/<model> |
/api/chat |
Chat completions (/v1/chat/completions) |
Real OpenAI-shaped: multi-turn history, tool calls, vision payloads, and the Ollama-native think parameter all flow through. |
ollama/<model> |
/api/embed for embeddings; /api/generate for legacy completions |
Embeddings (/v1/embeddings) |
Required for embedding routes. Legacy chat calls flatten multi-turn history into one prompt; tool calls do not work and think is dropped. ollama_chat/ rejects /v1/embeddings with Unmapped LLM provider for this endpoint. |
Embedding endpoint source: the pinned LiteLLM adapter.
services/litellm/init/scripts/init.py::render_model_list uses the versioned catalog metadata below. Curated kind: embedding entries get ollama/; curated kind: chat entries get their declared adapter. A custom or live-discovered model without metadata uses the legacy name heuristic and logs a startup warning. Existing operator-defined models therefore keep working.
Catalog rows may declare metadata_version: 1. Its provider-neutral fields are kind (chat/embedding), adapter, capabilities, request_defaults (for example think: false), recommended_roles (extract, keyword, query, judge, embedding, vision) and an embedding's dim. The field schema is in the comments next to the loader in llm_catalog.py.
LiteLLM receives the standard model_info fields and a namespaced atlas_model_metadata block. Consumers can use it to select model roles without provider, model-family or hardware assumptions. A cloud model with no catalog row (for example one picked live from OpenAI) gets no top-level model_info.mode. LiteLLM's own model map then routes it, so a Responses-only model such as gpt-5-pro is not forced onto /v1/chat/completions.
These capabilities are declarations. ./start.sh models probe measures tool calling, JSON output, vision and embedding dimension through this gateway, on demand. It reports each declaration that does not hold and does not change model selection (see Operations Β§1.2).
Full metadata comes from the authenticated GET /v1/model/info. GET /v1/models is the compatibility listing and does not return the complete model_info payload:
curl -s http://localhost:${LITELLM_PORT}/v1/model/info \
-H "Authorization: Bearer ${LITELLM_MASTER_KEY}"For extract, query or another role, clients can choose a model from this metadata with the following procedure. Then configure the selected model through LightRAGβs role bindings or the consuming clientβs settings:
- Keep rows with
inferred: false, the requiredkindor capability, and the role inatlas_model_metadata.recommended_roles. - Apply an explicit operator preference when one is configured.
- Otherwise use lexical
(provider, catalog_name, model_name)order as the provider-neutral fallback. - Deduplicate Ollama's dual aliases by
(provider, catalog_name)and retain the operator's preferred alias.
The order is deterministic and assumes no provider, hardware or model family.
Ollama's reasoning models (qwen3, gpt-oss, deepseek-r1, β¦) split their output into a thinking channel and a content channel. The response arrives empty when the max_tokens budget runs out inside the <think> block, or when a consumer such as Hermes Agent reads only content.
init.py applies think: false only when a model's catalog request_defaults declares it. The default qwen3.8:latest catalog row declares it, so its answer goes into content instead of reasoning. Other chat models do not inherit it. Chat models without metadata keep the old default and log a warning.
To get the thinking trace, override it per request:
curl -s -X POST http://localhost:${LITELLM_PORT}/v1/chat/completions \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-d '{"model":"qwen3.8:latest","messages":[...],"think":true}'think: false is not added to embedding entries, because their ollama/ adapter does not accept it.
-
GET http://localhost:${LITELLM_PORT}/health/livelinessβ fast liveness check (no auth). -
GET http://localhost:${LITELLM_PORT}/v1/models(withAuthorization: Bearer $LITELLM_MASTER_KEY) β lists every model registered inmodel_list.
On the first database connection after a cold boot, the ${PROJECT_NAME}-supabase-db log shows a burst of relation "<β¦>" does not exist errors.
These concern the configured LiteLLM database. This is an upstream LiteLLM race.
Its 4 uvicorn workers each start Prisma and probe dashboard views while the views are being created.
The errors clear within tens of milliseconds and do not recur.
Before both database checks, set LITELLM_DB_NAME to the value in the active env file.
Unset or blank values use litellm. Use the raw name, not LITELLM_DB_NAME_URI.
Confirm that all 8 dashboard views exist:
docker exec -e PGPASSWORD="$SUPABASE_DB_PASSWORD" ${PROJECT_NAME}-supabase-db \
psql -U supabase_admin -d "${LITELLM_DB_NAME:-litellm}" -tAc "
SELECT count(*) FROM pg_views WHERE schemaname='public' AND viewname IN
('LiteLLM_VerificationTokenView','MonthlyGlobalSpend','Last30dKeysBySpend',
'Last30dModelsBySpend','MonthlyGlobalSpendPerKey','MonthlyGlobalSpendPerUserPerKey',
'DailyTagSpend','Last30dTopEndUsersSpend')"
# Expect: 8First confirm that the query reached the configured database and completed successfully. If views stay missing or startup errors persist, collect the init and gateway logs before escalation.
# Liveness
curl -s http://localhost:${LITELLM_PORT}/health/liveliness
# Chat completion (Ollama upstream)
curl -s -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-X POST http://localhost:${LITELLM_PORT}/v1/chat/completions \
-d '{"model":"ollama/qwen3.8:latest","messages":[{"role":"user","content":"hi"}]}'
# Embeddings (Ollama upstream β Weaviate uses this path)
curl -s -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-X POST http://localhost:${LITELLM_PORT}/v1/embeddings \
-d '{"model":"ollama/nomic-embed-text","input":"hi"}'
# Cache and spend audit
redis-cli -h localhost -p ${REDIS_PORT} -a "$REDIS_PASSWORD" --scan --pattern "litellm*"
psql -h localhost -p ${SUPABASE_DB_PORT} -U supabase_admin \
-d "${LITELLM_DB_NAME:-litellm}" \
-c "SELECT * FROM \"LiteLLM_SpendLogs\"
ORDER BY \"startTime\" DESC LIMIT 5;"-
ollama-pullcalls the Ollama upstream directly (/api/pull), because model pulls are not OpenAI-compatible. Compose sets itsOLLAMA_HOST_URLfromLITELLM_OLLAMA_UPSTREAM. It runs only for theollama-container-*sources; for other sourcesOLLAMA_PULL_SCALE=0. Forollama-localhost, the bootstrapper pulls onto the host daemon instead (Ollama Β§5). -
Open WebUI's native Ollama UI features (model pulls in the UI) are disabled β
ENABLE_OLLAMA_API: "false"is set in compose. To pull a model directly on anollama-container-*source, rundocker exec -it $PROJECT_NAME-ollama ollama pull <model>. Onollama-localhost, runollama pull <model>on the host.
If LiteLLM stops being a fit (license change, security incident, project drift), Portkey AI Gateway (Apache-2.0) is the documented fallback. The default consumers read LITELLM_BASE_URL and LITELLM_API_KEY, so the swap happens there. Migrate any native-provider overrides separately.
When LIGHTRAG_SOURCE != disabled, litellm-init registers a lightrag model that proxies to LightRAG's Ollama-compatible API ({LIGHTRAG_ENDPOINT}/api). A prefix on the last user message selects the query mode: /local, /global, /hybrid, /naive, /mix or /bypass. Without a prefix the mode is mix.
curl -sX POST http://localhost:${LITELLM_PORT}/v1/chat/completions \
-H "Authorization: Bearer ${LITELLM_MASTER_KEY}" \
-d '{"model":"lightrag","messages":[{"role":"user","content":"/hybrid What is RAG?"}]}'Support tier: experimental β Capability contract declared; no cited cold-start, workflow, or upgrade qualification run yet (evidence at v0.1.0).
| Capability | Status | Verification | Notes |
|---|---|---|---|
| Unified authenticated model gateway | supported | tested | Atlas exposes chat, embeddings, image generation, and reranking through one LiteLLM endpoint protected by the generated master key, with an explicitly credentialed admin UI. |
| Catalog-driven provider routing | supported | tested | Startup deterministically renders Ollama, cloud, service-passthrough, and consumer-declared model rows from typed catalogs and enabled provider configuration. |
| Gateway persistence and response caching | supported | tested | LiteLLM stores its control and spend data in a dedicated Supabase database and uses the authenticated shared Redis service for namespaced bounded-TTL response caching. |
| Vision-model default consumption | stubbed | documented | Atlas resolves and persists LITELLM_VISION_MODEL for selection UX, but the manifest explicitly has no current consumer route for that default. |
| Unified speech routing | not-supported | documented | STT and TTS consumers call their provider endpoints directly; LiteLLM does not register the stock audio transcription or speech routes. |
| Per-service gateway credentials and budgets | partial | documented | TrueForge normally uses a dedicated virtual key, with a master-key fallback on mint failure. Other stock consumers use the master key by default. Atlas provisions no per-service spend caps or team budgets. |
| Service | Category |
|---|---|
| langfuse | infra |
| otel-collector | infra |
| redis | data |
| supabase | data |
| cloud-providers | llm |
| ollama | llm |
| tei-reranker | llm |
| vllm-metal | llm |
| fal | media |
| hermes β | agents |
| lightrag β | agents |
| Service | Category | Status |
|---|---|---|
| kong | infra | current |
| prometheus | infra | current |
| weaviate | data | optional: only collections whose text2vec-openai baseURL is LiteLLM, as the backend's are |
| airflow | agents | current |
| celery | agents | current |
| hermes β | agents | current |
| lightrag β | agents | current |
| n8n | agents | current |
| openclaw | agents | optional: openclaw-init sets models.providers.litellm.baseUrl when unset; an operator value is kept |
| trueforge | agents | current |
| backend | apps | current |
| jupyterhub | apps | current |
| llm-graph-builder | apps | current |
| local-deep-researcher | apps | current |
| open-webui | apps | current |
| verba | apps | current |

Open the full-size diagram for a full-screen view.
-
litellm β minio β Why: LiteLLM ships a first-class S3 logger that persists full request/response payloads. MinIO is in the stack but unused for LLM telemetry β wiring it gives offline replay, prompt-regression diffs, and audit trails without a new dependency. Mechanism:
litellm_settings.success_callback: ["s3"]+s3_callback_paramspointing athttp://minio:9000; provision alitellm-logsbucket viaminio-init. Effort: small. Confidence: high. -
litellm β stt-provider β Why: LiteLLM exposes a unified
/v1/audio/transcriptionsendpoint, but consumers hitSTT_ENDPOINTdirectly today, bypassing LiteLLM's auth/rate-limit/spend/Kong-alias affordances. Mechanism: add anaudio_transcriptionrow inmodel_listwithmodel: openai/<name>+api_base: ${STT_ENDPOINT}(speaches is OpenAI-compatible; parakeet needs a thin shim). Effort: medium. Confidence: medium. -
litellm β tts-provider β Why: same argument as STT β LiteLLM has
/v1/audio/speechrouting; consumers hit TTS engines directly. Mechanism: TTS row inmodel_listwithmodel: openai/<voice>+api_base: ${TTS_ENDPOINT}for speaches; chatterbox (port 4123) is also OpenAI-compatible on/v1/audio/speech. Effort: medium. Confidence: medium. -
litellm β searxng β Why: LiteLLM's MCP servers feature lets a tool be advertised to every chat-completions client. Wiring searxng as a built-in
search_webtool gives open-webui/n8n/hermes/jupyterhub web search for free. Mechanism: define a LiteLLM MCP server inlitellm_settings.mcp_serverscallinghttp://searxng:8080/search?format=json. Effort: medium. Confidence: medium.
No high-confidence opportunities identified.
- Guardrails β Why pursue: presidio PII redaction, lakera prompt-injection scanning, hide-secrets β all configurable per virtual key. Stack handles user data but has zero LLM-side PII controls today. Effort: medium.
- Virtual keys + team budgets β Why pursue: TrueForge already uses a dedicated virtual key, with a master-key fallback on mint failure. Other stock consumers use the master key by default. Atlas provisions no per-service spend caps or team budgets. Extending virtual keys to n8n / jupyterhub / open-webui would support separate budgets and credential revocation. Effort: small.
- Semantic caching + per-key cache controls β Why pursue: basic Redis response caching is already enabled stack-wide; LiteLLM's embedding-similarity semantic cache and per-virtual-key TTL/namespace controls remain unused. Effort: small.
-
/v1/audio/transcriptions+/v1/audio/speechrouting β Why pursue: see pair-integrations above. Effort: medium. -
Fallback model chains β Why pursue: declare
fallbacks: [{"gpt-5": ["claude-opus", "ollama/qwen3.8"]}]so a cloud outage degrades gracefully to local Ollama. Effort: small.