Skip to main content
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.connections in config.json is reconciled on startup.
    • Mapping needs the new UserProvisioning:UpdateWorkloadIdentities permission, granted only to Admin. Changes write workload_identity.created, updated and deleted audit 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 allowedAudiences list next to the single audience, 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. parallel runs the check while the LLM responds and holds the response until the verdict, so only a block is enforced. parallel works for chat, text completion and Responses, and is refused for MCP rules. Docs
  • Noma Security AI-DR Guardrail Provider - New noma-security provider, authenticated with a client ID and secret. Noma block and ask decisions intervene, mask becomes redactions on message text, tool-call arguments and tool results, and streamed responses are scanned progressively. application_id is 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, deprecation Link headers 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 create action 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 and ui:// resources as the server sent them, to callers that declared MCP Apps. Aggregate /mcp never lists app-only tools and namespaces ui:// 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_required result 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 by round_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, webhook result_url, MCP discovery and every copyable URL in the UI carry the prefix. Helm gets basePath.
  • SOCKS5 and TLS-Inspecting Global Proxies - The global proxy accepts socks5, takes a ca_cert_pem to 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_identity instead 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_ip on, 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_sessions and billed at the container rate, including under previous_response_id and conversation. OpenAI image generation tool tokens are billed at the image model’s rates and show as image_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 like 30m alongside bare minutes.

⚙️ Upgrade Notes

  • Bearer access tokens must match the configured audience - When an SSO provider has audience set, 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 MCPGateway permissions - /api/oauth/config/* is no longer skipped by RBAC. Callers without MCPGateway permissions 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:UpdateWorkloadIdentities is 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_missing so 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/2 while all nodes were connected.
  • SSO Token Without exp - A signed SSO token with no exp claim 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 instructions are redacted, and values split across streamed raw response frames are redacted.
  • Relay Log DAC - Relay latency histograms and relay log deletion are scoped by RelayLogs DAC.
  • Relay Log Exports - Splunk keeps fractional relay upstream latency, and relay spans report error.type with the same failure classes as LLM calls (for example policy_access_denied instead of 403).
  • Virtual MCP Filter Under DAC - Listing Virtual MCPs filtered by mcp_client_id works under DAC and returns an exact total.
  • Scoped MCP Client Refetch - RequirePublicTarget, OpenAPIConfig, PerUserDiscovery and PendingVerification are kept when an MCP client config is read back under DAC.
  • Edge Inspect Session IDs - Edge inspect logs store the conversation ID in session_id instead of parent_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_control is kept on chat completion messages, and OpenAI-style prompt_cache_breakpoint markers become cache_control for 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 data keep 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_content keep their content, and a function_call_output with a name and no call_id keeps 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_text stream events emit Anthropic thinking deltas.
  • Streamed Web Search Query - Streamed Anthropic web_search blocks always carry the search query.
  • DeepSeek V3.2 on Bedrock - Leaked DSML tags are stripped, and stopSequences is omitted for Converse models that reject it.
  • Databricks Safeguards - The Anthropic-only safeguards param 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 /api paths 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_url no longer produces //, and every /mcp 401 carries WWW-Authenticate.
  • MCP Connections - Permanent connect errors stop retrying, invalid ca_cert_pem is 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, and tls_config is kept on per-user headers clients.
  • MCP Tool Calls - Upstream tools are called by their exact name, a tool’s error flag survives on /mcp and in Responses, every code mode call inside agent mode is logged, code mode meta tools go through governance, tool_execution_timeout applies 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_configs are checked before an update applies, deleting a client reloads its virtual keys and drops its prices, and max_instructions_length is 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 (default pre_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.
    Rolling back ent_add_service_account_workload_identities_table drops the table and deletes every workload identity mapping.
  • ent_add_user_provisioning_update_workload_identities_permission - Adds the UserProvisioning:UpdateWorkloadIdentities permission 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_discovery and the mcp_per_user_discoveries table with its indexes. Reversible: drops the indexes, table and column
  • add_mcp_client_pending_verification_column - Adds config_mcp_clients.pending_verification and 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_ip and user_email to 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 id and parent_request_id and backfill them once with a background MATERIALIZE 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 data loses source.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

🔌 If you are compiling plugin against this release - use following deps