Skip to main content
2.1.0

✨ Features

  • Virtual MCPs - Replace MCP Tool Groups with named tool bundles drawn from one or more MCP clients, managed at /api/mcp/virtual-mcps, declared under mcp.virtual_mcps in config.json (mcp.tool_groups is deprecated) and Helm bifrost.mcp.virtualMcps, assignable to virtual keys from the VK sheet, and served at /mcp/<endpoint_slug>. Direct MCP clients also get an endpoint_slug and are reachable at /mcp/<slug>. Tool whitelisting is now explicit: ["*"] grants all tools, [] grants none, a named list grants exactly those. Disabled clients and stale definitions are never served. /workspace/mcp-tool-groups redirects to the new Virtual MCPs page (#6746, #6747, #6748, #6749, #6750, #6751, #6791, #6826, #6872, #6873, #6874, #6904, #6905, #6919, #6957)
  • Databricks Provider - First-class databricks/<model> provider covering Model Serving and Unity AI Gateway with PAT or OAuth M2M auth via databricks_key_config (workspace_url, api_format, client_id/client_secret, forward_gateway_tags). Requests are sanitized per model against datasheet capabilities, reasoning_effort is translated to Anthropic thinking on Claude endpoints, remote images are inlined, native Responses calls fall back to chat emulation, and upstream error messages are surfaced. The UI adds the key form and a guided migration from a custom provider named databricks (#6665, #6666, #6667, #6668, #6669, #6670, #6671, #6676, #6679, #6770, #6876, #6958)
  • Semantic Complexity Routing - The keyword scorer in the complexity router is replaced by an embedding-based classifier over three tiers with curated exemplar phrases (backfilled by migration, 750 combined phrase cap), a pluggable vector store including an embedded chromem backend with cross-node warm coordination, an optional LLM classifier fallback (semantic.fallback: llm), and session-aware routing that keeps a session at its highest observed tier. New status, generations and retry endpoints under /api/routing/complexity-analyzer-*, complexity_* log columns and filters, and routing embedding/LLM request and cost counters. tier_boundaries is deprecated and ignored (#6163, #6164, #6165, #6166, #6167, #6168, #6177, #6282, #6317, #6722, #6727, #6807, #6838, #6846, #6865)
    The routing metadata field on responses and log rows is renamed from routing_debug to routing_metadata with no alias. Governance error codes virtual_key_not_found and virtual_key_blocked are renamed to access_not_found and access_blocked. Update any consumer matching on those names.
  • Per-Request Grants - Every request now settles its identity (virtual key, MCP JWT, WebSocket key, ephemeral secret, GenAI session) onto one resolved access grant that governance checks, charges and filters with, so checked and billed limits cannot diverge and async jobs, WebRTC relays and WebSocket upgrades keep their identity. MCP runs a single shared server with tool visibility decided per request by governance admission, and every models listing (including integration routes) is narrowed by resolved access. allow_on_all_virtual_keys on MCP clients is renamed to allow_by_default (old key still accepted), and the list filter all_virtual_keys becomes allowed_by_default (#6306, #6307, #6308, #6309, #6311, #6313, #6314, #6641, #6642, #6643, #6649, #6678, #6701, #6706, #6768, #6801, #6857)
  • Virtual Key Rotation Cooldown - New client.vk_rotation_cooldown setting (duration string, e.g. “5m”): after a rotation the previous key value keeps authenticating until the grace window expires. config.json VK sync now treats a changed value as an explicit rotation (with console warning) and recognizes the previously rotated-out value as “no change”.
  • Scheduled Virtual Key Rotation - Access profiles gain auto_rotation_interval (1h to 365d, off by default) with next_rotation_at and read-only last_rotation_at. A background job rotates managed keys in batches, honours the rotation cooldown, posts dashboard notifications and advances the schedule; a manual rotation inside the window is respected (#6806)
  • Allow All Providers on Virtual Keys - allow_all_providers on virtual keys, projects and access profiles grants every configured provider, including ones added later, without listing them in provider_configs. Explicit provider entries still apply their model lists, and budgets and rate limits are unchanged. Exposed in the VK sheet, the API, config.json and Helm. A VirtualKeyPruneGuard stops config.json reconciliation from pruning access-profile-owned keys (#6662, #6663, #6827, #6863, #6875, #6953, #6954)
  • Prompt Cache Auto-Injection - New provider prompt_cache block (auto_inject, ttl, cache_control_injection_points) synthesizes cache breakpoints for clients that send none, so agentic clients like Codex stop paying the cache-write rate every turn. Off by default, capped at four markers, never touches caller-supplied markers, overridable per request with x-bf-prompt-cache-auto-inject. Edited from a new Prompt Caching tab in the provider sheet and extended to the gpt-5.6 family (prompt_cache_breakpoint plus explicit cache mode) (#6697, #6698, #6699, #6700, #6753)
  • Azure DeepSeek Chat Completions Routing - Responses requests to Azure DeepSeek models from coding harnesses are routed to Chat Completions because the DeepSeek Responses endpoint rejects reasoning.effort; models without a Responses endpoint fall back the same way, including on Bedrock Mantle. Controlled by compat.azure_deepseek (default true). The compat plugin also logs every dropped parameter and request-type conversion as structured per-request log entries (#6326, #6634, #6737)
  • Native Passthrough Redaction - Guardrail PII redaction now applies to Anthropic Messages and Gemini GenAI passthrough traffic, rewriting only content-bearing fields, and to native SSE streams through a paused-buffer codec that rewrites content_block_delta text before release (#6365, #6386)
  • Video Job Accounting - Async video generation is billed at settlement: a settler polls jobs to a terminal state, prices from captured params or provider-reported dimensions with new resolution-banded per-second rates (480p, 720p, 1024p, 1080p, 4k), records failures at zero and parks unpriceable jobs for backfill. The batch_jobs table is generalised into a provider job table with kind and params columns, and the log detail sheet gains a Video Details block (#6672, #6673, #6674, #6675, #6728, #6839)
  • Webhook Deliveries Page - GET /api/webhooks/deliveries searches delivery history across all endpoints by endpoint, event, outcome, status class, request or delivery ID and time window, paginated by delivery group. A Webhooks → Deliveries page adds filters, live polling, manual redelivery and deep links from each endpoint, with a topbar breadcrumb trail (#6707, #6708, #6709, #6710, #6714, #6893)
  • Request ID Lookup and Period Comparison in Logs - Logs, stats and histogram endpoints accept an exact request_id that bypasses the time window; the search box auto-detects a UUID or id: prefix. GET /api/logs/stats?compare_to_previous=true returns the previous period, powering a segmented metric strip with sparklines and change badges (#6694, #6695, #6719, #6720, #6788)
  • Hidden Request Types - logs_store.hidden_request_types (Helm storage.logsStore.hiddenRequestTypes) hides whole request types such as count_tokens from every log read path without affecting writes, cost recalculation or access control; shown read-only under Config → Logging (#6890, #6891, #6892, #6894)
  • Tool Call Names Filter - Logs gain a tool_call_names column, recorded even when content logging is off, with a matching filter on the logs and histogram endpoints and in the logs sidebar (#6911, #6912, #6913)
  • Served and Canonical Model in Logs - The model the provider actually served is persisted as served_model and shown when it differs from the request, and the logs model column displays the canonical name with the requested name as fallback (#6602, #6693)
  • MCP Connection Failure Details - GET /api/mcp/clients returns last_failure (stage, message, timestamps) and per-node node_states, OAuth tokens record a status_reason, and the server sheet shows the failure in the state badge popover plus a credential block with scopes, refresh-token presence and expiry (#6780, #6794, #6795, #6796)
  • Scoped Model Limits and Quota Sources - Model configs and quota budgets carry a structured SourceRef naming what governs them, GET /api/governance/model-configs accepts a comma-separated scope, quota responses tag each budget and rate limit with its source and list every contributing rate_limits entry, and read-only scopes render as view-only in the UI with scope labels on budget and rate limit cells. Provider-scoped budgets now participate in load-balancing candidate exclusion (#6715, #6729, #6733, #6752, #6800, #6810, #6813, #6829, #6830, #6843, #6856, #6858, #6860)
  • Plugin Config Hash Reconciliation - The plugin version field is removed from config.json, the API, Helm and docs; a leftover key is ignored. Plugin sync is now driven by a SHA-256 hash of the config entry, so a changed entry syncs automatically. Custom Go plugins can use SecretVar in their config, and a plugin’s created_at survives updates (#6250, #6336, #6337, #6600, #6935)
  • Tracing Controls - New export_overhead_spans toggle (Helm and the Configure Tracing sheet) controls whether internal overhead spans are exported, converter work is split into finer span buckets, batch and video settlement emit spans from the async sweeper, and a Latency and Overhead Breakdown docs page explains the log detail view (#6588, #6637, #6939, #6945)
  • Log Level Tabs for Plugin and Routing Logs - Routing decision and plugin logs carry a level and can be filtered by it in the log detail view (#6811, #6814)
  • UI Improvements - Custom providers whose name collides with a first-party integration prompt a switch, virtual key reveal and copy events are audited through an enterprise hook, access-profile-managed keys get a fallback creation view, sheets get a refreshed design with sticky headers, the logs page handles small screens, cached and uncached input tokens are broken down in a tooltip, and the Raw JSON tab explains when raw storage is disabled (#6596, #6608, #6610, #6618, #6619, #6651, #6786, #6789, #6790, #6793, #6820, #6833, #6845, #6871, #6940, #6951)
  • Helm Chart Updates - Values and schema for projects, Databricks keys, access-profile mappings, VK rotation cooldown, virtual MCPs, allow_all_providers, hidden request types and guardrail send_all_conversation_turns; the SCIM block renders as-is when enabled: false (#6663, #6758, #6869, #6892, #6904, #6917, #6953)
  • Baseten on Hugging Face - Baseten is discoverable as a Hugging Face inference provider (thanks @nicolastoulemont!) (#6633)
  • Magic Hour in MCP Library - Magic Hour added to the MCP library (thanks @runshouse!) (#6691)

🐞 Fixed

  • Streaming Hangs and Connection Leaks - A patched fasthttp fixes a race when closing streams, abandoned streams are drained in the background so the upstream connection returns to the pool, streams that send only heartbeats after finish_reason now terminate, and a does_not_send_done_marker toggle on custom providers ends the stream at finish_reason for upstreams that never send [DONE] (#6799, #6802, #6803, #6948, #6960)
  • DeepSeek Reasoning Lost on Multi-Turn - Assistant reasoning_content is aliased instead of stripped for Groq and Cerebras, so thinking survives multi-turn requests on the OpenAI-compatible inbound (#6949)
  • Reasoning Summary Stream Events - summary_index, summary text and signatures are populated on reasoning_summary_* events for Anthropic, Bedrock and Gemini (#6902)
  • Responses-to-Chat finish_reason - Chat finish_reason is derived from the Responses terminal state and incomplete details instead of being dropped (#6901, #6920)
  • Anthropic Stream Truncation - response.incomplete and response.failed emit proper message_delta, message_stop and error events instead of truncating the stream, and a missing terminal text suffix is synthesized from output_text.done (#6159, #6805)
  • Anthropic-on-Vertex Passthrough - Usage and stream terminal detection for Anthropic models in Vertex GenAI passthrough mode go through the Anthropic parsers (#6639)
  • Anthropic Passthrough for Non-Claude Models - Raw-body passthrough is cleared based on the resolved provider and model pair, so non-Claude models on Vertex, Azure and Bedrock Mantle are converted instead of forwarded as Anthropic payloads, and it is also cleared when the provider does not support the output config format (#6798)
  • Unsupported Reasoning Signature - The encrypted reasoning signature is stripped when the upstream reports the field as unsupported, such as Bedrock Converse replaying a Claude signature onto a non-Anthropic model
  • Bedrock Reasoning Blocks - Unsigned reasoning blocks are dropped from Converse replays to Claude, which rejects them, while Nova and MiniMax keep receiving them, and native Grok or OpenAI reasoning summaries on Converse responses are rendered instead of dropped (#6834, #6942)
  • Bedrock Null Content on Empty Assistant Messages - An assistant message with no text and no tool calls no longer serializes as content:null, which Converse rejected outright (thanks @Jesse-Schultz-Relativity!) (#6732)
  • Bedrock Model Routing to Converse - Bedrock models route to the Converse API as intended (#6655)
  • GenAI Signature Drop - Standalone thoughtSignature parts with empty text are no longer dropped on native GenAI (#6745)
  • Ollama max_tokens - Ollama receives max_tokens instead of the unsupported max_completion_tokens (#6607)
  • Cohere Rerank Documents - Rerank documents are sent as Cohere v2 strings rather than objects (thanks @AdityaPainuli!) (#6654)
  • Nullable Response Fields - Spec-required nullable response fields are marshalled as null instead of omitted (thanks @PSR94!) (#6723)
  • Model Arrays from OpenAI-Compatible APIs - Top-level arrays returned by OpenAI-compatible model listings are accepted (thanks @dani29!) (#6712)
  • GPT-6 Astra Reasoning Effort - Max reasoning effort is preserved instead of being downgraded to high (thanks @nettee!) (#6881)
  • Forced Tool Choice - Anthropic tool_choice: any maps to required on OpenAI egress, gated on the provider capability flag (thanks @Atharva-Kanherkar!) (#6888, #6903)
  • Azure Reasoning Efforts - Reasoning effort handling for Azure-hosted models (#6877)
  • Thinking Block Modification Error - Replayed thinking blocks no longer trigger a modification error (#6854)
  • Custom Provider in List Models - Custom providers are skipped in list models when the request is not allowed to use them (#6853)
  • Vertex GenAI Model Names - Vertex GenAI resource model names are normalised to bare IDs for governance and key selection (#6918)
  • Allowed Models Wildcard - allowed_models: ["*"] no longer returns model_blocked when the live list-models store is empty for a provider (#6767)
  • OpenRouter Prompt Caching on Responses - cache_control breakpoints are translated correctly for OpenRouter Claude models on the Responses API (#6692)
  • Plugin Config Reverted on Restart - Plugin config edited via UI or API is no longer reverted from config.json on restart under source_of_truth: split; see Plugin Config Hash Reconciliation (#6250)
  • Realtime Observability and Auth - WebSocket Responses turns emit llm.call spans, realtime auth survives KV replication, and realtime WebSocket and WebRTC routes honour enforce_auth_on_inference (#6592, #6759, #6943)
  • Budget State Preserved Across Edits - Changing a budget’s reset frequency or fiscal-quarter setting no longer resets accumulated usage or drops quarter_start_month, new model budgets start empty, and budget IDs survive edits (#6810, #6813, #6932)
  • Routing Rule Persistence - Stale routing rules are deleted inside the merge transaction to avoid priority collisions, and rule reads honour the row-visibility query scope (#6638, #6934)
  • created_at Preserved on Sync - created_at survives config sync and updates for budgets, rate limits, teams, customers, model configs, pricing overrides, routing rules and plugins (#6616, #6792, #6935)
  • Vault Encryption Deadlocks at Boot - Rows are encrypted one per transaction with cursor pagination and concurrent vault writes, preventing deadlocks and boot hangs (#6808)
  • MCP Client Deletion - Legacy FK constraints on oauth_user_tokens and oauth_user_sessions are dropped so deleting an MCP client no longer fails, and the client ID is resolved before vault hooks run (#6648, #6812)
  • SSRF Hardening for MCP - Unauthenticated callers cannot register stdio MCP clients or private addresses, all MCP HTTP clients dial through the SSRF guard, and the Teredo prefix is blocked (#6757, #6760)
  • Rate Limits on Model-less Passthrough - Rate limits apply to passthrough requests that carry no model (#6774)
  • Redis Semantic Cache - Hex value fields are handled and the score filter is removed from the Redis store (#6772, #6773)
  • Prompt Child Scoping - Prompt child reads and writes are scoped to their parent prompt (#6761)
  • Billed Usage on Failed Requests - Tracing emits billed token and cost attributes on failed requests (thanks @vdemonchy!) (#6259)
  • File Response MIME Type - File responses carry the MIME type (#6684)
  • Logs Filter Search Case - Filter data search is case-insensitive on SQLite, Postgres and ClickHouse (#6915)
  • UI Fixes - Logout no longer cascades into 401s, the OSS build declares VKCreationPolicyResponse (thanks @markdawson!), virtual key loading state is consistent, managed VK state uses the server flag, and background polling pauses while an edit sheet is open (#6610, #6776, #6793, #6855, #6859)
  • Dependency and Security Updates - Dependabot and CodeQL fixes across modules (#6696, #6832, #6835, #6836, #6837)

🗄️ Database Migrations

  • backfill_default_complexity_exemplars_v2 - Rewrites the complexity_semantic_config governance row, appending curated default exemplar phrases and seeding the semantic row on pre-split installs. Non-reversible: appended default phrases cannot be distinguished safely from administrator-owned phrases.
  • add_vk_rotation_cooldown_columns - Adds previous_value, previous_value_hash, previous_value_expires_at, rotated_at and an index to governance_virtual_keys. Reversible: rolls back by dropping the columns.
  • add_vk_rotation_cooldown_client_column - Adds vk_rotation_cooldown_ns to config_client. Reversible: rolls back by dropping the column.
  • drop_legacy_oauth_user_fk_constraints - Drops the MCP client and virtual key FK constraints on oauth_user_tokens and oauth_user_sessions. Reversible: recreates the constraints, which can fail if orphan rows accumulated meanwhile.
  • add_virtual_mcp_tables - Creates the virtual MCP and VK-to-virtual-MCP tables, adds endpoint_slug and backfills unique slugs. Non-reversible: no rollback is defined.
  • add_video_resolution_pricing_columns - Adds resolution-banded video per-second rate columns to model_pricing. Non-reversible: dropping them would permanently delete custom per-resolution prices; the columns are additive and older binaries ignore them.
  • add_provider_job_kind_columns, swap_provider_job_indexes - Adds kind (default batch) and params to batch_jobs and swaps the identity and sweeper indexes to include kind, concurrently on Postgres. Reversible only while no non-batch jobs or captured params exist; otherwise the rollback refuses to avoid merging job namespaces and discarding pricing basis.
  • add_compat_azure_deepseek_column - Adds compat_azure_deepseek to config_client and sets it true on existing rows. Reversible: rolls back by dropping the column.
  • clear_plugin_config_hashes - Blanks config_hash on every plugin row so hash-based reconciliation starts clean. Non-reversible in effect: the rollback is a no-op.
  • add_mcp_oauth_token_status_reason_column - Adds status_reason to mcp_oauth_tokens. Reversible: rolls back by dropping the column.
  • add_databricks_key_config_columns - Adds the five databricks_* key columns. Reversible: rolls back by dropping the columns.
  • add_github_copilot_config_columns - Adds the five github_copilot_* key columns. Non-reversible: dropping them would permanently delete stored GitHub App private keys, which GitHub only issues once; the columns are additive and older binaries ignore them.
  • add_mcp_client_endpoint_slug - Adds endpoint_slug to config_mcp_clients and backfills a unique slug for every row, then builds the unique index concurrently. Non-reversible: the column and backfill step has no rollback; the index step drops cleanly.
  • add_allow_all_providers_to_virtual_key - Adds allow_all_providers (default false) to governance_virtual_keys. Reversible: rolls back by dropping the column.
  • backfill_vk_allow_all_providers_hash - Recomputes config_hash for every virtual key. Non-reversible in effect: the rollback is a no-op.
  • add_prompt_cache_json_column - Adds prompt_cache_json to the provider table. Reversible: rolls back by dropping the column.
  • Log store - Nine additive migrations (logs_add_complexity_routing_columns, logs_add_session_id_column, logs_add_routing_metadata_column, webhook_deliveries_add_filter_indexes_v1, logs_add_video_debug_column, logs_add_project_columns, mcp_tool_logs_add_project_columns, logs_add_served_model_column, logs_add_tool_call_names_column) add nullable columns to logs and mcp_tool_logs and filter indexes on webhook_deliveries. No backfill, no data rewrite. All reversible: each rolls back by dropping what it added.
    This release adds new columns to the log store. Each ADD COLUMN takes an ACCESS EXCLUSIVE lock on logs, the highest-volume table, and on Postgres the migration waits at most 5 seconds for that lock before failing the boot and retrying on the next one. Upgrade during a low-activity window so the lock is acquired immediately and no queries queue behind it.
    To apply the log store schema ahead of the upgrade, run the statements below against the log store database. They match what the migrator executes, and every statement is idempotent. After the DDL you must also record the nine migration IDs in the migrations table (shown after the SQLite block) so the next boot treats them as applied. Postgres:
    SQLite (no IF NOT EXISTS on ADD COLUMN; skip any column that already exists):
    Then record the migrations in the log store’s migrations table (Postgres and SQLite). Run in this order. On SQLite use CURRENT_TIMESTAMP instead of NOW():
    ClickHouse has no migration ledger; Bifrost reconciles missing columns on boot with ADD COLUMN IF NOT EXISTS (add ON CLUSTER when configured):

🐙 Closed GitHub Issues

  • #2765 - Bedrock provider does not sanitize empty content blocks (regression from #1189 fix)
  • #5887 - DeepSeek thinking silently lost on ALL multi-turn requests via OpenAI-compat inbound (v1.6.7; regression from v1.6.3)
  • #6073 - GenAI passthrough in Vertex mode breaks Anthropic models
  • #6132 - Ollama provider: max_tokens / max_completion_tokens silently dropped from forwarded request
  • #6143 - data race - fasthttp requestStream released to pool while SSE reader is still inside Read (stream cancellation)
  • #6180 - explicit prompt cache for Bedrock Mantle GPT-5.6 Responses
  • #6265 - Realtime/WebSocket Responses turns produce no llm.call span, so span-based observability connectors export them unattributed
  • #6290 - OpenRouter Claude prompt caching remains broken on Responses API
  • #6434 - Plugin config edited via UI/API is reverted from config.json on every restart under source_of_truth: split
  • #6624 - Bedrock reasoning signature field is dropped for Anthropic models, which require it present
  • #6631 - add Baseten to Hugging Face inference providers
  • #6640 - v2.0.0 rerank sends documents as objects ({"text": ...}) to Cohere-based custom providers, breaking servers that expect Cohere v2 strings
  • #6657 - Fireworks virtual key with allowed_models: [”*”] blocks every model (empty synced catalog; explicit list works)
  • #6689 - Responses omit spec-required nullable fields
  • #6690 - [MCP Library] Add: Magic Hour
  • #6711 - Support array responses from OpenAI-compatible model APIs
  • #6730 - Native GenAI drops empty text from standalone thoughtSignature parts
  • #6775 - OSS ui typecheck fails since #6618 (VKCreationPolicyResponse missing from fallback types)
  • #6784 - Chat completion stream hangs forever after finish_reason when upstream omits [DONE] but keeps sending heartbeats
  • #6831 - Responses-to-Chat mux drops non-streaming finish_reason
  • #6880 - GPT-6 Astra max reasoning effort is silently downgraded to high
  • #6887 - Anthropic tool_choice {type: any} forwarded to OpenAI as “any” instead of “required”
  • #6914 - Team current spend is reset after adjusting budget limit even when choosing Preserve Usage
1.8.5
  • fix: map forced tool choice any to required on OpenAI Responses and Chat egress (#6887) @Atharva-Kanherkar
  • [fix]: preserve max reasoning effort for GPT-6 Astra @nettee
  • fix: give a Bedrock message a placeholder text block instead of a null content field when it has no text and no tool calls - BedrockMessage.Content has no omitempty, so a message with empty text and no tool calls (or an empty tool_calls array) serialized as content:null, which Converse rejects with “Member must not be null” (#2765)
  • [fix]: marshal required nullable response fields as null @PSR94
  • fix: accept top-level arrays from OpenAI-compatible model APIs @dani29
  • feat: add Baseten to Hugging Face inference provider discovery @nicolastoulemont
  • fix: strip the encrypted reasoning signature when the upstream reports the field as unsupported (e.g. Bedrock Converse replaying a Claude signature onto a non-Anthropic model after a mid-conversation model switch), extending the existing unverifiable-signature fail-soft
  • fix: clear Anthropic raw-body passthrough based on the resolved provider and model pair, so non-Claude models on multi-family providers (Vertex, Azure, Bedrock Mantle) convert the request instead of passing the Anthropic payload through
  • feat: optionally synthesize prompt-cache breakpoints for requests that carry none, so agentic clients that emit no cache markers (Codex and similar) stop paying the cache-write rate on every turn; off by default per provider via prompt_cache.auto_inject, with cache_control_injection_points for role/index targeting, and extended to translate the marker into prompt_cache_breakpoint plus explicit cache mode on the gpt-5.6 family
  • fix: drop unsigned reasoning blocks from Bedrock Converse replays to Claude, which verifies the thinking signature and rejects a block without one in every serialisation; Nova and MiniMax keep receiving unsigned blocks with the field omitted. Gated on a new datasheet capability bedrock_requires_signed_reasoning with an Anthropic-family fallback (#6624)
  • fix: render reasoning the upstream actually returned on Bedrock Converse-shaped responses (/bedrock converse and the framework drop-ins that reuse it): a native Grok or OpenAI reasoning summary with no encrypted content was resolved through the request-direction redacted shape and silently dropped, so clients saw text only; the response direction now emits reasoningText for exposed text and keeps redactedContent for opaque blocks, while replays to Bedrock are unchanged @akshaydeo
  • feat: add Databricks as a first-class provider covering Model Serving and Unity AI Gateway with PAT or OAuth M2M auth, per-model parameter sanitization from datasheet capabilities, Claude reasoning translation, remote image inlining, Responses-to-chat fallback and surfaced upstream errors (#6665, #6676, #6770, #6958)
  • feat: add GitHub Copilot provider that mints installation tokens server-to-server from GitHub App credentials, with chat completions, Responses and list models (#6352, #6353, #6356)
  • feat: add virtual MCP server support, endpoint slugs for direct MCP servers, and config.json wiring for mcp.virtual_mcps (#6746, #6791, #6904)
  • feat: add the project governance dimension to request context, schemas and log payloads (#6702, #6705)
  • feat: settle per-request identity onto a grant at context conversion and rename AllowOnAllVirtualKeys to AllowByDefault with backward-compatible wire aliases (#6306, #6307, #6308, #6641, #6642, #6649)
  • feat: add allow_all_providers to virtual key schemas (#6662)
  • feat: add semantic complexity routing contracts, vector store and embedding executor, LLM classifier fallback, session-aware routing and the 750-phrase limit; rename BifrostCacheDebug, BifrostGuardrailDebug and BifrostRoutingDebug to *Metadata with type aliases, and rename the routing_debug field to routing_metadata (#6164, #6166, #6177, #6317, #6722, #6727)
  • feat: support native raw request redaction for Anthropic and Gemini passthrough and add RawStreamTextCodec with a paused buffer transform for native SSE redaction (#6365, #6386)
  • feat: route Azure DeepSeek Responses requests from coding harnesses to chat completions, fall back for models without a Responses endpoint, and gate it on compat.azure_deepseek (#6326, #6737)
  • feat: split converter processing into individual span buckets and add the overhead spans export toggle (#6588, #6945)
  • feat: persist the served model from the provider response (#6693)
  • feat: record MCPConnectionFailure on client state (#6794)
  • feat: remove the plugin version field in favour of hash-based reconciliation (#6250)
  • fix: patch fasthttp to remove races when closing streams, drain abandoned streams so upstream connections return to the pool, terminate streams that send only heartbeats after usage, and add does_not_send_done_marker for custom providers (#6799, #6802, #6948, #6960)
  • fix: alias assistant reasoning_content for Groq and Cerebras instead of stripping it (#6949)
  • fix: populate summary_index, summary text and signatures on reasoning_summary_* stream events for Anthropic, Bedrock and Gemini (#6902)
  • fix: derive chat finish_reason from the Responses terminal state and incomplete details (#6901)
  • fix: emit proper terminal events for Anthropic response.incomplete and response.failed instead of truncating, and synthesize a missing terminal text suffix from output_text.done (#6159, #6805)
  • fix: route Anthropic-on-Vertex passthrough usage and stream terminal detection through the Anthropic parsers (#6639)
  • fix: remove raw body passthrough when the provider does not support the output config format (#6798)
  • fix: route Bedrock models to Converse (#6655)
  • fix: keep standalone thoughtSignature parts with empty text on native GenAI (#6745)
  • fix: use max_tokens instead of max_completion_tokens for Ollama (#6607)
  • fix: send rerank documents as Cohere v2 strings, not objects (thanks @AdityaPainuli!) (#6654)
  • fix: handle reasoning efforts for Azure providers (#6877)
  • fix: thinking block modification error on replay (#6854)
  • fix: skip custom providers in list models when the request is not allowed to use them (#6853)
  • fix: pass the MIME type in file responses (#6684)
  • fix: retry video job polling and record video debug data (#6728)
  • fix: translate cache_control breakpoints for OpenRouter Claude models on the Responses API (#6692)
  • fix: block Teredo addresses in the dial-time SSRF guard and run MCP auth through SSRF checks (#6757, #6760)
1.6.1

✨ Features

  • Virtual Key Rotation Grace Period - New rotation-state columns on governance_virtual_keys (previous_value, previous_value_hash, previous_value_expires_at, rotated_at) with encryption support, plus a vk_rotation_cooldown client config setting (duration string, default 0 = immediate flip) controlling how long a rotated-out key value keeps authenticating.
  • feat: persist provider prompt_cache configuration (new prompt_cache_json column and migration), including on the read path cluster peers use to reload after a config broadcast
  • feat: add scheduled automatic virtual key rotation on access profiles via auto_rotation_interval (#6806)
  • feat: add the project governance dimension to log tables, filters, histograms, rankings and matviews with project_ids and project dimension support (#6702, #6704, #6705)
  • feat: add virtual MCP tables, CRUD, endpoint slugs for MCP clients and virtual key assignments (#6746, #6747, #6750, #6791, #6826)
  • feat: persist Databricks key config with DB columns, encryption, redaction, validation and merge support, and register Databricks in the pricing catalog (#6666, #6669)
  • feat: persist GitHub Copilot app credentials with encryption and redaction (#6354)
  • feat: add grants package for per-request identity, access and limits and wire grant creation into governance (#6306, #6307, #6308, #6641)
  • feat: add allow_all_providers to virtual keys with a hash backfill migration and VirtualKeyPruneGuard (#6662, #6863)
  • feat: replace framework/batchaccounting with framework/jobaccounting, generalise batch_jobs into a provider job table with kind and params, settle video jobs at completion, and add resolution-banded video pricing columns (#6672, #6673, #6674, #6675, #6728)
    TableBatchJob is now TableProviderJob and the JobStore, SweepStore, AggregateLogEmitter and UsageReporter interfaces are renamed. Go consumers of the accounting package must update.
  • feat: add semantic complexity routing config wire, migrations, vector stores with the chromem backend, LLM classifier fallback, session-aware routing, warm coordination and generation reclamation, and complexity_* plus session_id log columns (#6163, #6164, #6166, #6177, #6317, #6722, #6727, #6807, #6846)
  • feat: add request_id exact lookup, compare_to_previous on stats, served_model, tool_call_names, and hidden_request_types visibility filtering to the log store (#6693, #6694, #6719, #6890, #6911)
  • feat: add cross-endpoint GET /api/webhooks/deliveries search with filter indexes (#6708)
  • feat: record MCPConnectionFailure and OAuth token status_reason (#6794)
  • feat: replace user-scoped model configs with ExtraScopedIDsResolver, add structured SourceRef on model configs and quota budgets, multi-scope filtering, ScopedModelLimits, and list every contributing rate limit in quota responses (#6715, #6729, #6752, #6800, #6829, #6858)
  • feat: remove the plugin version field and reconcile plugins by config hash, support SecretVar in native plugin config, and preserve plugin created_at (#6250, #6600, #6935)
  • feat: add native raw request redaction and RawStreamTextCodec support (#6365, #6386)
  • feat: add compat_azure_deepseek client config column (#6737)
  • feat: wire tracing into async job settlement (#6939)
  • fix: emit billed usage token and cost attributes on failed requests (thanks @vdemonchy!) (#6259)
  • fix: preserve created_at across config sync and updates for budgets, rate limits, teams, customers, model configs, pricing overrides and routing rules (#6616, #6792)
  • fix: encrypt rows one per transaction with cursor pagination and concurrent vault writes to prevent deadlocks and boot hangs (#6808)
  • fix: drop legacy FK constraints on oauth_user_tokens and oauth_user_sessions that blocked MCP client deletion, and resolve the MCP client ID before vault hooks run (#6648, #6812)
  • fix: delete stale routing rules inside the merge transaction and honour the row-visibility query scope on rule reads (#6638, #6934)
  • fix: handle hex value fields and remove the score filter in the Redis vector store (#6772, #6773)
  • fix: make filter data search case-insensitive across SQLite, Postgres and ClickHouse (#6915)
  • fix: scope prompt child reads and writes to their parent prompt (#6761)
  • fix: honour allowed_models: ["*"] when the live list-models store is empty for a provider (#6767)
  • fix: patch fasthttp to remove races when closing streaming calls (#6799)
0.2.1
  • feat: route Azure DeepSeek Responses requests from coding harnesses to chat completions, fall back for models without a Responses endpoint, and gate it on the compat.azure_deepseek toggle (#6326, #6737)
  • feat: log every dropped parameter and request-type conversion as a structured per-request entry (#6634)
  • feat: persist the served model from the provider response (#6693)
1.7.1
  • feat: add the project dimension to governance context and permit evaluation, refusing requests that name a project outside their scope (#6702)
  • feat: resolve every request onto a single grant so limit assembly, enforcement and billing use one resolved access, and replace the per-VK MCP server map with MCPGatewayAdmitter admission (#6308, #6311, #6313, #6314, #6643, #6649, #6706, #6724, #6725)
  • feat: add virtual MCP support with VK assignments, slug endpoints and the explicit tool whitelisting convention, and stop serving disabled MCP clients (#6746, #6748, #6749, #6750, #6791, #6826, #6872)
  • feat: add allow_all_providers on virtual keys (#6662)
  • feat: add ScopedModelLimits, ProviderScopedModelLimitsInScope and the split GlobalProviderLimits/PermitModelLimits primitives so provider-scoped budgets take part in load-balancing candidate exclusion (#6729, #6800, #6810, #6856)
  • feat: rename AllowOnAllVirtualKeys to AllowByDefault with backward-compatible aliases (#6642)
  • feat: honour the rotation grace-period previous value in virtual key auth (#5439)
  • feat: require auth for realtime connections when enforced on inference (#6759)
  • feat: replace user-scoped model configs with ExtraScopedIDsResolver (#6715)
  • feat: add semantic complexity routing hooks and cachemetadata renames (#6164, #6166, #6177, #6722)
  • feat: add a focused usage snapshot for cheaper accounting reads (#6683)
  • fix: apply rate limits on model-less passthrough requests (#6774)
  • fix: honour allowed_models: ["*"] when the synced catalog is empty (#6767)
  • fix: update job accounting for the provider job table (#6673, #6674)
1.6.1
  • chore: upgraded core to v1.8.5 and framework to v1.6.1
1.7.1
  • feat: record tool_call_names and populate tool_calls on log entries (#6911, #6912, #6913)
  • feat: persist the served model from the provider response (#6693)
  • feat: add project, complexity routing and session ID columns to log entries (#6702, #6704, #6846, #6166, #6317)
  • feat: add log-level filtering to plugin and routing decision logs (#6811)
  • feat: record video job costs and debug data in job accounting (#6672, #6673, #6674, #6675, #6728)
  • feat: wire tracing into async jobs and split converter processing into span buckets (#6588, #6939)
  • feat: rename cache and routing debug payloads to metadata (#6722)
1.7.1
  • chore: upgraded core to v1.8.5 and framework to v1.6.1
1.6.1
  • chore: upgraded core to v1.8.5 and framework to v1.6.1
1.1.1
  • chore: upgraded core to v1.8.5 and framework to v1.6.1
1.5.1
  • feat: add project_id and project_name span attributes and metric labels (#6705)
  • feat: add the export_overhead_spans toggle to filter internal overhead spans (#6945)
  • feat: rename cache and routing debug attributes to metadata (#6722)
1.1.1
  • chore: upgraded core to v1.8.5 and framework to v1.6.1
1.0.1
  • feat: replace the keyword complexity scorer with a semantic classifier over three tiers and curated exemplars, add vector stores with the chromem backend, harness-aware input extraction, LLM classifier fallback, session-aware routing, cross-node warm coordination with generation reclamation, and a 750-phrase combined limit; tier_boundaries is deprecated and ignored (#6163, #6164, #6165, #6166, #6177, #6317, #6722, #6727, #6807, #6838, #6846)
  • feat: evaluate routing rules from a GovernanceScope read off the resolved access grant (#6308, #6313)
1.6.1
  • fix: handle hex value fields and remove the score filter in the Redis store (#6772, #6773)
  • feat: share vector store warm coordination and chromem cleanup with the complexity router (#6727, #6807)
  • feat: rename cache debug payloads to cache metadata (#6722)
1.6.1
  • feat: add project_id and project_name metric labels (#6705)
  • feat: add routing embedding and LLM classifier request and cost counters (#6166, #6177)
  • feat: rename cache and routing debug attributes to metadata (#6722)