- NPX
- Docker
- feat: dedicated provider keys API — keys are now managed via
/api/providers/{provider}/keysendpoints instead of being embedded in provider create/update payloads - feat: VK provider config key_ids now supports [”*”] wildcard to allow all keys; empty key_ids denies all; handler resolves wildcard to AllowAllKeys flag without DB key lookups
- feat: now plugins can start injecting logs at trace level. Just use
ctx.Log(schemas.LogLevelInfo, "Test log") - feat: add option to disable automatic MCP tool injection per request
- feat: virtual key MCP configs now act as an execution-time allow-list — tools not permitted by the VK are blocked at inference and MCP tool execution
- refactor: standardize empty array conventions in bifrost. Empty array means no tools/keys are allowed, [”*”] means all tools/keys are allowed.
- feat: add support for request level extra headers in MCP tool execution.
- fix: add support for
x-bf-mcp-include-clientsandx-bf-mcp-include-toolsrequest headers to filter MCP tools/list response when using bifrost as an MCP gateway. - refactor: parallelize model listing for providers to speed up startup time.
- fix: send back accumulated usage in MCP agent mode.
- feat: MCP configuration now supports assigning virtual keys with per-tool access control.
- feat: adds option to allow MCP clients to run on all virtual keys without explicit assignment.
- feat: add support for pricing overrides.
- feat: add StabilityAI provider support to Bedrock.
- fix: handle text, vtt, srt response formats in OpenAI transcription response.
What Changed (The Short Version)
v1.5.0 flips the meaning of empty arrays across all allow-list fields:| What you write | v1.4.x meaning | v1.5.0 meaning |
|---|---|---|
[] (empty array) | ✅ Allow all | ❌ Allow none (deny by default) |
["*"] (wildcard) | Not applicable | ✅ Allow all |
["a", "b"] | Only a and b | Only a and b (unchanged) |
- Provider key
modelsfield — which models a key can serve - Virtual Key
provider_configs[].allowed_models— which models a VK can use per provider - Virtual Key
provider_configs[].key_ids— which API keys a VK can use (also renamed fromallowed_keys) - Virtual Key
mcp_configs[].tools_to_execute— which MCP tools a VK can execute - Virtual Key
provider_configsitself — which providers a VK can access
allowed_keysfield renamed tokey_idsin VK provider configsweightfield is now optional (nullable) on VK provider configs
Automatic Migration for Existing Data
If you are running Bifrost with a database (SQLite or Postgres), all existing data is automatically migrated on startup. You do not need to manually update your database records.The following automatic migrations run on upgrade:
- All provider keys with
models: []are converted tomodels: ["*"] - All virtual key provider configs with
allowed_models: []are converted toallowed_models: ["*"] - All virtual keys with no
provider_configsget backfilled with all currently configured providers (withallowed_models: ["*"]andkey_ids: ["*"]) - All virtual keys with no
mcp_configsget backfilled with all currently connected MCP clients (withtools_to_execute: ["*"])
config.json or manage virtual keys via the API, you must update those manually using this guide.Breaking Change 1: Provider Key models Field
Who is affected: Anyone who configures provider keys in config.json or programmatically with the field models absent or set to [].What changed
Themodels field on a provider key previously defaulted to “allow all” when empty. It now means “allow none.” You must explicitly use ["*"] to allow a key to serve all models.- config.json
- Specific Model List (unchanged)
Before (v1.4.x):
models: [] → key served all modelsAfter (v1.5.0):models: ["*"] → key serves all modelsHow to update
Search yourconfig.json for any provider key that has "models": [] or no models field at all, and add "models": ["*"] to restore the “allow all” behavior.Breaking Change 2: Virtual Key allowed_models Field
Who is affected: Anyone who creates or updates Virtual Keys via config.json, the REST API, or the SDK with allowed_models absent or set to [].What changed
Theallowed_models field on a Virtual Key provider config previously defaulted to “allow all models for this provider” when empty. It now means “block all models from this provider.” You must use ["*"] to allow all models.- config.json
- REST API
Before (v1.4.x):Missing
allowed_models → all OpenAI models allowedAfter (v1.5.0):allowed_models: ["*"] → all OpenAI models allowedBreaking Change 3: Virtual Key Provider Configs — Deny-by-Default
Who is affected: Anyone creating Virtual Keys with noprovider_configs array (or an empty one), expecting those keys to have unrestricted provider access.What changed
In v1.4.x, a Virtual Key with noprovider_configs had access to all configured providers. In v1.5.0, a Virtual Key with no provider_configs blocks all providers by default.Before (v1.4.x): Virtual Key with provider_configs: [] → access to all providersAfter (v1.5.0): Virtual Key with provider_configs: [] → no provider access (all blocked)How to update
Every Virtual Key must now explicitly list the providers it is permitted to use. To allow access to all providers, add a config entry per provider with"allowed_models": ["*"].Breaking Change 4: allowed_keys Renamed to key_ids
Who is affected: Anyone using the allowed_keys field in Virtual Key provider configs in config.json or the REST API.What changed
The field used to restrict which provider API keys a Virtual Key can use has been renamed fromallowed_keys to key_ids. The semantics follow the same deny-by-default model as all other v1.5.0 whitelist fields:| Value | v1.4.x behavior | v1.5.0 behavior |
|---|---|---|
Field absent / [] | Allow all keys | Deny all keys |
["*"] | Not applicable | Allow all keys (explicit wildcard) |
["key-1"] | Only key-1 | Only key-1 (unchanged) |
Unlike
allowed_models, there is no automatic database migration for key_ids. The “allow all when empty” behavior is not preserved — an empty or omitted key_ids sets allow_all_keys: false internally, which blocks all key selection. You must explicitly use ["*"] to restore allow-all behavior.- Allow all keys (most common)
- Specific keys
- REST API
Before (v1.4.x): After (v1.5.0): must use
allowed_keys omitted or [] → all keys allowed["*"] explicitly — omitting key_ids or leaving it [] now blocks all keysBreaking Change 5: Virtual Key MCP tools_to_execute Field
Who is affected: Anyone configuring MCP tool filtering on Virtual Keys in config.json or the REST API.What changed
Thetools_to_execute field on a Virtual Key MCP config previously defaulted to “allow all tools” when empty. It now means “block all tools from this client.” You must use ["*"] to allow all tools.Additionally, the Virtual Key mcp_configs list itself now acts as a strict allow-list:- No
mcp_configs→ all MCP tools blocked for this VK mcp_configswith entries → only the listed clients and tools are accessible
- config.json
- REST API
Before (v1.4.x):Empty
tools_to_execute → all tools from my-tools-server allowedAfter (v1.5.0):["*"] → all tools from my-tools-server allowedmcp_configs | tools_to_execute | Result |
|---|---|---|
| Not configured | N/A | All MCP tools blocked |
[{ client: "X" }] | [] | All tools from X blocked |
[{ client: "X" }] | ["*"] | All tools from X allowed |
[{ client: "X" }] | ["tool-a"] | Only tool-a from X allowed |
[{ client: "X" }, { client: "Y" }] | ["*"] / ["*"] | All tools from X and Y allowed; all other clients blocked |
Breaking Change 6: weight Field is Now Optional
Who is affected: Anyone programmatically processing or constructing Virtual Key provider config objects via the API.What changed
Theweight field on a Virtual Key provider config was previously a required float64. It is now an optional nullable value (*float64). The new semantics:weight: 0.5— provider participates in weighted load balancingweight: nullor omitted — provider is configured and accessible but is excluded from weighted routing (it can still be used for directprovider/modelrequests or fallbacks)
weight field may now be null in API responses. Update any client code that assumes weight is always a number.anthropic/claude-3-5-sonnet-20241022 direct routing or as a manual fallback, but won’t receive any traffic from weighted load balancing.New Validation: WhiteList Rules
v1.5.0 introduces theWhiteList type, which enforces two new validation rules on all allow-list fields. The API now returns HTTP 400 if either rule is violated.Rule 1: Wildcard cannot be mixed with other values
["*"] is only valid when it is the sole element. Using it alongside specific values is a validation error.Rule 2: No duplicate values
allowed_models, key_ids, models (on provider keys), tools_to_execute, tools_to_auto_execute, and allowed_extra_headers.Complete Before/After Reference
Provider Key (config.json)
Before:Simple Virtual Key (config.json)
Before:Virtual Key with Key Restrictions (config.json)
Before:Virtual Key with MCP Tools (config.json)
Before:Full Virtual Key (REST API)
Before:Breaking Change 7: Compact plugin supports two new modes
Who is affected: Anyone using thecompact plugin.What changed
Thecompact plugin now supports two new modes:- Chat to responses fallback: If Chat completion API is hit for models that only support Responses API, the chat completion is routed via the responses API.
- OpenAI Compatible parameters dropping: If a model does not support any standard OpenAI compatible model parameter, it is dropped.
enable_litellm_fallbacks is removed and replaced with:compat.convert_text_to_chat: Enable text completion to chat completion fallback (original behavior)compat.convert_chat_to_responses: Enable chat completion to responses fallbackcompat.should_drop_params: Enable OpenAI Compatible parameters dropping
extra_fields.litellm_compatis removedextra_fields.dropped_compat_plugin_paramsreturns which parameters were dropped by this pluginextra_fields.converted_request_typereturns the type of convert to (NOTE: If the request is a streaming request, this will still be base request type. For streaming chat completions, converted_request_type will be “chat_completions” and not “chat_completion_stream”)
Breaking Change 8: Image Edits No Longer Supported on Replicate’s Image Generation Endpoint
Who is affected: Anyone using the Replicate provider to perform image editing operations via the/v1/images/generations endpoint (i.e., passing a source image or mask to generate a modified image).What changed
The/v1/images/generations endpoint on the Replicate provider previously accepted image editing parameters (source image + optional mask) alongside a generation prompt. This behavior is no longer supported — the endpoint now only handles pure image generation (text-to-image).Attempting to pass image editing parameters to /v1/images/generations on Replicate will return an error.How to update
If you were using Replicate for image editing via the generations endpoint, you have the following option:- Switch to the image edit endpoint
/v1/images/edits.
Support for image editing via the dedicated
/v1/images/edits endpoint on Replicate is also being removed in a follow-up release. If your workflow depends on Replicate-backed image editing, plan to migrate to an alternative provider.Breaking Change 9: Provider Keys API Separated from Provider API
Who is affected: Anyone who reads keys from provider API responses, or sends keys in provider create/update requests via the REST API.What changed
Provider key management has been separated into dedicated endpoints. Thekeys field has been removed from all provider API requests and responses.GET /api/providersandGET /api/providers/{provider}no longer return akeysfield.POST /api/providersno longer accepts akeysfield. Create the provider first, then add keys separately.PUT /api/providers/{provider}no longer accepts akeysfield. Existing keys are preserved as-is during provider updates.- The existing
GET /api/keysendpoint (flat key list across all providers) is unchanged.
New endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/providers/{provider}/keys | List all keys for a provider |
GET | /api/providers/{provider}/keys/{key_id} | Get a single key |
POST | /api/providers/{provider}/keys | Create a new key |
PUT | /api/providers/{provider}/keys/{key_id} | Update a key |
DELETE | /api/providers/{provider}/keys/{key_id} | Delete a key |
{ "keys": [...], "total": N }. All other endpoints return a single key object. Delete returns the deleted key for confirmation. Key values are always redacted in responses.Create key notes:idis auto-generated if omittedenableddefaults totrueif omittedvalueis required and must not be empty- Provider-specific config fields (
azure_key_config,vertex_key_config,bedrock_key_config,vllm_key_config) are supported as before - Keyless providers (e.g., Ollama) reject key creation with
400
How to update
Creating a provider with keys:Before (v1.4.x):Other behavioral changes
- Model discovery is automatically triggered after key create, update, and delete operations.
- Provider updates (
PUT /api/providers/{provider}) now invalidate key status caches, so key statuses refresh after provider config changes. - Existing keys are safe — no data migration is needed. All existing keys remain intact and accessible via the new endpoints.
Quick Migration Checklist
Use this checklist when upgrading to v1.5.0:Update provider key models in config.json
Find every provider key in your
config.json that has "models": [] or no models field. Add "models": ["*"] to each.Add allowed_models to every VK provider config
Find every
provider_configs entry in your Virtual Keys (in config.json and any automation that calls the API). Add "allowed_models": ["*"] if you want all models, or list specific models you want to allow.Ensure every VK has at least one provider config
Any Virtual Key with
"provider_configs": [] or no provider_configs will block all traffic. Add the providers you want to allow.Rename allowed_keys to key_ids and set explicit values
Search your
config.json and API calls for "allowed_keys" and rename it to "key_ids". Then:- If
allowed_keyswas omitted or[](previously meaning “allow all”), change to"key_ids": ["*"]— an empty or omittedkey_idsnow blocks all keys. - If
allowed_keyslisted specific key IDs, keep the same values — only the field name changes.
Update tools_to_execute for MCP configs
Change any
"tools_to_execute": [] to "tools_to_execute": ["*"] if you want to allow all tools. Ensure every VK that needs MCP access has at least one mcp_configs entry.Handle nullable weight in API consumers
If you parse the Virtual Key API response in your code, update the
weight field handler to accept null values in addition to numbers.Fix any invalid WhiteList values
Check that none of your lists mix
"*" with other values (e.g., ["*", "gpt-4o"]), and that none have duplicate entries. These will now be rejected with HTTP 400.Troubleshooting
All requests are returning 403/blocked after upgrade
This usually means a provider key hasmodels: [] or a Virtual Key has no provider_configs, or a provider config has allowed_models: []. Check the Bifrost logs — a blocked request will log which rule denied it.Fix: Follow the checklist above. Ensure models: ["*"] on provider keys and allowed_models: ["*"] on VK provider configs.MCP tools are not being injected / tool calls are blocked
The VK needs anmcp_configs entry for the MCP client, and that entry needs "tools_to_execute": ["*"] (or a specific tool list).Fix: Add or update the mcp_configs on the Virtual Key.API returning 400 on virtual key create/update
The most common cause is a whitelist validation failure — either["*", "gpt-4o"] mixing a wildcard with a specific value, or a duplicate value in a list.Fix: Use only ["*"] alone or a list of specific values without duplicates.Requests fail with “no keys available” or key selection errors after upgrade
A provider config withkey_ids omitted or set to [] now blocks all keys (allow_all_keys: false, no specific keys configured). This is different from allowed_models — there is no automatic migration for key_ids.Fix: Add "key_ids": ["*"] to any provider config that previously had allowed_keys: [] or no allowed_keys field.Provider create/update returns errors about keys field
The keys field has been removed from provider API payloads. Use the dedicated /api/providers/{provider}/keys endpoints to manage keys separately.Fix: Remove keys from your provider create/update requests. Create keys via POST /api/providers/{provider}/keys after creating the provider.Existing keys work fine but newly created keys are blocked
The automatic migration only updates existing data. New keys created after upgrade must follow the new semantics. Use["*"] for all allow-list fields where you want unrestricted access.- feat: add DisableAutoToolInject to MCPToolManagerConfig to suppress automatic MCP tool injection per request
- feat: add BifrostContextKeyMCPAddedTools to context to track MCP tools added to the request
- refactor: standardize empty array conventions in bifrost. Empty array means deny all, [”*”] means allow all for models/tools/keys.
- feat: add support for request-level extra headers in MCP tool execution using BifrostContextKeyMCPExtraHeaders key in context.
- fix: send back accumulated usage in MCP agent mode.
- feat: add StabilityAI provider support to Bedrock.
- fix: handle text, vtt, srt response formats in OpenAI transcription response.
- feat: add provider keys CRUD to configstore and in-memory store
- feat: add virtual key access management for MCP clients
- feat: adds option to allow MCP clients to run on all virtual keys
- feat: add image edit input view on logs
- refactor: replace string slice with WhiteList type for model restrictions
- refactor: blacklist models on new convention
- fix: add blacklisted model field in tableKeyFromSchemaKey
- feat: logging in plugins
- chore: adds migration guide for 1.5 and test fixes
- refactor: standardize empty array conventions for VK Provider & MCP Configs, and makes Provider Config weight optional for routing
- feat: VK MCP config now works as an AllowList
- refactor: standardize empty array conventions for VK Provider Config Allowed Keys
- refactor: standardize empty array conventions for allowed models
- refactor: replace string slices with WhiteList for allowlist fields
- feat: implement scoped pricing override
- refactor: custom pricing refactor
- feat: adds option to allow MCP clients to run on all virtual keys
- refactor: blacklist models on new convention
- chore: upgraded core to v1.5.0 and framework to v1.3.0
- chore: upgraded core to v1.5.0 and framework to v1.3.0
- feat: add image edit input view on logs
- feat: logging in plugins
- feat: implement scoped pricing override
- refactor: custom pricing refactor
- chore: upgraded core to v1.5.0 and framework to v1.3.0
- chore: upgraded core to v1.5.0 and framework to v1.3.0
- chore: upgraded core to v1.5.0 and framework to v1.3.0
- chore: upgraded core to v1.5.0 and framework to v1.3.0
- feat: implement scoped pricing override
- refactor: custom pricing refactor

