Skip to main content

Overview

The LiteLLM migration tool reads the entities from a running LiteLLM proxy and recreates them in Bifrost through the management API. It is a one-time, operator-run migration: point it at your LiteLLM deployment and your Bifrost gateway, and it will provision the equivalent providers, keys, governance entities, and virtual keys. It is distributed as an npx package:
npx @maximhq/bifrost-migration-cli
  • Read from LiteLLM APIs - reads from the LiteLLM management API, the LiteLLM config.yaml, and (optionally) the LiteLLM Postgres database. Both files and the database are needed because the management API masks secrets.
  • Dry-run first - set DRY_RUN=1 to print a full migration plan and report without writing anything to Bifrost.
  • Idempotent - re-running is safe. Entities that already exist (HTTP 409) are treated as success, and custom-provider names are deterministic.
  • Fault tolerant - a single bad record is logged and counted, but does not abort the rest of the migration.
This page covers the data migration tool, which moves your LiteLLM configuration and governance entities into Bifrost. If you instead want to keep using the LiteLLM SDK and point it at Bifrost, see the LiteLLM SDK integration.

What gets migrated

The tool migrates five entity types. They are processed in dependency order so that owner links resolve correctly:
OrderLiteLLM sourceBifrost targetNotes
1Model deploymentsProviders, provider keys, global model configsResolves credentials, structured Azure/Bedrock/Vertex creds, vllm/ollama per-key URLs, and custom providers
2OrganizationsCustomersorganization_alias becomes name
3TeamsTeamsLinked to the migrated customer via the org alias
4Internal usersUsers + team membershipsEmail required
5Virtual keysVirtual keysOwner is a team or customer; model allow-lists folded onto the VK
Models are migrated first so that virtual keys can attach to concrete provider keys by ID. Organizations are migrated before teams (a team links to its customer), and teams before users (a user links to its teams).

Prerequisites

1

A running LiteLLM proxy

You need the proxy URL and its admin/master key. To migrate encrypted secrets (model credentials stored in the database), you also need the LiteLLM config.yaml path and, for database-stored deployments, the Postgres connection URL and the salt key used to encrypt them.
2

A running Bifrost gateway

Bifrost must be reachable with its management API enabled. You need the gateway URL and a Bifrost API key with permission to create providers, keys, and governance entities.
3

Node.js

Required to run the tool via npx.
The migration only reads from LiteLLM. It never modifies your LiteLLM deployment.

Configuration

