v2.5.0
Changelog
v2.5.0 moves the enterprise gateway onto OSS transports v2.5.0. Service accounts can now authenticate with workload identity: a workload sends a token from Entra, AWS or a trusted OIDC issuer instead of a stored key. Guardrails now apply to passthrough requests and responses, including streams, and input checks can run in parallel with the LLM call. Noma Security AI-DR is a new guardrail provider. The OSS release adds per-user MCP tool discovery, MCP Apps, serving under a base path, and Anthropic workload identity federation.✨ Features
- Workload Identity for Service Accounts - A workload can call inference endpoints with a token from its own platform and run as the Bifrost service account an admin connected it to. Supported sources are Entra managed identities and apps, AWS outbound identity federation (IAM role or IAM user ARN), and trusted OIDC issuers with presets for Okta, Auth0 and Keycloak. Tokens are verified on every request and never stored. Docs
- The service account sheet has a Workload identities tab to connect, enable, disable and remove workloads, with an optional required app role per connection.
- Admin API under
/api/workload-identity, with Entra directory search through Microsoft Graph. An Entra object ID is checked against the directory before it is saved, and a client ID is refused with the matching object ID to use. workload_identity.connectionsin config.json is reconciled on startup.- Mapping needs the new
UserProvisioning:UpdateWorkloadIdentitiespermission, granted only to Admin. Changes writeworkload_identity.created,updatedanddeletedaudit events and apply on every cluster node. - Issuer signing keys are fetched in advance on reload, so the first request does not wait for them.
- Several Audiences for SSO and the Auth Proxy - Every SSO provider takes an
allowedAudienceslist next to the singleaudience, and a token for any of them is accepted. The auth proxy accepts the union of both fields. The UI edits all audiences as one list. Existing single-audience configs keep working. - Guardrails on Passthrough Routes - Input and output guardrails now apply to passthrough requests and responses, streamed and non-streamed. Redactions and transforms are written back into the raw body. A typed route whose body cannot be read is refused when a rule could block it. Routes with no typed form, such as
/v1/files, pass through with a warning. Docs - Parallel Input Checks - Guardrail rules take
inputTiming.pre_call(default) finishes the input check before the request is sent.parallelruns the check while the LLM responds and holds the response until the verdict, so only a block is enforced.parallelworks for chat, text completion and Responses, and is refused for MCP rules. Docs - Noma Security AI-DR Guardrail Provider - New
noma-securityprovider, authenticated with a client ID and secret. Nomablockandaskdecisions intervene,maskbecomes redactions on message text, tool-call arguments and tool results, and streamed responses are scanned progressively.application_idis optional and defaults to the virtual key name. The client secret is encrypted at rest. Docs - Enterprise Under a Base Path -
server.base_path(or-base-path/BIFROST_BASE_PATH) now works for enterprise builds. Login redirects, the SSO PKCE cookie, the Edge gateway URL, deprecationLinkheaders and the license-only bootstrap carry the prefix. The SSO and SCIM setup wizard shows the exact redirect URI to paste into the identity provider. - Access Profiles on the MCP Server Access Tab - The MCP server view sheet lists the access profiles that grant the server, with their user counts. Results follow DAC. Backed by
GET /api/mcp/client/{id}/access-profiles. - Per-User MCP Discovery in Clusters - Per-user discovery cache evictions are broadcast to every node. A user’s discoveries are deleted with the user and kept when the user ID is remapped. The per-user OAuth and MCP headers sweep workers run only on the cluster leader.
- Enterprise UI Translations - Enterprise views use the dashboard’s i18n catalogs, so they follow the selected language. A
createaction URL param opens the create sheet on enterprise views, which the command palette uses.
🌎 Open Source Features
- MCP Per-User Tool Discovery - Per-user OAuth and per-user headers clients can set
per_user_discovery, so each caller sees the tools, prompts and resources their own credential unlocks on the MCP gateway. Discovery is stored at sign-in, shared across callers with identical results, and removed with the credential. A per-caller connect tool, caller counts in the sessions table and registry, and a Refresh tools action on the sessions page come with it. Turning it off sends a per-user OAuth server back to pending verification. - MCP Apps on the Gateway -
/mcp/<slug>serves MCP Apps tools andui://resources as the server sent them, to callers that declared MCP Apps. Aggregate/mcpnever lists app-only tools and namespacesui://URIs per client. App-only tools never reach models, tools are accepted by the names their own server gave them, and MCP logs record Apps use. - MCP Multi Round-Trip - Bifrost passes an upstream server’s
input_requiredresult through to a gateway caller that can answer it, and forwards callers’ declared capabilities upstream. MCP logs record each round and link a call’s rounds byround_trip_id. - Faster Boot with MCP Clients - MCP clients from config.json connect in the background, so an unreachable client no longer delays the HTTP listener.
- Serve Under a Base Path -
server.base_path(or-base-path/BIFROST_BASE_PATH) serves the API and UI under a URL prefix. Redirects, OAuth bootstrap URLs, webhookresult_url, MCP discovery and every copyable URL in the UI carry the prefix. Helm getsbasePath. - SOCKS5 and TLS-Inspecting Global Proxies - The global proxy accepts
socks5, takes aca_cert_pemto trust a TLS-inspecting proxy, and always verifies targets through the proxy. The Inference and API toggles now take effect. - Anthropic Workload Identity Federation - Anthropic keys (and custom providers with an Anthropic base) can carry
anthropic_key_config.workload_identityinstead of a static key. Bifrost exchanges the workload’s OIDC token for a short-lived access token and refreshes it before expiry. The key form gets an API Key / Workload Identity tab. Docs - Caller Identity on Logs - LLM, MCP and relay logs record the caller’s user email and, with
logs_store.capture_client_ipon, their client IP. Both show on log pages and in CSV exports, and export to object storage. - Relay Logs Match LLM Logs - The relay log store, API and UI reach parity with LLM logs: session and correlation ids, large payload previews, filters and capture behaviour. The relay detail header is redesigned and OpenAPI import moves to a side sheet.
- Multi-Value Metadata Filters - Log metadata filters accept several values per key.
- Gemini Interactions Billing - On
/genai_passthrough, the Interactions agent is recorded as the model, poll records name it, and each run is billed and counted as one request. - Container and Image Tool Billing - Containers started through OpenAI and Azure code interpreter and hosted shell, and Anthropic code execution, are counted on
usage.tool_usage.container_sessionsand billed at thecontainerrate, including underprevious_response_idandconversation. OpenAI image generation tool tokens are billed at the image model’s rates and show asimage_cost. - OpenAI 12h Prompt Cache - Prompt cache breakpoints accept a TTL, and 12h cache writes are priced from new datasheet columns.
- Complexity Router Confidence Thresholds - Decision model routers take confidence thresholds before they act on a classification.
- Optional Routing Rule IDs - config.json routing rules no longer need an
id. A rule without one matches the stored rule by name and scope, and a priority collision with an undeclared stored rule logs a warning instead of stopping startup. - Dashboard Languages - The dashboard is fully translated with i18next across 11 locales. Numbers and dates follow the selected language, non-English catalogs lazy-load, and the language toggle lives in client settings.
- Command Palette - Press ⌘K to jump anywhere in the workspace.
- MCP Server UI - The MCP server sheet splits into a read-only view and a settings editor, tool parameters toggle between table and JSON, extra access grants have their own registry, and code mode settings collapse into an accordion.
- Sticky Log Message Filter - The log detail messages filter persists across reloads.
- Duration Strings for
tool_sync_interval- Accepts values like30malongside bare minutes.
⚙️ Upgrade Notes
- Bearer access tokens must match the configured audience - When an SSO provider has
audienceset, access and ID tokens must be addressed to that audience or the client ID (and, for Entra, the App ID URI). Deployments that already set an audience start rejecting bearer tokens issued for other apps. With no audience set, behaviour is unchanged. - MCP OAuth config routes need
MCPGatewaypermissions -/api/oauth/config/*is no longer skipped by RBAC. Callers withoutMCPGatewaypermissions can no longer read an MCP OAuth config’s status or revoke its token. Sign-in routes stay open. - Workload identity mapping is Admin-only on upgrade -
UserProvisioning:UpdateWorkloadIdentitiesis granted only to Admin. Grant it to custom roles yourself if they need it.
🐞 Fixed
- Budget Requests After Propagation - Pending budget requests stay attached when access profile propagation re-creates budgets, so they stay listed, can be approved and still block duplicates.
- Budget Requests for Removed Budgets - Requests whose budget no longer exists are listed as
target_missingso an approver can deny them, instead of being hidden. - Home Budget Card - The pooled “Closest to limit” figure sums only budgeted profiles, and a tooltip shows each profile’s usage and limit.
- Broker Cluster Peer Count - Broker transport heartbeats no longer erase a peer’s stored membership, which showed
Peers 0/2while all nodes were connected. - SSO Token Without
exp- A signed SSO token with noexpclaim is refused instead of crashing the process. - Workload Identity Service Accounts Without a Role - Requests for a service account with no role are no longer refused as if the account were deleted.
- Guardrail Output Blocks Skip Fallbacks - An output-phase guardrail block is final and no longer triggers fallbacks.
- Guardrail Transforms on Raw Bodies - Provider transforms (for example Bedrock email masking) reach raw request and response bodies, and text Bifrost added (MCP server instructions) is not transformed.
- Guardrail Tool-Call Arguments - Local detectors scan decoded tool-call arguments, so escapes cannot hide a value, and an argument-only redaction that a raw body cannot carry fails open with a warning.
- Guardrail Streamed Raw Payloads - Raw provider payloads in held Chat and Responses streams match the redacted text.
- Log Store Redaction - Passthrough model parameters such as Responses
instructionsare redacted, and values split across streamed raw response frames are redacted. - Relay Log DAC - Relay latency histograms and relay log deletion are scoped by
RelayLogsDAC. - Relay Log Exports - Splunk keeps fractional relay upstream latency, and relay spans report
error.typewith the same failure classes as LLM calls (for examplepolicy_access_deniedinstead of403). - Virtual MCP Filter Under DAC - Listing Virtual MCPs filtered by
mcp_client_idworks under DAC and returns an exact total. - Scoped MCP Client Refetch -
RequirePublicTarget,OpenAPIConfig,PerUserDiscoveryandPendingVerificationare kept when an MCP client config is read back under DAC. - Edge Inspect Session IDs - Edge inspect logs store the conversation ID in
session_idinstead ofparent_request_id, so fallback chains and root listings are no longer confused. - Enterprise Boot with MCP Clients - Enterprise startup no longer waits for unreachable MCP clients.
- Users Table Role Badge - Every role badge shows the shield icon.
- Singulr AI Icon - The Singulr AI guardrail provider has a dark-mode icon.
- Anthropic Prompt Caching on Chat Messages - Message-level
cache_controlis kept on chat completion messages, and OpenAI-styleprompt_cache_breakpointmarkers becomecache_controlfor Claude on Anthropic and Bedrock. - Zero Token Usage - Explicitly reported zero token counts from OpenAI-compatible providers are preserved instead of dropped.
- Anthropic Web Tool Versions - Explicit web search and web fetch versions are kept instead of upgraded, and web search and code execution are dropped for Claude on Bedrock.
- Anthropic Empty Content - Responses requests drop empty text blocks instead of failing with a 400, and text documents with empty
datakeep their source type. - Claude Haiku 5.x Parameters - Haiku 5.x takes reasoning effort like Sonnet 5.x, sampling params are dropped, and custom Anthropic-based providers read their base provider’s capabilities.
- Codex on Claude - Codex’s client-side tool search runs as the caller’s own, a tool re-declared mid-session no longer fails as a duplicate after namespace flattening, and invalid tool arguments in history replay as
{}instead of a 500. - Codex on OpenAI Responses - Assistant messages carrying
encrypted_contentkeep their content, and afunction_call_outputwith a name and nocall_idkeeps its name. - Gemini Item IDs - Non-streamed Gemini item ids stay under 64 characters, reasoning items get ids, and Bedrock Mantle replay keeps them.
- vLLM and SGLang Reasoning - Unsigned thinking blocks and replayed reasoning content are kept, and raw
reasoning_textstream events emit Anthropic thinking deltas. - Streamed Web Search Query - Streamed Anthropic
web_searchblocks always carry the search query. - DeepSeek V3.2 on Bedrock - Leaked DSML tags are stripped, and
stopSequencesis omitted for Converse models that reject it. - Databricks Safeguards - The Anthropic-only
safeguardsparam is stripped from Databricks chat and Responses requests. - GitHub Copilot Tool Search - Tool search works without the beta header Copilot rejects.
- Chat to Responses Conversion - Assistant text next to tool calls is kept.
- Runware Async Output - Bifrost polls the task when a sync request turns async.
- Multi-Key Stored Objects - Follow-up calls on a stored response, container or video find the key that created it instead of returning 404.
- Routing Rule Fallbacks on 4xx - Routing-rule fallbacks run when the primary target returns a 4xx.
- Pricing Model Names - Pricing lookups match model names case-insensitively, and Azure Model Router deployments bill the served model’s tokens.
- Dropped Requests Skipped Post-Hooks - Requests rejected before reaching a provider worker (full queue, shutdown, cancelled wait) run their post-hooks, and telemetry no longer counts them as upstream traffic.
- ClickHouse Log Detail at Scale - Opening a single log no longer scans the whole logs table.
- Log Retention Lag - Postgres retention runs hourly, keeps draining past a short batch, and lets one replica drain each table. ClickHouse dedupes deletes per cutoff.
- Fallback Chain Banner - The banner shows only for real fallback attempts, not for session rows sharing a parent id.
- Realtime and Live Logging Headers - Setup-request headers reach realtime and Live log rows.
- Config-File-Only Mode Logs - The dashboard and MCP logs show in config-file-only mode.
- Unmatched API Paths - Unknown
/apipaths return a JSON 404 instead of the dashboard shell. - Config Sync - Unchanged framework URLs skip the URL accessibility check, and a config.json MCP client keeps its stored id.
- Relay Passthrough - Relays match passthrough for headers and streams.
- Drop-Params Key Aliases - Supported-param lookups resolve key aliases.
- Complexity Router Subagents - Complexity session state is scoped per subagent.
- MCP OAuth Server - ChatGPT and other CIMD clients sign in, including documents that list grants the server does not offer. A replayed authorization code revokes its grant, an expired virtual key cannot consent or refresh, a grant bound before an issuer change cannot refresh, a trailing slash in
issuer_urlno longer produces//, and every/mcp401 carriesWWW-Authenticate. - MCP Connections - Permanent connect errors stop retrying, invalid
ca_cert_pemis refused, a failed enable stays unstable with its checker retrying, TLS and SSE header edits apply to the live client, a per-call credential refreshes once on a 401, a tool’s own 401 is no longer treated as an upstream auth failure, andtls_configis kept on per-user headers clients. - MCP Tool Calls - Upstream tools are called by their exact name, a tool’s error flag survives on
/mcpand in Responses, every code mode call inside agent mode is logged, code mode meta tools go through governance,tool_execution_timeoutapplies to code mode and in-process clients, and timeout errors report the caller’s deadline. - MCP Admin API - Client create, rename, reconnect, OAuth and virtual key mistakes return 400, 404 or 409 instead of 500. Unknown auth types and per-user auth on SSE and STDIO are refused,
vk_configsare checked before an update applies, deleting a client reloads its virtual keys and drops its prices, andmax_instructions_lengthis returned in the client list. - MCP Per-User Auth - A revoke is not undone by a sign-in finishing during it, pending OAuth flows can be revoked from the sessions list, per-user headers keep their sample values as the admin credential, a stored OpenAPI credential cannot fill a caller-supplied header, and sign-in prompts no longer create MCP log rows.
- MCP Library - Invalid catalog entries are skipped, permanent fetch errors stop retrying, and a custom entry can reuse a deleted entry’s name.
🗄️ Database Migrations
Enterprise
- ent_add_guardrail_rule_input_timing_column - Adds
enterprise_guardrail_rules.input_timing(defaultpre_call), so existing rules keep finishing their input check before the LLM call. Reversible: rollback drops the column. - ent_add_service_account_workload_identities_table - Creates
enterprise_service_account_workload_identities, which maps a workload identity to the service account its requests run as. Reversible: rollback drops the table. - ent_add_user_provisioning_update_workload_identities_permission - Adds the
UserProvisioning:UpdateWorkloadIdentitiespermission and grants it to Admin only. Rollback is a no-op, so grants on customized roles are kept.
Open Source
- add_anthropic_workload_identity_column - Adds
config_keys.anthropic_workload_identity_json. Non-reversible: dropping it would delete every Anthropic key’s workload identity config. Additive, so older binaries ignore it - add_mcp_per_user_discoveries - Adds
config_mcp_clients.per_user_discoveryand themcp_per_user_discoveriestable with its indexes. Reversible: drops the indexes, table and column - add_mcp_client_pending_verification_column - Adds
config_mcp_clients.pending_verificationand backfills it to true for OAuth and per-user clients still awaiting verification. Reversible: drops the column - add_cache_creation_above_12hr_pricing_columns - Adds eight 12h cache write pricing columns. Reversible: drops them
- mcp_tool_logs_add_round_trip_id_column, logs_add_client_ip_column, logs_add_user_email_column - Add
round_trip_id,client_ipanduser_emailto the log tables. Reversible only while the columns are empty: rollback is refused once any row holds a value - relay_logs_add_session_id, relay_logs_add_correlation_columns, relay_logs_add_large_payload_response - Add session, correlation and preview columns to relay logs. Non-reversible: dropping them would lose recorded relay data
ClickHouse log stores add bloom-filter skip indexes on
idandparent_request_idand backfill them once with a backgroundMATERIALIZE INDEX. Startup does not wait for it.
🐙 Closed OSS Issues
- #3261 - Routing-rule fallbacks not invoked when primary target returns 4xx (chat completions)
- #6764 - Dashboard UI full multi-language i18n (i18next, 11 locales)
- #8037 - OpenAPI spec omits the 100-row clamp and default of 25 on paginated list endpoints
- #8712 - Message-level cache_control on chat messages is dropped, so Anthropic prompt caching never triggers
- #8749 - Custom OpenAI-compatible provider responses drop prompt_tokens/completion_tokens - only total_tokens survives
- #8849 - Anthropic route: a text document with empty
datalosessource.type, upstream 400 - #9150 - Anthropic /v1/messages overrides the client’s explicit web_search version, implicitly enabling code_execution
- #9316 - ClickHouse logs store: single-log detail scans the whole logs table, so the log drawer never loads
- #9318 - Anthropic Responses converter forwards empty text blocks, upstream rejects with 400
- #9324 - Persist message-type filter selection in the chat UI
- #9490 - Claude Haiku 5.5 behind a custom Anthropic-base provider: reasoning effort is dropped and temperature is forwarded
📀 Base OSS version
transports/v2.5.0