The tool is configured entirely through environment variables.
VariableRequiredDefaultDescription
LITELLM_URLYesBase URL of the LiteLLM proxy (e.g. http://localhost:4000).
LITELLM_MASTER_KEYYesLiteLLM admin/master key used to read entities from the management API.
LITELLM_CONFIGYesPath to the LiteLLM config.yaml. Read directly for unredacted credential references (env refs and literals).
BIFROST_URLYesBase URL of the Bifrost gateway (e.g. http://localhost:8080).
BIFROST_API_KEYYesBifrost API key (sent as a bearer token) for the management API.
LITELLM_DB_URLNoLiteLLM Postgres connection URL. Needed to decrypt credentials and budgets for deployments stored in the database. Omit if all models live in config.yaml.
LITELLM_SALT_KEYNoLITELLM_MASTER_KEYSalt key used to decrypt database-stored secrets. Falls back to the master key when unset.
DEFAULT_PROVIDERNoopenaiProvider assumed for a bare model name with no prefix and no custom_llm_provider (mirrors LiteLLM’s own default).
MAX_BUDGET_PERIODNo10YReset window applied to a budget that has a spend cap but no budget_duration. LiteLLM allows never-resetting budgets; Bifrost requires a window, so this long default stands in for “effectively never”.
DRY_RUNNo0Set to 1 to plan and report without writing to Bifrost.

Running the migration

1

Set the environment variables

export LITELLM_URL="http://localhost:4000"
export LITELLM_MASTER_KEY="sk-1234"
export LITELLM_CONFIG="/path/to/litellm/config.yaml"

# Only when models are stored in the LiteLLM database:
export LITELLM_DB_URL="postgresql://user:pass@localhost:5432/litellm"
export LITELLM_SALT_KEY="your-litellm-salt-key"

export BIFROST_URL="http://localhost:8080"
export BIFROST_API_KEY="your-bifrost-api-key"
2

Run a dry run and review the plan

DRY_RUN=1 npx @maximhq/bifrost-migration-cli
This prints what would be created and a report of everything that could not be carried over faithfully (skipped providers, unmapped models, dropped fields). Sample output:
fetched 12 model deployment(s) from LiteLLM; resolved 3 named credential(s) and 12 deployment param set(s)
PLAN provider "openai" (custom=false, base_url=""): 1 key(s)
       key "openai/OPENAI_API_KEY" models=[*]
PLAN model config source="gpt-4o" provider="openai" model="gpt-4o" budgets=1 rateLimit=true
dry-run: 4 provider(s), 6 model config(s) planned, no writes performed
REPORT skipped providers (1):
  - cohere (custom api_base is not supported for model "cohere/command-r")
3

Run the migration

Once the plan looks correct, run without DRY_RUN:
npx @maximhq/bifrost-migration-cli
The tool logs each write with an OK / FAIL / SKIP / WARN prefix and a per-entity summary:
OK   provider "openai" (custom=false, base_url="")
OK   key "openai/OPENAI_API_KEY" (models=[*])
OK   org "org-123" -> customer "Acme"
OK   team "team-abc" -> team "Platform" (customer=true)
OK   user "alice@acme.com" -> "usr_..."
OK   vkey "prod-key" (owner=team:Platform, providers=2)
done: 4 provider(s), 5 key(s), 6 model config(s) written, 0 failed
4

Verify in Bifrost

Check the migrated entities in the Bifrost UI or via the management API - providers and keys, customers, teams, users, and virtual keys. Pay attention to any REPORT and WARN lines from the run (see Mapping details and limitations).

How credentials are resolved

The LiteLLM management API masks secrets: /credentials shows values like os****KE and /model/info omits the api_key entirely. The tool therefore reads real credential material from two unredacted sources:
  • config.yaml - credential_list and model_list entries carry plaintext values: environment references like os.environ/FOO and literal keys.
  • The LiteLLM Postgres database (LITELLM_CredentialsTable, LITELLM_ProxyModelTable) - values are encrypted with the salt key and decrypted by the tool using LITELLM_SALT_KEY.
Credential values map onto Bifrost key values as follows:
LiteLLM valueBifrost key valueMeaning
os.environ/OPENAI_API_KEYenv.OPENAI_API_KEYResolved from the environment at runtime
sk-abc... (literal)sk-abc...Stored as a literal value
For environment-reference keys (env.FOO), the tool migrates the reference, not the resolved value. The corresponding environment variables must be set wherever Bifrost runs.

Mapping details and limitations

Budgets and rate limits

LiteLLMBifrostNotes
max_budgetbudgets[].max_limitOmitted when <= 0 (LiteLLM “no cap”).
budget_durationbudgets[].reset_durationmoM; other units (s, m, h, d, w) are identical.
max_budget with no durationreset_duration: MAX_BUDGET_PERIODDefaults to 10Y.
tpm_limitrate_limit.token_max_limitReset window 1m.
rpm_limitrate_limit.request_max_limitReset window 1m.
When the same actual model appears in multiple LiteLLM deployments, their model-level limits are folded into a single Bifrost model config using the lowest limit per dimension.

Provider name normalization

LiteLLM provider slugs are normalized to Bifrost standard provider names:
LiteLLMBifrost
vertex_ai, vertex_ai_betavertex
hosted_vllmvllm
ollama_chatollama
cohere_chatcohere
text-completion-openaiopenai
azure_aiazure
fireworks_aifireworks

Models and providers that are skipped

  • Partial wildcards (e.g. openai/gpt-4*) are not representable in Bifrost and are skipped.
  • Unsupported or unresolvable providers (including provider globs like */...) are skipped and reported.
  • Custom api_base on an unsupported base provider (anything outside openai, anthropic, gemini, bedrock) is skipped.
  • Deployments with no resolvable credential skip key creation but still create a model config for rate limits.
Bifrost has no organization-level model gates. Any model restriction a LiteLLM organization imposes is folded onto the virtual keys that belong to it, mirroring LiteLLM’s layered enforcement (a request must satisfy the key, team, and org restrictions).
  • A team inside a LiteLLM organization is linked to the migrated customer (resolved via the org alias). If the customer cannot be resolved, the team is created unlinked and a warning is logged.
  • A user is linked to the Bifrost teams matching its LiteLLM team memberships. Unresolvable links are warned and skipped.
  • A virtual key’s owner resolves to a Bifrost team (preferred) or customer - the two are mutually exclusive. If the owner cannot be resolved, the VK is created unlinked.

Provider compatibility

Bifrost natively supports the standard providers that also exist in LiteLLM, applying the name normalization above. These include anthropic, azure, bedrock, cerebras, cohere, elevenlabs, fireworks, gemini, groq, huggingface, mistral, nebius, ollama, openai, openrouter, perplexity, replicate, runway, vertex, vllm, and xai. LiteLLM also supports many OpenAI-compatible providers that are not Bifrost standard providers (for example deepseek, together_ai, sambanova, nvidia_nim, moonshot, hyperbolic). These can generally be modeled as Bifrost custom providers with the openai base provider and the provider’s OpenAI-compatible base URL.

Idempotency and re-running

The migration is safe to run multiple times:
  • Entities that already exist return HTTP 409 and are treated as success.
  • Custom-provider names are a deterministic hash of (base provider, api_base), so the same deployment always maps to the same provider.
  • Virtual keys whose allow-list covers “all proxy models” are expanded to all providers currently in Bifrost - not just those found during the run - so providers added between runs are also covered.
Re-running creates new virtual keys for any VK that was previously created unlinked or skipped, but it does not reconcile or update entities that already exist. Review the report after each run.

Troubleshooting

Secrets not decrypting / empty key values Database-stored credentials need LITELLM_DB_URL and the correct LITELLM_SALT_KEY. If the salt key differs from the master key, set it explicitly. Keys that resolve to empty are reported and skipped (model configs are still created). Providers showing up as skipped Check the REPORT skipped providers section. Common causes: a partial wildcard model, an unsupported provider, or a custom api_base on a base provider Bifrost cannot wrap. Teams or virtual keys created but are not linked Owner resolution depends on migration order and on aliases. Ensure organizations have an organization_alias and teams have a team_alias, and that the dependency chain (orgs → teams → users → VKs) completed without failures. Users skipped Bifrost requires an email. LiteLLM users with no user_email are skipped and listed in the report. Virtual keys work in Bifrost but old tokens fail VK token values are not migrated - Bifrost generates new ones. Re-issue the new sk-bf-* values to your callers. Provider create rejected during VK migration A virtual key can only reference providers that exist in Bifrost. If a provider’s migration failed, its allow-list entries are dropped and reported. Fix the provider migration and re-run.

Next steps