{"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://www.getbifrost.ai/schema","title":"Bifrost Configuration Schema","description":"Schema for Bifrost HTTP transport configuration","type":"object","properties":{"$schema":{"type":"string","description":"Schema location for IDE validation. Defaults to \"https://www.getbifrost.ai/schema\" and can be set to a mirrored URL, file:// URL, or filesystem path for isolated deployments.","default":"https://www.getbifrost.ai/schema"},"server":{"type":"object","properties":{"read_buffer_size":{"type":"integer","description":"Read buffer size in bytes. This controls the size of the buffer used for reading HTTP headers.","default":65536}},"required":["read_buffer_size"]},"version":{"type":"integer","description":"Controls how empty arrays in allow-list fields (models, allowed_models, key_ids, tools_to_execute) are interpreted. Omit or set to 2 for v1.5.0+ semantics: empty = deny all, [\"*\"] = allow all. Set to 1 to restore v1.4.x semantics: empty = allow all.","enum":[1,2],"default":2},"source_of_truth":{"type":"string","description":"Controls how config.json is reconciled with the config store. \"split\" preserves existing merge behavior. \"config.json\" makes present config.json sections authoritative during startup sync; missing sections leave database rows untouched.","enum":["split","config.json"],"default":"split"},"encryption_key":{"type":"string","description":"You can set the value as env.<ENV_VAR_NAME> to use an environment variable. We also read encryption key from BIFROST_ENCRYPTION_KEY environment variable. Note: once set, the encryption key cannot be changed unless you clean up the database. Accepts any string; a secure 32-byte AES-256 key will be derived using Argon2id KDF. If not provided, data will be saved in plain text. Recommended: use a passphrase of at least 16 bytes for better security"},"env_label":{"type":"string","description":"Short label (max 10 characters) displayed in the management UI sidebar to identify the environment (e.g. \"staging\", \"prod\"). Overrides the BIFROST_ENV_LABEL environment variable when both are set.","maxLength":10},"auth_config":{"$ref":"#/$defs/auth_config"},"client":{"type":"object","description":"Client configuration settings","properties":{"drop_excess_requests":{"type":"boolean","description":"Whether to drop excess requests when pool is full"},"initial_pool_size":{"type":"integer","minimum":1,"description":"Initial size of the connection pool","default":300},"prometheus_labels":{"type":"array","items":{"type":"string"},"description":"Labels to use for Prometheus metrics"},"allowed_origins":{"type":"array","items":{"anyOf":[{"type":"string","const":"*"},{"type":"string","format":"uri"}]},"description":"CORS allowed origins (supports \"*\" or URI strings)"},"enable_logging":{"type":"boolean","description":"Enable request/response logging"},"disable_content_logging":{"type":"boolean","description":"Disable logging of sensitive content (inputs, outputs, embeddings, etc.)"},"allow_per_request_content_storage_override":{"type":"boolean","description":"Allow individual requests to override content storage via the x-bf-disable-content-logging header or context key, and to opt in to raw-byte persistence in logs via x-bf-store-raw-request-response. When false (default), the global disable_content_logging setting is authoritative and per-request storage overrides are ignored. Does not control sending raw bytes back to callers — see allow_per_request_raw_override.","default":false},"allow_per_request_raw_override":{"type":"boolean","description":"Allow individual requests to send raw provider request/response bytes back to the caller via the x-bf-send-back-raw-request and x-bf-send-back-raw-response headers. When false (default), the provider-level send_back_raw_request/response settings are authoritative and per-request overrides are ignored. Does not affect raw-byte persistence in logs — see allow_per_request_content_storage_override.","default":false},"disable_db_pings_in_health":{"type":"boolean","description":"Disable DB pings in health check","default":false},"dump_errors_in_console_logs":{"type":"boolean","description":"Dump full error details to the server console logs. Useful for debugging; may be noisy in production.","default":false},"log_retention_days":{"type":"integer","minimum":1,"description":"Number of days to retain logs","default":365},"enforce_governance_header":{"type":"boolean","description":"Deprecated: use enforce_auth_on_inference"},"enforce_auth_on_inference":{"type":"boolean","description":"Require auth (VK, API key, or user token) on inference endpoints"},"dual_credential_conflict_behavior":{"type":"string","enum":["error","prefer_vk","prefer_idp"],"description":"Controls behavior when an inference request carries both an IDP access token (Authorization: Bearer <jwt>) and a virtual key (x-bf-vk header). 'error' rejects with 400. 'prefer_vk' drops the IDP token and authenticates via the VK. 'prefer_idp' (default) uses the IDP token for identity."},"enforce_scim_auth":{"type":"boolean","description":"Deprecated: use enforce_auth_on_inference"},"max_request_body_size_mb":{"type":"integer","minimum":1,"description":"Maximum request body size in MB"},"compat":{"type":"object","description":"Compat plugin configuration for request type conversion, parameter dropping, and parameter value conversion","properties":{"convert_text_to_chat":{"type":"boolean","description":"Convert text completion requests to chat for models that only support chat"},"convert_chat_to_responses":{"type":"boolean","description":"Convert chat completion requests to responses for models that only support responses"},"should_drop_params":{"type":"boolean","description":"Drop unsupported parameters based on model catalog allowlist"},"should_convert_params":{"type":"boolean","description":"Converts model parameter values that are not supported by the model.","default":false}},"additionalProperties":false},"header_filter_config":{"type":"object","description":"Global header filtering configuration for x-bf-eh-* headers forwarded to LLM providers","properties":{"allowlist":{"type":"array","items":{"type":"string"},"description":"If non-empty, only these headers (from x-bf-eh-* prefix) are allowed to be forwarded"},"denylist":{"type":"array","items":{"type":"string"},"description":"Headers to always block from being forwarded"}},"additionalProperties":false},"async_job_result_ttl":{"type":"integer","description":"Default TTL for async job results in seconds (default: 3600 = 1 hour)","default":3600,"minimum":1},"required_headers":{"type":"array","items":{"type":"string"},"description":"Headers that must be present on every request. Requests missing any of these headers are rejected with 400. Case-insensitive matching."},"logging_headers":{"type":"array","items":{"type":"string"},"description":"Headers to capture in log metadata. Values are extracted from incoming requests and stored in the metadata field of log entries."},"whitelisted_routes":{"type":"array","items":{"type":"string"},"description":"Routes that bypass auth middleware. Requests to these exact paths skip authentication checks."},"hide_deleted_virtual_keys_in_filters":{"type":"boolean","description":"When true, deleted virtual keys are omitted from logs and MCP logs filter data.","default":false},"allowed_headers":{"type":"array","items":{"type":"string"},"description":"Additional allowed headers for CORS and WebSocket"},"allow_direct_keys":{"type":"boolean","description":"Allow callers to bypass the registered key pool by supplying x-bf-direct-key: true and the provider's raw API key in an Authorization (Bearer), x-api-key, or x-goog-api-key header.","default":false},"mcp_agent_depth":{"type":"integer","minimum":1,"description":"DEPRECATED: Maximum depth for MCP agent mode tool execution. Use mcp.tool_manager_config.max_agent_depth.","default":10},"mcp_tool_execution_timeout":{"type":"integer","minimum":1,"description":"DEPRECATED: Timeout for individual MCP tool execution in seconds. Use mcp.tool_manager_config.tool_execution_timeout.","default":30},"mcp_code_mode_binding_level":{"type":"string","enum":["server","tool"],"description":"DEPRECATED: Code mode binding level for MCP tools. Use mcp.tool_manager_config.code_mode_binding_level."},"mcp_tool_sync_interval":{"type":"integer","minimum":0,"description":"DEPRECATED: Global tool sync interval in minutes (0 = disabled). Use mcp.tool_sync_interval.","default":10},"mcp_disable_auto_tool_inject":{"type":"boolean","description":"DEPRECATED: When true, MCP tools are not automatically injected into requests. Use mcp.tool_manager_config.disable_auto_tool_inject.","default":false},"mcp_enable_temp_token_auth":{"type":"boolean","description":"When true, Bifrost mints and accepts scoped temp tokens for MCP per-user OAuth and per-user-headers auth pages so anonymous browser visitors can complete the flow without a dashboard session. User-mode flows are never minted regardless of this setting — they always require SSO login.","default":false},"routing_chain_max_depth":{"type":"integer","minimum":1,"description":"Maximum depth for routing rule chain evaluation","default":10},"mcp_external_client_url":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}],"description":"Public base URL Bifrost uses as the redirect_uri when acting as an OAuth client to upstream MCP servers (Notion, Jira, etc.). Set when Bifrost's callback endpoint is reached via a different URL than its server-side metadata. Supports env var syntax: \"env.MY_VAR\"."},"mcp_server_auth_mode":{"type":"string","enum":["headers","both","oauth"],"description":"How /mcp authenticates inbound MCP clients. 'headers' (default): VK/api-key/session headers only, discovery disabled. 'both': accepts header credentials and Bifrost-issued JWTs, discovery enabled. 'oauth': Bifrost JWTs only — WARNING: disables VK/header MCP access."},"oauth2_server_config":{"type":"object","properties":{"issuer_url":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}],"description":"Stable public URL advertised as the OAuth2 AS issuer in discovery documents and JWT iss claim. Required for multi-host deployments; single-host deployments can omit this (falls back to request Host header). Supports env var syntax: \"env.MY_VAR\"."},"auth_code_ttl":{"type":"integer","minimum":1,"maximum":900,"default":300,"description":"Lifetime of the single-use authorization code in seconds (default: 300, max: 900 = 15 minutes)."},"access_token_ttl":{"type":"integer","minimum":1,"default":600,"description":"Lifetime of the issued JWT Bearer token in seconds (default: 600)."},"disable_vk_identity":{"type":"boolean","default":false,"description":"When true, the OAuth consent flow no longer offers or accepts virtual-key identity and existing virtual-key grants lose access immediately (rejected at request time and unable to refresh). Honored only when an identity provider is configured. Only valid when mcp_server_auth_mode is 'oauth'."}},"additionalProperties":false,"description":"OAuth2 authorization server settings for /mcp. Only relevant when mcp_server_auth_mode is 'both' or 'oauth'."}},"additionalProperties":false},"framework":{"type":"object","properties":{"pricing":{"$ref":"#/$defs/pricing_config"}},"additionalProperties":false},"providers":{"type":"object","description":"AI provider configurations","properties":{"openai":{"$ref":"#/$defs/provider"},"anthropic":{"$ref":"#/$defs/provider"},"bedrock":{"$ref":"#/$defs/provider_with_bedrock_config"},"bedrock_mantle":{"$ref":"#/$defs/provider_with_bedrock_mantle_config"},"cohere":{"$ref":"#/$defs/provider"},"azure":{"$ref":"#/$defs/provider_with_azure_config"},"vertex":{"$ref":"#/$defs/provider_with_vertex_config"},"mistral":{"$ref":"#/$defs/provider"},"ollama":{"$ref":"#/$defs/provider_with_ollama_config"},"groq":{"$ref":"#/$defs/provider"},"gemini":{"$ref":"#/$defs/provider"},"opencode-go":{"$ref":"#/$defs/provider"},"opencode-zen":{"$ref":"#/$defs/provider"},"openrouter":{"$ref":"#/$defs/provider"},"sgl":{"$ref":"#/$defs/provider_with_sgl_config"},"parasail":{"$ref":"#/$defs/provider"},"perplexity":{"$ref":"#/$defs/provider"},"replicate":{"$ref":"#/$defs/provider_with_replicate_config"},"elevenlabs":{"$ref":"#/$defs/provider"},"cerebras":{"$ref":"#/$defs/provider"},"deepseek":{"$ref":"#/$defs/provider"},"vllm":{"$ref":"#/$defs/provider_with_vllm_config"},"huggingface":{"$ref":"#/$defs/provider"},"fireworks":{"$ref":"#/$defs/provider"},"nebius":{"$ref":"#/$defs/provider"},"xai":{"$ref":"#/$defs/provider"},"runway":{"$ref":"#/$defs/provider"},"runware":{"$ref":"#/$defs/provider"},"sarvam":{"$ref":"#/$defs/provider"}},"additionalProperties":true},"governance":{"type":"object","description":"Governance configuration for budgets, rate limits, customers, teams, virtual keys, and routing rules","properties":{"budgets":{"type":"array","description":"Budget configurations","items":{"type":"object","properties":{"id":{"type":"string","description":"Budget ID"},"max_limit":{"type":"number","description":"Maximum budget limit in dollars"},"reset_duration":{"type":"string","description":"Budget reset duration (e.g., '30s', '5m', '1h', '1d', '1w', '1M', '1Y')"},"current_usage":{"type":"number","description":"Current usage in dollars","default":0},"last_reset":{"type":"string","format":"date-time","description":"Last time budget was reset"},"virtual_key_id":{"type":"string","description":"ID of the virtual key this budget belongs to (mutually exclusive with provider_config_id)"},"provider_config_id":{"type":"integer","description":"ID of the provider config this budget belongs to (mutually exclusive with virtual_key_id)"},"model_config_id":{"type":"string","description":"ID of the model config this budget belongs to (mutually exclusive with the other owner IDs)"},"customer_id":{"type":"string","description":"ID of the customer this budget belongs to (mutually exclusive with the other owner IDs)"},"team_id":{"type":"string","description":"ID of the team this budget belongs to (mutually exclusive with virtual_key_id and provider_config_id)"},"calendar_aligned":{"type":"boolean","description":"Deprecated: set calendar_aligned on the owner (team / virtual key / access profile) instead. Kept for backward compatibility with older config.json files; ignored unless a reconciler promotes it to its owner.","default":false}},"required":["id","max_limit","reset_duration"],"additionalProperties":false}},"rate_limits":{"type":"array","description":"Rate limit configurations","items":{"type":"object","properties":{"id":{"type":"string","description":"Rate limit ID"},"token_max_limit":{"type":"integer","description":"Maximum tokens allowed"},"token_reset_duration":{"type":"string","description":"Token reset duration (e.g., '30s', '5m', '1h', '1d', '1w', '1M', '1Y')"},"token_current_usage":{"type":"integer","description":"Current token usage","default":0},"token_last_reset":{"type":"string","format":"date-time","description":"Last time token counter was reset"},"request_max_limit":{"type":"integer","description":"Maximum requests allowed"},"request_reset_duration":{"type":"string","description":"Request reset duration (e.g., '30s', '5m', '1h', '1d', '1w', '1M', '1Y')"},"request_current_usage":{"type":"integer","description":"Current request usage","default":0},"request_last_reset":{"type":"string","format":"date-time","description":"Last time request counter was reset"},"calendar_aligned":{"type":"boolean","description":"Deprecated: set calendar_aligned on the owner (team / virtual key / access profile) instead. Kept for backward compatibility with older config.json files; ignored unless a reconciler promotes it to its owner.","default":false}},"required":["id"],"additionalProperties":false}},"customers":{"type":"array","description":"Customer configurations","items":{"type":"object","properties":{"id":{"type":"string","description":"Customer ID"},"name":{"type":"string","description":"Customer name"},"budgets":{"type":"array","description":"Inline budget configurations for this customer. Each entry must have a unique reset_duration. Mutually exclusive with budget_id.","items":{"$ref":"#/$defs/budget_line"}},"budget_id":{"type":"string","description":"Single budget reference (pre-declared in governance.budgets). Deprecated in favour of inline budgets."},"rate_limit_id":{"type":"string","description":"Associated rate limit ID"},"calendar_aligned":{"type":"boolean","description":"Snap the customer's budget and rate-limit reset windows to clean calendar boundaries (day, week, month, year)","default":false}},"required":["id","name"],"not":{"required":["budgets","budget_id"]},"additionalProperties":false}},"teams":{"type":"array","description":"Team configurations","items":{"type":"object","properties":{"id":{"type":"string","description":"Team ID"},"name":{"type":"string","description":"Team name"},"source_id":{"type":"string","description":"Optional external source identifier (e.g. SCIM group ID) used to map this team to an upstream system. Unique when set."},"customer_id":{"type":"string","description":"Associated customer ID"},"budget_id":{"type":"string","description":"Associated budget ID"},"rate_limit_id":{"type":"string","description":"Associated rate limit ID"},"business_unit_id":{"type":"string","description":"Associated business unit ID"},"profile":{"type":"object","description":"Team profile data"},"config":{"type":"object","description":"Team configuration data"},"claims":{"type":"object","description":"Team claims data"},"calendar_aligned":{"type":"boolean","description":"Snap the team's budget and rate-limit reset windows to clean calendar boundaries (day, week, month, year)","default":false},"virtual_key_count":{"type":"integer","description":"Computed count of virtual keys associated with this team","minimum":0,"readOnly":true}},"required":["id","name"],"additionalProperties":false}},"business_units":{"type":"array","description":"Business unit configurations with optional team assignments","items":{"type":"object","properties":{"id":{"type":"string","description":"Business unit ID"},"name":{"type":"string","description":"Business unit name"},"budget_id":{"type":"string","description":"Associated budget ID"},"rate_limit_id":{"type":"string","description":"Associated rate limit ID"},"profile":{"type":"object","description":"Business unit profile data"},"config":{"type":"object","description":"Business unit configuration data"},"claims":{"type":"object","description":"Business unit claims data"},"team_ids":{"type":"array","description":"Team IDs to assign to this business unit","items":{"type":"string"}}},"required":["id","name"],"additionalProperties":false}},"roles":{"type":"array","description":"RBAC role definitions. Roles are created or updated on startup if the config hash changes; system roles and dashboard-created roles are never deleted.","items":{"type":"object","properties":{"name":{"type":"string","description":"Unique role name"},"description":{"type":"string","description":"Human-readable description of the role"},"dac":{"type":"string","description":"Data Access Control scope: own-data (user's own records), team-data (user's team records), all-data (unrestricted). Defaults to all-data.","enum":["own-data","team-data","all-data"],"default":"all-data"},"access_profile":{"type":"string","description":"Name of the access profile (defined in access_profiles) to attach as the default for this role. Changing this field triggers a re-sync on next startup. Leave unset to let the dashboard manage the assignment."},"permissions":{"type":"array","description":"List of resource+operation permission pairs to grant to this role","items":{"type":"object","properties":{"resource":{"type":"string","description":"Permission resource (e.g. Logs, VirtualKeys, Users, ModelProvider, Metrics, Guardrails, AccessProfiles, MCPToolGroups, Roles, BusinessUnits, AuditLogs, Billing)"},"operation":{"type":"string","description":"Permission operation (e.g. View, Create, Update, Delete, Download, RunInference, ManageInference, ViewInference)"}},"required":["resource","operation"],"additionalProperties":false}}},"required":["name"],"additionalProperties":false}},"virtual_keys":{"type":"array","description":"Virtual key configurations","items":{"type":"object","properties":{"id":{"type":"string","description":"Virtual key ID"},"name":{"type":"string","description":"Virtual key name"},"description":{"type":"string","description":"Virtual key description"},"value":{"type":"string","description":"The virtual key value. A literal, or an \"env.VAR\"/\"vault.path\" reference resolved to plaintext at load time."},"is_active":{"type":"boolean","description":"Whether the virtual key is active","default":true},"expires_at":{"type":"string","format":"date-time","description":"Optional expiry timestamp (RFC3339). Once passed, requests using this virtual key are rejected. Omit for a key that never expires."},"calendar_aligned":{"type":"boolean","description":"Snap all budget resets to calendar boundaries (day, week, month, year)","default":false},"team_id":{"type":"string","description":"Associated team ID (mutually exclusive with customer_id)"},"customer_id":{"type":"string","description":"Associated customer ID (mutually exclusive with team_id)"},"access_profile_id":{"type":"integer","minimum":1,"description":"Associated access profile ID for direct access profile assignment (mutually exclusive with team_id and customer_id)"},"rate_limit_id":{"type":"string","description":"Associated rate limit ID"},"provider_configs":{"type":"array","description":"Provider configurations for this virtual key (empty means no providers allowed, deny-by-default)","items":{"$ref":"#/$defs/virtual_key_provider_config"}},"mcp_configs":{"type":"array","description":"MCP configurations for this virtual key (empty array means no MCP tools allowed, deny-by-default)","items":{"$ref":"#/$defs/virtual_key_mcp_config"}}},"required":["id","name"],"additionalProperties":false}},"routing_rules":{"type":"array","description":"Routing rules for dynamic provider/model selection based on CEL expressions","items":{"$ref":"#/$defs/routing_rule"}},"pricing_overrides":{"type":"array","description":"Scoped pricing overrides applied at runtime by the model catalog","items":{"$ref":"#/$defs/provider_pricing_override"}},"auth_config":{"$ref":"#/$defs/auth_config"},"complexity_analyzer_config":{"$ref":"#/$defs/complexity_analyzer_config"},"model_configs":{"type":"array","description":"Per-model rate limit and budget configurations","items":{"type":"object","properties":{"id":{"type":"string","description":"Model config ID"},"model_name":{"type":"string","description":"Model name to apply the configuration to"},"provider":{"type":"string","description":"Optional provider name to scope this config"},"scope":{"type":"string","description":"Scope where this config applies: \"global\" (default) or \"virtual_key\"","default":"global"},"scope_id":{"type":"string","description":"Target entity ID for non-global scopes (e.g. virtual key ID). Required when scope != \"global\""},"calendar_aligned":{"type":"boolean","description":"Snap this config's budget resets to calendar boundaries (e.g. a monthly budget resets on the 1st) rather than rolling windows. For virtual_key-scoped configs it inherits the virtual key's setting.","default":false},"budget_id":{"type":"string","description":"Deprecated — single budget reference. Use budget_ids instead."},"budget_ids":{"type":"array","description":"List of budget IDs (from governance.budgets) to associate with this model config. Supports multiple budgets (e.g. daily + monthly). Replaces budget_id.","items":{"type":"string"}},"rate_limit_id":{"type":"string","description":"Rate limit ID to associate with this model"}},"required":["id","model_name"],"additionalProperties":false}},"providers":{"type":"array","description":"Provider-level governance configurations","items":{"type":"object","properties":{"id":{"type":"string","description":"Provider row ID"},"name":{"type":"string","description":"Provider name"},"description":{"type":"string","description":"Operator-facing provider description"},"budget_id":{"type":"string","description":"Associated budget ID"},"rate_limit_id":{"type":"string","description":"Associated rate limit ID"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"network_config":{"$ref":"#/$defs/network_config"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"openai_config":{"$ref":"#/$defs/openai_config"}},"required":["name"]}}},"additionalProperties":false},"alerting":{"type":"object","description":"Enterprise alerting configuration for governance-backed alert channels, rules, history retention, and outbound webhook URL validation.","properties":{"history_retention_days":{"type":"integer","minimum":0,"default":365,"description":"Number of days to retain alert history. Omit to use the default. Set to 0 to disable retention pruning."},"webhook_network":{"type":"object","description":"Outbound URL validation controls for Slack, Microsoft Teams, and generic webhook alert channels.","properties":{"allow_http":{"type":"boolean","default":false,"description":"Allow alert webhooks to use http URLs. By default only https URLs are accepted."},"allow_private_network":{"type":"boolean","default":false,"description":"Allow alert webhooks to target private or loopback network addresses. Useful for local testing."}},"additionalProperties":false},"channels":{"type":"array","description":"Declarative alert channels synced into the enterprise config store at startup.","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable alert channel ID."},"name":{"type":"string","description":"Operator-facing alert channel name."},"description":{"type":"string","description":"Optional alert channel description."},"type":{"type":"string","enum":["slack","microsoft_teams","pagerduty","webhook"],"description":"Alert channel type."},"enabled":{"type":"boolean","description":"Whether this alert channel can receive notifications."},"cooldown_seconds":{"type":"integer","minimum":0,"description":"Minimum seconds between sends for this channel. Set to 0 for no channel-level cooldown."},"config":{"type":"object","description":"Channel-specific delivery configuration. Slack and Microsoft Teams use webhook_url or url. PagerDuty uses routing_key or integration_key. Generic webhook uses url or webhook_url, plus optional string headers.","additionalProperties":true}},"required":["id","name","type","enabled"],"allOf":[{"if":{"properties":{"type":{"const":"slack"}},"required":["type"]},"then":{"properties":{"config":{"type":"object","properties":{"webhook_url":{"type":"string","minLength":1,"anyOf":[{"format":"uri"},{"pattern":"^env\\.[A-Za-z_][A-Za-z0-9_]*$"}],"description":"Slack incoming webhook URL. Supports env.VAR_NAME references."},"url":{"type":"string","minLength":1,"anyOf":[{"format":"uri"},{"pattern":"^env\\.[A-Za-z_][A-Za-z0-9_]*$"}],"description":"Alias for webhook_url. Supports env.VAR_NAME references."}},"oneOf":[{"required":["webhook_url"]},{"required":["url"]}],"additionalProperties":true}},"required":["config"]}},{"if":{"properties":{"type":{"const":"microsoft_teams"}},"required":["type"]},"then":{"properties":{"config":{"type":"object","properties":{"webhook_url":{"type":"string","minLength":1,"anyOf":[{"format":"uri"},{"pattern":"^env\\.[A-Za-z_][A-Za-z0-9_]*$"}],"description":"Microsoft Teams incoming webhook or workflow URL. Supports env.VAR_NAME references."},"url":{"type":"string","minLength":1,"anyOf":[{"format":"uri"},{"pattern":"^env\\.[A-Za-z_][A-Za-z0-9_]*$"}],"description":"Alias for webhook_url. Supports env.VAR_NAME references."}},"oneOf":[{"required":["webhook_url"]},{"required":["url"]}],"additionalProperties":true}},"required":["config"]}},{"if":{"properties":{"type":{"const":"pagerduty"}},"required":["type"]},"then":{"properties":{"config":{"type":"object","properties":{"routing_key":{"type":"string","minLength":1,"description":"PagerDuty Events API v2 integration key. Supports env.VAR_NAME references."},"integration_key":{"type":"string","minLength":1,"description":"Alias for routing_key. Supports env.VAR_NAME references."}},"oneOf":[{"required":["routing_key"]},{"required":["integration_key"]}],"additionalProperties":true}},"required":["config"]}},{"if":{"properties":{"type":{"const":"webhook"}},"required":["type"]},"then":{"properties":{"config":{"type":"object","properties":{"url":{"type":"string","minLength":1,"anyOf":[{"format":"uri"},{"pattern":"^env\\.[A-Za-z_][A-Za-z0-9_]*$"}],"description":"Generic webhook URL. Supports env.VAR_NAME references."},"webhook_url":{"type":"string","minLength":1,"anyOf":[{"format":"uri"},{"pattern":"^env\\.[A-Za-z_][A-Za-z0-9_]*$"}],"description":"Alias for url. Supports env.VAR_NAME references."},"headers":{"type":"object","description":"Optional headers to send with the webhook request. Values support env.VAR_NAME references. Sensitive hop-by-hop headers are ignored at send time.","additionalProperties":{"type":"string"}}},"oneOf":[{"required":["url"]},{"required":["webhook_url"]}],"additionalProperties":true}},"required":["config"]}}],"additionalProperties":false}},"rules":{"type":"array","description":"Declarative alert rules synced into the enterprise config store at startup.","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable alert rule ID."},"name":{"type":"string","description":"Operator-facing alert rule name."},"description":{"type":"string","description":"Optional alert rule description."},"enabled":{"type":"boolean","description":"Whether this alert rule is evaluated."},"scope_type":{"type":"string","enum":["virtual_key","team","customer"],"description":"Governance owner scope to evaluate."},"scope_id":{"type":"string","description":"ID of the virtual key, team, or customer referenced by scope_type."},"cel_expression":{"type":"string","description":"CEL expression evaluated against alerting usage variables such as budget_usage_percent, budget_spent, request_usage, token_usage, and rate-limit percentages."},"query":{"type":"object","description":"Optional UI query-builder representation of cel_expression.","additionalProperties":true},"cooldown_seconds":{"type":"integer","minimum":0,"default":60,"description":"Minimum seconds between notifications for this rule. Omit to use the default. Set to 0 for no rule cooldown."},"notify_once_per_reset_cycle":{"type":"boolean","default":false,"description":"When true, notify at most once per matched budget or rate-limit reset cycle. This overrides rule cooldown to 0."},"channel_ids":{"type":"array","description":"IDs of alert channels to notify when this rule matches.","items":{"type":"string","minLength":1},"minItems":1},"target_type":{"type":"string","enum":["budget"],"description":"Optional explicit target type. Use budget with target_id to evaluate one specific budget; omit to evaluate all budgets for the scope."},"target_id":{"type":"string","description":"ID of the explicit target referenced by target_type."}},"required":["id","name","enabled","scope_type","scope_id","cel_expression","channel_ids"],"allOf":[{"if":{"required":["target_type"]},"then":{"required":["target_id"]}},{"if":{"required":["target_id"]},"then":{"required":["target_type"]}}],"additionalProperties":false}}},"additionalProperties":false},"mcp":{"type":"object","description":"Model Context Protocol configuration","properties":{"client_configs":{"type":"array","items":{"$ref":"#/$defs/mcp_client_config"},"description":"MCP client configurations"},"tool_manager_config":{"$ref":"#/$defs/mcp_tool_manager_config"},"tool_sync_interval":{"description":"Global default interval for syncing tools from MCP servers (Go duration string, e.g. '10m', '1h', '0s' to use runtime default). Legacy numeric nanoseconds are also supported for backward compatibility.","oneOf":[{"type":"string","pattern":"^-?(?:\\d+(?:\\.\\d+)?(?:ns|us|µs|ms|s|m|h))+$"},{"type":"integer"}]},"tool_groups":{"type":"array","description":"Enterprise MCP tool groups with optional governance associations","items":{"$ref":"#/$defs/mcp_tool_group_config"}}},"additionalProperties":false},"vector_store":{"type":"object","description":"Vector store configuration for caching","properties":{"enabled":{"type":"boolean","description":"Enable vector store"},"type":{"type":"string","enum":["weaviate","redis","qdrant","pinecone"],"description":"Vector store type (use \"redis\" for Redis or Valkey-compatible endpoints)"},"config":{"anyOf":[{"if":{"properties":{"type":{"const":"weaviate"}}},"then":{"$ref":"#/$defs/weaviate_config"}},{"if":{"properties":{"type":{"const":"redis"}}},"then":{"$ref":"#/$defs/redis_config"}},{"if":{"properties":{"type":{"const":"qdrant"}}},"then":{"$ref":"#/$defs/qdrant_config"}},{"if":{"properties":{"type":{"const":"pinecone"}}},"then":{"$ref":"#/$defs/pinecone_config"}}]}},"additionalProperties":false},"config_store":{"type":"object","description":"Configuration store settings","properties":{"enabled":{"type":"boolean","description":"Enable configuration store"},"type":{"type":"string","enum":["sqlite","postgres"],"description":"Configuration store type"},"config":{"anyOf":[{"if":{"properties":{"type":{"const":"sqlite"}}},"then":{"type":"object","properties":{"path":{"type":"string","description":"Database file path"}},"required":["path"],"additionalProperties":false}},{"if":{"properties":{"type":{"const":"postgres"}}},"then":{"type":"object","properties":{"host":{"type":"string","description":"Database host"},"port":{"type":"string","description":"Database port"},"user":{"type":"string","description":"Database user"},"password":{"type":"string","description":"Database password. Use password_command instead when the password must be generated dynamically."},"password_command":{"type":"object","description":"Command executed without a shell to produce the database password on stdout for each new physical connection.","properties":{"command":{"type":"string","minLength":1,"pattern":"^\\S+$","description":"Executable path or name to run"},"args":{"type":"array","description":"Arguments passed directly to the executable","items":{"type":"string"},"default":[]},"timeout":{"type":"string","description":"Command timeout as a Go duration string (default: 10s)","pattern":"^[1-9][0-9]*(ns|us|µs|ms|s|m|h)$","default":"10s"}},"required":["command"],"additionalProperties":false},"db_name":{"type":"string","description":"Database name"},"ssl_mode":{"type":"string","description":"Database SSL mode"},"max_idle_conns":{"type":"integer","description":"Maximum number of idle connections in the pool (default: 5)","minimum":0,"default":5},"max_open_conns":{"type":"integer","description":"Maximum number of open connections to the database (default: 50)","minimum":2,"default":50},"conn_max_lifetime":{"type":"string","description":"Maximum lifetime for physical database connections as a Go duration string","pattern":"^[1-9][0-9]*(ns|us|µs|ms|s|m|h)$"}},"required":["host","port","user","db_name","ssl_mode"],"oneOf":[{"required":["password"]},{"required":["password_command"]}],"additionalProperties":false}}]},"vault_store":{"type":"object","description":"Vault store for external secret management. Fields stored as vault.<path> or vault.<path>#<jsonKey> references are resolved through the configured backend.","properties":{"enabled":{"type":"boolean","description":"Enable vault integration"},"type":{"type":"string","enum":["aws-secrets-manager","gcp-secret-manager","hashicorp-vault"],"description":"Vault backend type"},"prefix":{"type":"string","description":"Path prefix applied to every secret (default: bifrost)"},"access_mode":{"type":"string","enum":["read_only","read_and_write"],"description":"read_only resolves existing refs only; read_and_write also auto-stores plaintext fields and deletes owned secrets. Defaults to read_only."},"aws":{"type":"object","description":"AWS Secrets Manager configuration","properties":{"region":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"access_key_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"secret_access_key":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"session_token":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"role_arn":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"kms_key_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]}},"additionalProperties":false},"gcp":{"type":"object","description":"GCP Secret Manager configuration","properties":{"project_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"credentials_json":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]}},"additionalProperties":false},"hashicorp":{"type":"object","description":"HashiCorp Vault (KV v2) configuration","properties":{"address":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"token":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"namespace":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"mount_path":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"role_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"secret_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]}},"additionalProperties":false}},"additionalProperties":false}},"additionalProperties":false},"logs_store":{"type":"object","description":"Logs store settings","properties":{"enabled":{"type":"boolean","description":"Enable logs store"},"type":{"type":"string","enum":["sqlite","postgres","clickhouse"],"description":"Logs store type"},"config":{"type":"object","oneOf":[{"if":{"properties":{"../type":{"const":"sqlite"}}},"then":{"properties":{"path":{"type":"string","description":"Database file path"}},"required":["path"],"additionalProperties":false}},{"if":{"properties":{"../type":{"const":"postgres"}}},"then":{"properties":{"host":{"type":"string","description":"Database host"},"port":{"type":"string","description":"Database port"},"user":{"type":"string","description":"Database user"},"password":{"type":"string","description":"Database password. Use password_command instead when the password must be generated dynamically."},"password_command":{"type":"object","description":"Command executed without a shell to produce the database password on stdout for each new physical connection.","properties":{"command":{"type":"string","minLength":1,"pattern":"^\\S+$","description":"Executable path or name to run"},"args":{"type":"array","description":"Arguments passed directly to the executable","items":{"type":"string"},"default":[]},"timeout":{"type":"string","description":"Command timeout as a Go duration string (default: 10s)","pattern":"^[1-9][0-9]*(ns|us|µs|ms|s|m|h)$","default":"10s"}},"required":["command"],"additionalProperties":false},"db_name":{"type":"string","description":"Database name"},"ssl_mode":{"type":"string","description":"Database SSL mode"},"max_idle_conns":{"type":"integer","description":"Maximum number of idle connections in the pool (default: 5)","minimum":0,"default":5},"max_open_conns":{"type":"integer","description":"Maximum number of open connections to the database (default: 50)","minimum":2,"default":50},"matview_refresh_interval":{"type":"string","description":"How often to refresh dashboard materialized views. Go duration string (e.g. '1m', '5m', '1h'). Default 1m. Raise this when matview refresh CPU cost is material on the database instance. Minimum 5s.","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","default":"1m"},"conn_max_lifetime":{"type":"string","description":"Maximum lifetime for physical database connections as a Go duration string","pattern":"^[1-9][0-9]*(ns|us|µs|ms|s|m|h)$"}},"required":["host","port","user","db_name","ssl_mode"],"oneOf":[{"required":["password"]},{"required":["password_command"]}],"additionalProperties":false}},{"if":{"properties":{"../type":{"const":"clickhouse"}}},"then":{"properties":{"host":{"type":"string","description":"ClickHouse host"},"port":{"type":"string","description":"ClickHouse port. Defaults by protocol: native 9000 (9440 TLS), http 8123 (8443 TLS)"},"database":{"type":"string","description":"ClickHouse database name (default: default)"},"username":{"type":"string","description":"ClickHouse username"},"password":{"type":"string","description":"ClickHouse password"},"protocol":{"type":"string","enum":["native","http"],"description":"ClickHouse wire protocol (default: native)"},"secure":{"type":"boolean","description":"Enable TLS (native: secure=true; http: switches to https)","default":false},"dial_timeout":{"type":"integer","description":"Connection dial timeout in milliseconds (default: 10000)","minimum":1,"default":10000},"cluster":{"type":"string","description":"Optional cluster name; when set, DDL runs ON CLUSTER with replicated table engines"}},"required":["host"],"additionalProperties":false}}]},"writer":{"type":"object","description":"Async logging writer queue and batch tuning. Omitted fields use runtime defaults.","properties":{"max_batch_size":{"type":"integer","description":"Maximum number of log entries to batch before flushing (default: 1000)","minimum":1,"default":1000},"batch_interval":{"type":"string","description":"Maximum time to wait before flushing a partial batch as a Go duration string (default: 5s)","pattern":"^[1-9][0-9]*(ns|us|µs|ms|s|m|h)$","default":"5s"},"max_batch_bytes":{"type":"integer","description":"Approximate byte-size ceiling for a batch before flushing (default: 314572800)","minimum":1,"default":314572800},"write_queue_capacity":{"type":"integer","description":"Buffered queue capacity for pending log writes (default: 10000)","minimum":1,"default":10000},"deferred_usage_concurrency":{"type":"integer","description":"Maximum concurrent deferred usage database updates (default: 5)","minimum":1,"default":5}},"additionalProperties":false},"object_storage":{"type":"object","description":"Optional object storage for offloading LLM and MCP log payloads. When configured, full payloads are stored in S3/GCS while the DB keeps lightweight index data. MCP log rows keep dashboard/table fields plus a 200-character input preview.","properties":{"type":{"type":"string","enum":["s3","gcs"],"description":"Object storage backend type"},"bucket":{"anyOf":[{"type":"string","minLength":1},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"Bucket name. Supports env var reference (e.g. env.S3_BUCKET) or a structured secret reference."},"prefix":{"type":"string","description":"Key prefix for stored objects (default: bifrost)","default":"bifrost"},"compress":{"type":"boolean","description":"Enable gzip compression for stored objects. Default: false","default":false}},"required":["type","bucket"],"if":{"properties":{"type":{"const":"s3"}}},"then":{"properties":{"type":true,"bucket":true,"prefix":true,"region":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS region. Supports env var reference"},"endpoint":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"Custom S3-compatible endpoint for MinIO/R2. Supports env var reference"},"access_key_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS access key ID. Omit to use default credential chain (instance role, env vars, etc.). Supports env var reference"},"secret_access_key":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS secret access key. Supports env var reference"},"session_token":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS session token for STS temporary credentials. Supports env var reference"},"role_arn":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS IAM role ARN for STS AssumeRole. Works with static creds or instance role. Supports env var reference"},"force_path_style":{"type":"boolean","description":"Use path-style URLs for S3 (required for MinIO). Default: false","default":false},"compress":true},"dependentRequired":{"access_key_id":["secret_access_key"],"secret_access_key":["access_key_id"],"session_token":["access_key_id","secret_access_key"]},"additionalProperties":false},"else":{"properties":{"type":true,"bucket":true,"prefix":true,"credentials_json":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"GCP service account credentials JSON or file path. Omit to use Application Default Credentials. Supports env var reference"},"credentials":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"Deprecated: use credentials_json. Kept for backwards compatibility."},"project_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"GCP project ID override. Supports env var reference"},"compress":true},"additionalProperties":false}},"object_storage_exclude_fields":{"type":"array","description":"LLM log payload field DB column names that should NOT be offloaded to object storage and must remain in the database (e.g. output_message, input_history, raw_request, raw_response). Unknown names are ignored. MCP logs always offload the full log and keep dashboard/table fields plus a 200-character input preview in the database.","items":{"type":"string"}},"retention_days":{"type":"integer","minimum":0,"description":"Days to retain log entries. 0 disables retention-based cleanup."}},"additionalProperties":false},"skills_registry":{"type":"object","description":"Declarative Skills Repository definitions reconciled from config.json","properties":{"enabled":{"type":"boolean","description":"Whether config-defined skills should be reconciled at startup"},"skills":{"type":"array","description":"Skills to create or update from config.json","items":{"type":"object","required":["name","description","skill_md_body","version"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"license":{"type":"string"},"compatibility":{"type":"string"},"allowed_tools":{"type":"string"},"extra_frontmatter":{"type":"object","additionalProperties":true},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"skill_md_body":{"type":"string"},"version":{"type":"string"},"files":{"type":"array","items":{"type":"object","required":["path","source_type"],"properties":{"path":{"type":"string"},"source_type":{"type":"string","enum":["text","url","dataurl"]},"url":{"type":"string"},"content":{"type":"string"},"dataurl":{"type":"string"}},"additionalProperties":false,"oneOf":[{"properties":{"source_type":{"const":"url"}},"required":["url"]},{"properties":{"source_type":{"const":"text"}},"required":["content"]},{"properties":{"source_type":{"const":"dataurl"}},"required":["dataurl"]}]}}},"additionalProperties":false}}},"additionalProperties":false},"plugins":{"type":"array","description":"Plugins configuration","items":{"type":"object","required":["enabled","name"],"properties":{"enabled":{"type":"boolean","description":"Enable plugins"},"name":{"type":"string","description":"Name of the plugin (built-in: telemetry, prompts, logging, governance, maxim, semantic_cache, otel, or custom plugin name)"},"config":{"type":"object","description":"Configuration for the plugin"},"path":{"type":"string","description":"Path to the plugin (optional, required for dynamic plugins)","optional":true},"version":{"type":"integer","minimum":1,"maximum":32767,"description":"DB-Backed Only. Version metadata persisted on TablePlugin (default: 1). In DB-backed sync, version metadata is considered for plugin replacement/reload decisions.","optional":true,"default":1},"placement":{"type":"string","enum":["pre_builtin","post_builtin","builtin"],"description":"DB-Backed Only. Whether this plugin runs before, after, or as a built-in. Default: post_builtin. Ignored in config.json.","optional":true,"default":"post_builtin"},"order":{"type":"integer","description":"DB-Backed Only. Position within placement group. Lower values execute earlier. Default: 0. Ignored in config.json.","optional":true,"default":0}},"allOf":[{"if":{"properties":{"name":{"const":"telemetry"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the telemetry plugin (Prometheus metrics)","properties":{"custom_labels":{"type":"array","items":{"type":"string"},"description":"Custom labels to add to Prometheus metrics"},"push_gateway":{"type":"object","description":"Configuration for pushing metrics to a Prometheus Push Gateway for multi-node cluster deployments","properties":{"enabled":{"type":"boolean","description":"Whether to enable pushing metrics to the Push Gateway","default":false},"push_gateway_url":{"type":"string","description":"URL of the Prometheus Push Gateway (e.g., http://pushgateway:9091)","format":"uri"},"job_name":{"type":"string","description":"Job label for pushed metrics","default":"bifrost"},"instance_id":{"type":"string","description":"Instance identifier for grouping metrics. If not set, hostname is used automatically."},"push_interval":{"type":"integer","description":"How often to push metrics in seconds","default":15,"minimum":1,"maximum":300},"basic_auth":{"type":"object","description":"Basic authentication credentials for the Push Gateway","properties":{"username":{"type":"string","description":"Username for basic authentication"},"password":{"type":"string","description":"Password for basic authentication"}},"required":["username","password"]}},"required":["push_gateway_url"]}},"additionalProperties":false}}}},{"if":{"properties":{"name":{"const":"logging"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the logging plugin","properties":{"disable_content_logging":{"type":"boolean","description":"Disable logging of request and response content"},"allow_per_request_content_storage_override":{"type":"boolean","description":"Allow individual requests to override content storage via the x-bf-disable-content-logging header or context key, and to opt in to raw-byte persistence in logs via x-bf-store-raw-request-response. When false (default), per-request storage overrides are ignored. Does not control sending raw bytes back to callers — see allow_per_request_raw_override.","default":false},"logging_headers":{"type":"array","items":{"type":"string"},"description":"List of headers to capture in log metadata"}},"additionalProperties":false}}}},{"if":{"properties":{"name":{"const":"governance"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the governance plugin","properties":{"is_vk_mandatory":{"type":"boolean","description":"Whether virtual key (x-bf-vk header) is mandatory for all requests"},"required_headers":{"type":"array","items":{"type":"string"},"description":"List of headers that must be present in requests"},"is_enterprise":{"type":"boolean","description":"Enable enterprise mode features"}},"additionalProperties":false}}}},{"if":{"properties":{"name":{"const":"maxim"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the Maxim SDK integration plugin","properties":{"api_key":{"type":"string","description":"API key for Maxim SDK authentication"},"log_repo_id":{"type":"string","description":"Optional default ID for the Maxim logger instance"},"request_headers":{"type":"array","items":{"type":"string"},"description":"Request header name patterns (exact or wildcard like x-custom-*) to capture and attach as trace tags. Note: * captures all headers including sensitive ones like Authorization."}},"required":["api_key"],"additionalProperties":false}}}},{"if":{"properties":{"name":{"const":"semantic_cache"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the semantic cache plugin","properties":{"provider":{"type":"string","minLength":1,"description":"Provider to use for generating embeddings. Required for semantic search; omit it for direct hash mode with dimension: 1.","enum":["openai","anthropic","gemini","bedrock","bedrock_mantle","azure","cohere","mistral","groq","ollama","openrouter","vertex","cerebras","deepseek","vllm","parasail","perplexity","replicate","sgl","huggingface"]},"embedding_model":{"type":"string","description":"Model to use for generating embeddings in provider-backed semantic caching. Required when provider is set and not allowed in direct-only mode."},"ttl":{"description":"Time-to-live for cached responses (supports duration strings like '5m', '1h' or seconds as number, default: 5min)","oneOf":[{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$"},{"type":"integer","minimum":0}]},"threshold":{"type":"number","description":"Cosine similarity threshold for semantic matching (default: 0.8)","minimum":0,"maximum":1},"vector_store_namespace":{"type":"string","description":"Namespace for vector store (optional)"},"dimension":{"type":"integer","description":"Dimension for vector store embeddings. Use 1 for direct (hash-based) caching without an embedding provider.","minimum":1},"default_cache_key":{"type":"string","description":"Default cache key used when no per-request key is provided. When set, all requests without an explicit x-bf-cache-key header will use this value and be cached automatically."},"conversation_history_threshold":{"type":"integer","description":"Skip caching for requests with more than this number of messages in conversation history (default: 3)","minimum":0},"cache_by_model":{"type":"boolean","description":"Include model in cache key (default: true)"},"cache_by_provider":{"type":"boolean","description":"Include provider in cache key (default: true)"},"exclude_system_prompt":{"type":"boolean","description":"Exclude system prompt in cache key (default: false)"}},"required":["dimension"],"allOf":[{"if":{"properties":{"provider":{"type":"string","minLength":1}},"required":["provider"]},"then":{"required":["provider","embedding_model"],"properties":{"dimension":{"type":"integer","minimum":2}}},"else":{"not":{"required":["embedding_model"]},"properties":{"dimension":{"const":1}}}}],"additionalProperties":false}}}},{"if":{"properties":{"name":{"const":"otel"}}},"then":{"required":["config"],"properties":{"config":{"anyOf":[{"$ref":"#/$defs/otel_profile_config"},{"$ref":"#/$defs/otel_profiles_config"}],"description":"Configuration for the OpenTelemetry plugin. Supports the legacy single-profile shape or the profiles wrapper for multiple collectors."}}}},{"if":{"properties":{"name":{"const":"datadog"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the Datadog APM and metrics plugin","properties":{"service_name":{"type":"string","description":"Name of the service to report to Datadog","default":"bifrost"},"ml_app":{"type":"string","description":"ML application name for LLM Observability grouping (defaults to service_name)"},"agent_addr":{"type":"string","description":"Combined host:port address of the Datadog Agent for APM traces (agent mode only, can use env. prefix). Overridden by agent_host when set.","default":"localhost:8126"},"agent_host":{"type":"string","description":"Host of the Datadog Agent for APM traces, provided separately from the port (agent mode only, can use env. prefix). Takes precedence over agent_addr when set. Useful in Kubernetes where the host is injected via the downward API (status.hostIP)."},"agent_port":{"type":"string","description":"Port of the Datadog Agent for APM traces (agent mode only, can use env. prefix). Used only when agent_host is set (defaults to 8126); has no effect when agent_host is unset, in which case agent_addr supplies the port.","default":"8126"},"dogstatsd_addr":{"type":"string","description":"Combined host:port address of the DogStatsD server for metrics (agent mode only, can use env. prefix). Overridden by dogstatsd_host when set.","default":"localhost:8125"},"dogstatsd_host":{"type":"string","description":"Host of the DogStatsD server for metrics, provided separately from the port (agent mode only, can use env. prefix). Takes precedence over dogstatsd_addr when set. Useful in Kubernetes where the host is injected via the downward API (status.hostIP)."},"dogstatsd_port":{"type":"string","description":"Port of the DogStatsD server for metrics (agent mode only, can use env. prefix). Used only when dogstatsd_host is set (defaults to 8125); has no effect when dogstatsd_host is unset, in which case dogstatsd_addr supplies the port.","default":"8125"},"env":{"type":"string","description":"Environment tag (e.g., production, staging)"},"version":{"type":"string","description":"Service version tag"},"custom_tags":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional tags to add to all traces and metrics (values can use env. prefix)"},"enable_metrics":{"type":"boolean","description":"Enable metrics emission (default: true)","default":true},"enable_traces":{"type":"boolean","description":"Enable APM traces (default: true)","default":true},"enable_llm_obs":{"type":"boolean","description":"Enable LLM Observability (default: true)","default":true},"group_traces_by_session":{"type":"boolean","description":"Group requests sharing the same x-bf-session-id header into a single APM trace, with each request as a top-level sibling span. Agent mode only; an inbound W3C traceparent takes precedence (default: false)","default":false},"disable_content_logging":{"type":"boolean","description":"Disable logging of message content to Datadog (default: false)","default":false},"agentless":{"type":"boolean","description":"Use agentless mode to send data directly to Datadog APIs (default: false)","default":false},"api_key":{"type":"string","description":"Datadog API key, required for agentless mode (can use env. prefix)"},"site":{"type":"string","description":"Datadog site/region (e.g., datadoghq.com, datadoghq.eu)","default":"datadoghq.com"},"request_headers":{"type":"array","items":{"type":"string"},"description":"Request header names to capture as span tags"},"plugin_span_filter":{"$ref":"#/$defs/plugin_span_filter"}},"allOf":[{"if":{"properties":{"agentless":{"const":true}},"required":["agentless"]},"then":{"required":["api_key"]}}],"additionalProperties":false}}}},{"if":{"properties":{"name":{"const":"bigquery"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the BigQuery traces plugin","properties":{"project_id":{"type":"string","description":"GCP project ID (required)"},"dataset_id":{"type":"string","description":"BigQuery dataset name","default":"bifrost_traces"},"table_id":{"type":"string","description":"BigQuery table name","default":"traces"},"location":{"type":"string","description":"BigQuery dataset location","default":"US"},"service_account_key":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}],"description":"Service account key JSON for authentication. Omit to use Application Default Credentials (ADC). Supports env var syntax: \"env.MY_VAR\"."},"create_table_if_not_exists":{"type":"boolean","description":"Auto-create the table if it does not exist","default":true},"flush_interval_seconds":{"type":"integer","description":"Interval between buffer flushes, in seconds","default":5},"buffer_size":{"type":"integer","description":"Max rows to buffer before flushing","default":500},"custom_labels":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}]},"description":"Arbitrary key-value pairs stored as JSON in the labels column"},"disable_content_logging":{"type":"boolean","description":"Omit conversation history (input/output) columns","default":false},"request_headers":{"type":"array","items":{"type":"string"},"description":"Request-header name patterns (exact or wildcard like \"x-custom-*\") whose values are stored in the request_headers column"},"plugin_span_filter":{"$ref":"#/$defs/plugin_span_filter"}},"required":["project_id"],"additionalProperties":false}}}},{"if":{"properties":{"name":{"const":"kafka"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the Kafka traces plugin (Enterprise). Publishes completed traces as JSON messages to a Kafka topic, keyed by trace ID.","properties":{"brokers":{"type":"array","items":{"type":"string"},"minItems":1,"description":"Kafka broker addresses (required)"},"topic":{"type":"string","description":"Kafka topic to publish traces to (required)"},"sasl_enabled":{"type":"boolean","description":"Enable SASL authentication. SASL is only activated when both sasl_enabled is true and sasl is set.","default":false},"sasl":{"type":"object","description":"SASL credentials, used when sasl_enabled is true","properties":{"mechanism":{"type":"string","enum":["PLAIN","SCRAM-SHA-256","SCRAM-SHA-512"]},"username":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}],"description":"SASL username. Supports env var syntax: \"env.MY_VAR\"."},"password":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}],"description":"SASL password. Supports env var syntax: \"env.MY_VAR\"."}},"additionalProperties":false},"tls_enabled":{"type":"boolean","description":"Enable TLS for broker connections","default":false},"ca_cert":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}],"description":"PEM-encoded CA certificate used to verify the broker's TLS certificate. Omit to use the system CA pool. Supports env var syntax: \"env.KAFKA_CA_CERT\"."},"compression":{"type":"string","enum":["none","gzip","snappy","lz4","zstd"],"description":"Compression codec for published messages","default":"none"},"batch_size":{"type":"integer","description":"Maximum number of messages batched per write","default":100},"flush_interval_ms":{"type":"integer","description":"Maximum time (ms) to wait before flushing a batch","default":1000},"auto_create_topic":{"type":"boolean","description":"Create the topic at startup if it does not exist","default":false},"disable_content_logging":{"type":"boolean","description":"Strip input/output message content from traces before publishing","default":false},"request_headers":{"type":"array","items":{"type":"string"},"description":"Request-header name patterns (exact or wildcard like \"x-custom-*\") whose captured values are embedded in published traces"},"plugin_span_filter":{"$ref":"#/$defs/plugin_span_filter"}},"required":["brokers","topic"],"additionalProperties":false}}}},{"if":{"properties":{"name":{"const":"pubsub"}}},"then":{"required":["config"],"properties":{"config":{"type":"object","description":"Configuration for the Google Cloud Pub/Sub traces plugin (Enterprise). Publishes completed traces as JSON messages to a Pub/Sub topic.","properties":{"project_id":{"type":"string","description":"GCP project ID (required)"},"topic_id":{"type":"string","description":"Pub/Sub topic ID — just the ID, not the full resource name (required)"},"service_account_key":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"additionalProperties":false}],"description":"Service account key JSON for authentication. Omit to use Application Default Credentials (ADC). Supports env var syntax: \"env.MY_VAR\"."},"auto_create_topic":{"type":"boolean","description":"Create the topic at startup if it does not exist","default":false},"disable_content_logging":{"type":"boolean","description":"Strip request/response content from traces before publishing","default":false},"request_headers":{"type":"array","items":{"type":"string"},"description":"Request-header name patterns (exact or wildcard like \"x-custom-*\") whose captured values are included in published traces"},"plugin_span_filter":{"$ref":"#/$defs/plugin_span_filter"}},"required":["project_id","topic_id"],"additionalProperties":false}}}}],"additionalProperties":false}},"websocket":{"$ref":"#/$defs/websocket_config"},"guardrails_config":{"$ref":"#/$defs/guardrails_config"},"audit_logs":{"$ref":"#/$defs/audit_logs_config"},"cluster_config":{"$ref":"#/$defs/cluster_config"},"load_balancer_config":{"$ref":"#/$defs/load_balancer_config"},"large_payload_optimization":{"$ref":"#/$defs/large_payload_optimization"},"scim_config":{"$ref":"#/$defs/scim_config"},"access_profiles":{"$ref":"#/$defs/access_profiles"},"feature_flags":{"$ref":"#/$defs/feature_flags_config"},"circuit_breaker_config":{"$ref":"#/$defs/circuit_breaker_config"}},"additionalProperties":false,"$defs":{"otel_endpoint":{"type":"string","anyOf":[{"format":"uri"},{"pattern":"^[^:\\s]+:\\d+$"},{"pattern":"^env\\.[A-Za-z_][A-Za-z0-9_]*$"}]},"plugin_span_filter":{"type":"object","description":"Controls which plugin hook spans this observability connector exports. Omit to export all plugin spans. Mode \"include\" exports only the listed plugins; mode \"exclude\" exports everything except them. Plugin names match the <name> in the span name \"plugin.<name>.<stage>\".","properties":{"mode":{"type":"string","enum":["include","exclude"]},"plugins":{"type":"array","items":{"type":"string"}}},"required":["mode","plugins"],"additionalProperties":false},"otel_profile_config":{"type":"object","description":"OpenTelemetry export profile. This legacy single-profile shape is still accepted directly as the plugin config.","properties":{"enabled":{"type":"boolean","description":"Whether this profile exports traces and metrics","default":true},"service_name":{"type":"string","description":"Service name to be used for tracing","default":"bifrost"},"collector_url":{"$ref":"#/$defs/otel_endpoint","description":"URL of the OpenTelemetry collector"},"trace_type":{"type":"string","description":"Type of trace to use for the OTEL collector","enum":["genai_extension","vercel","open_inference"]},"protocol":{"type":"string","description":"Protocol to use for the OTEL collector","enum":["http","grpc"]},"metrics_enabled":{"type":"boolean","description":"Enable push-based metrics export via OTLP. Recommended for multi-node cluster deployments.","default":false},"metrics_endpoint":{"$ref":"#/$defs/otel_endpoint","description":"OTLP metrics endpoint URL (e.g., http://otel-collector:4318/v1/metrics for HTTP or otel-collector:4317 for gRPC)"},"metrics_push_interval":{"type":"integer","description":"Metrics push interval in seconds","default":15,"minimum":1,"maximum":300},"request_headers":{"type":"array","items":{"type":"string"},"description":"Request header name patterns (exact or wildcard like x-custom-*) to capture and emit as span attributes. Note: * captures all headers including sensitive ones like Authorization."},"disable_content_logging":{"type":"boolean","description":"When true, message content (input/output messages, embeddings, tool definitions, and tool call arguments/results) is dropped from exported spans. Only metadata such as model, tokens, and latency is sent to the collector.","default":false},"group_traces_by_session":{"type":"boolean","description":"When true, requests sharing the same x-bf-session-id header are grouped into a single OTEL trace, each request's root span appearing as a top-level sibling. An inbound W3C traceparent takes precedence, leaving that request on its own distributed trace.","default":false},"disable_root_span_content":{"type":"boolean","description":"When true, input/output message content is dropped from the root span only; the underlying generation (llm.call) span retains the full content. This removes the duplicate input/output stored at the trace level (e.g. the Langfuse trace Input/Output goes empty) to reduce downstream storage.","default":false},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom headers for the collector. Supports env.VAR_NAME prefix for environment variable substitution."},"tls_ca_cert":{"type":"string","description":"Path to TLS CA certificate file"},"insecure":{"type":"boolean","description":"Skip TLS verification (ignored if tls_ca_cert is set)","default":true},"plugin_span_filter":{"$ref":"#/$defs/plugin_span_filter"}},"allOf":[{"if":{"not":{"properties":{"enabled":{"const":false}},"required":["enabled"]}},"then":{"required":["collector_url","trace_type","protocol"]}},{"if":{"properties":{"metrics_enabled":{"const":true}},"required":["metrics_enabled"]},"then":{"required":["metrics_endpoint"]}}],"additionalProperties":false},"otel_profiles_config":{"type":"object","description":"OpenTelemetry plugin configuration with one or more export profiles.","properties":{"profiles":{"type":"array","description":"OpenTelemetry export profiles","items":{"$ref":"#/$defs/otel_profile_config"},"minItems":1},"plugin_span_filter":{"$ref":"#/$defs/plugin_span_filter"}},"required":["profiles"],"additionalProperties":false},"feature_flags_config":{"type":"object","description":"Boot-time overrides for feature flags. Flags themselves are declared in code via featureflags.Register; this block only sets initial values. Anything set here is rendered as locked in the UI - operators must edit the config (or Helm values) to change it.","properties":{"flags":{"type":"object","additionalProperties":{"type":"object","properties":{"enabled":{"description":"Boolean value or a string: either 'env.NAME' for env-var indirection, or a literal boolean (true / false / 1 / 0 / yes / no / on / off, case-insensitive).","oneOf":[{"type":"boolean"},{"type":"string","pattern":"^(env\\.[A-Za-z_][A-Za-z0-9_]*|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|[01]|[Yy][Ee][Ss]|[Nn][Oo]|[Oo][Nn]|[Oo][Ff][Ff])$"}]}},"required":["enabled"],"additionalProperties":false}}},"additionalProperties":false},"routing_target":{"type":"object","description":"A single weighted routing target within a rule. All fields except weight are optional; omitting provider or model means use the incoming request value. Weights across all targets in a rule must sum to 1.","properties":{"provider":{"type":"string","minLength":1,"description":"Target provider name (e.g., 'openai', 'azure'). Omit to use the incoming request provider"},"model":{"type":"string","minLength":1,"description":"Target model name. Omit to use the incoming request model"},"provider_key_name":{"type":"string","minLength":1,"description":"Optional provider key name. Resolved to internal key_id at config load time. Requires provider."},"weight":{"type":"number","description":"Probability weight for this target (must be > 0). All weights in a rule must sum to 1","exclusiveMinimum":0,"maximum":1}},"required":["weight"],"additionalProperties":false},"routing_rule":{"type":"object","description":"Routing rule for dynamic provider/model selection","properties":{"id":{"type":"string","description":"Unique routing rule ID"},"name":{"type":"string","description":"Human-readable rule name"},"description":{"type":"string","description":"Optional description of the rule"},"enabled":{"type":"boolean","description":"Whether the rule is enabled","default":true},"cel_expression":{"type":"string","description":"CEL (Common Expression Language) expression for rule evaluation"},"chain_rule":{"type":"boolean","default":false,"description":"If true, re-evaluates routing chain after this rule matches"},"targets":{"type":"array","minItems":1,"description":"Weighted routing targets. Weights must sum to 1. Omit provider or model to use the incoming request value.","items":{"$ref":"#/$defs/routing_target"}},"provider":false,"model":false,"fallbacks":{"type":"array","description":"Fallback provider chain in order","items":{"type":"string"}},"scope":{"type":"string","enum":["global","team","customer","virtual_key"],"description":"Rule scope level","default":"global"},"scope_id":{"type":"string","description":"Entity ID for non-global scopes (required for non-global scope)"},"priority":{"type":"integer","description":"Evaluation priority within scope (lower = earlier)","default":0},"query":{"description":"Visual rule builder state for the management UI (react-querybuilder). Omitted unless exported from the dashboard. Not evaluated at routing runtime (cel_expression is). When present, must include combinator and rules[] so arbitrary metadata cannot be mistaken for builder state.","anyOf":[{"type":"null"},{"type":"object","required":["combinator","rules"],"properties":{"combinator":{"type":"string","enum":["and","or"]},"rules":{"type":"array","items":{"type":"object"},"description":"Leaf rules (field, operator, value) and/or nested combinator+rules groups from the query builder."}},"additionalProperties":true}]}},"required":["id","name","targets"],"additionalProperties":false,"if":{"properties":{"scope":{"enum":["team","customer","virtual_key"]}},"required":["scope"]},"then":{"required":["scope_id"],"properties":{"scope_id":{"type":"string","minLength":1}}}},"virtual_key_provider_config":{"type":"object","description":"Provider configuration for a virtual key","properties":{"id":{"type":"integer","description":"Provider config ID"},"virtual_key_id":{"type":"string","description":"Associated virtual key ID"},"provider":{"type":"string","description":"Provider name"},"weight":{"type":["number","null"],"description":"Weight for load balancing (null opts out of weighted routing)","default":null},"allowed_models":{"type":"array","description":"Allowed models for this provider config. Use [\"*\"] to allow all models; empty array denies all (deny-by-default).","items":{"type":"string"}},"blacklisted_models":{"type":"array","description":"Models blocked for this provider config even if matched by allowed_models. Use [\"*\"] to block all; empty array blocks none.","items":{"type":"string"}},"rate_limit_id":{"type":"string","description":"Associated rate limit ID"},"key_ids":{"type":"array","description":"Key identifiers allowed for this provider config. Use [\"*\"] to allow all keys. Semantics depend on version: v2 (default) empty = deny all; v1 empty = allow all. Values are the key IDs.","items":{"type":"string"}}},"required":["provider"],"additionalProperties":false},"virtual_key_mcp_config":{"type":"object","description":"MCP configuration for a virtual key","properties":{"id":{"type":"integer","description":"MCP config ID"},"virtual_key_id":{"type":"string","description":"Associated virtual key ID"},"mcp_client_id":{"type":"integer","description":"Associated MCP client ID (database format)"},"mcp_client_name":{"type":"string","description":"MCP client name (config file format — resolved to mcp_client_id at startup)"},"tools_to_execute":{"type":"array","description":"Include-only list of tools this Virtual Key is permitted to execute from this MCP client. ['*'] means all tools allowed, [] means no tools allowed (deny-by-default).","items":{"type":"string"}}},"additionalProperties":false},"complexity_tier_boundaries":{"type":"object","description":"Score thresholds used to classify complexity_tier values","properties":{"simple_medium":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1,"description":"Scores below this threshold are SIMPLE"},"medium_complex":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1,"description":"Scores below this threshold and at or above simple_medium are MEDIUM"},"complex_reasoning":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1,"description":"Scores below this threshold and at or above medium_complex are COMPLEX"}},"required":["simple_medium","medium_complex","complex_reasoning"],"additionalProperties":false},"complexity_analyzer_keywords":{"type":"object","description":"User-editable keyword lists for complexity analysis","properties":{"code_keywords":{"type":"array","minItems":1,"items":{"type":"string","minLength":1}},"reasoning_keywords":{"type":"array","minItems":1,"items":{"type":"string","minLength":1}},"technical_keywords":{"type":"array","minItems":1,"items":{"type":"string","minLength":1}},"simple_keywords":{"type":"array","minItems":1,"items":{"type":"string","minLength":1}}},"required":["code_keywords","reasoning_keywords","technical_keywords","simple_keywords"],"additionalProperties":false},"complexity_analyzer_config":{"type":"object","description":"Runtime configuration for complexity_tier CEL routing","properties":{"tier_boundaries":{"$ref":"#/$defs/complexity_tier_boundaries"},"keywords":{"$ref":"#/$defs/complexity_analyzer_keywords"}},"required":["tier_boundaries","keywords"],"additionalProperties":false},"auth_config":{"type":"object","description":"Authentication configuration. Deprecated: Use governance.auth_config instead.","properties":{"admin_username":{"type":"string","description":"Admin username"},"admin_password":{"type":"string","description":"Admin password"},"is_enabled":{"type":"boolean","description":"Whether authentication is enabled"},"disable_auth_on_inference":{"type":"boolean","deprecated":true,"description":"Deprecated and ignored. Use client_config.enforce_auth_on_inference instead."}},"additionalProperties":false},"pricing_config":{"type":"object","properties":{"pricing_url":{"type":"string","description":"Pricing URL","optional":true,"format":"uri"},"pricing_sync_interval":{"type":"integer","description":"Pricing sync interval in seconds. Default is 24 hours. Minimum is 3600 seconds (1 hour).","default":86400,"optional":true,"minimum":3600},"model_parameters_url":{"type":"string","description":"Model parameters URL","optional":true,"format":"uri"},"mcp_library_url":{"type":"string","description":"URL to a custom MCP server catalog. Leave empty to use the default Bifrost catalog.","optional":true,"format":"uri"},"mcp_library_sync_interval":{"type":"integer","description":"MCP library sync interval in seconds. Default is 24 hours. Minimum is 3600 seconds (1 hour).","default":86400,"optional":true,"minimum":3600}},"additionalProperties":false},"network_config":{"type":"object","properties":{"base_url":{"type":"string","format":"uri","description":"Base URL for the provider (optional, required for Ollama)"},"extra_headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional headers to send with requests"},"default_request_timeout_in_seconds":{"type":"integer","minimum":1,"description":"Default request timeout in seconds"},"max_retries":{"type":"integer","minimum":0,"description":"Maximum number of retries"},"retry_backoff_initial":{"type":"integer","minimum":100,"description":"Initial retry backoff in milliseconds"},"retry_backoff_max":{"type":"integer","minimum":100,"description":"Maximum retry backoff in milliseconds"},"enforce_http2":{"type":"boolean","description":"Force HTTP/2 on provider connections (relevant for Bedrock and other net/http-based providers)"},"insecure_skip_verify":{"type":"boolean","description":"Disable TLS certificate verification for provider connections. This bypasses server certificate validation and should be used only as a last resort when a trusted CA chain cannot be configured. Prefer ca_cert_pem for self-signed or private CA deployments."},"ca_cert_pem":{"type":"string","description":"PEM-encoded CA certificate to trust for provider endpoint connections (e.g. self-signed or internal CA). Supports inline PEM or env.VAR_NAME."},"stream_idle_timeout_in_seconds":{"type":"integer","minimum":5,"maximum":3600,"description":"Idle timeout per stream chunk in seconds. If no data is received for this many seconds, the stream is closed. Default: 120."},"max_conns_per_host":{"type":"integer","minimum":1,"maximum":10000,"description":"Maximum number of TCP connections per provider host. For HTTP/2 (e.g. Bedrock), each connection supports ~100 concurrent streams. Default: 5000."},"beta_header_overrides":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Override default Anthropic beta header support per provider. Keys are header prefixes (e.g. 'redact-thinking-'), values are true (supported) or false (unsupported). Headers not listed use the built-in defaults."},"allow_private_network":{"type":"boolean","description":"Allow connections to RFC 1918 private IPs (10.x, 172.16.x, 192.168.x). Enable for providers on a k8s pod network, LAN, or private VPC. Loopback addresses (localhost, 127.0.0.1, ::1) remain allowed regardless of this setting. Link-local addresses (169.254.x.x) are always blocked.","default":false}},"additionalProperties":false},"network_config_without_base_url":{"type":"object","properties":{"extra_headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional headers to send with requests"},"default_request_timeout_in_seconds":{"type":"integer","minimum":1,"description":"Default request timeout in seconds"},"max_retries":{"type":"integer","minimum":0,"description":"Maximum number of retries"},"retry_backoff_initial":{"type":"integer","minimum":100,"description":"Initial retry backoff in milliseconds"},"retry_backoff_max":{"type":"integer","minimum":100,"description":"Maximum retry backoff in milliseconds"},"enforce_http2":{"type":"boolean","description":"Force HTTP/2 on provider connections (relevant for Bedrock and other net/http-based providers)"},"insecure_skip_verify":{"type":"boolean","description":"Disable TLS certificate verification for provider connections. This bypasses server certificate validation and should be used only as a last resort when a trusted CA chain cannot be configured. Prefer ca_cert_pem for self-signed or private CA deployments."},"ca_cert_pem":{"type":"string","description":"PEM-encoded CA certificate to trust for provider endpoint connections (e.g. self-signed or internal CA)"},"stream_idle_timeout_in_seconds":{"type":"integer","minimum":5,"maximum":3600,"description":"Idle timeout per stream chunk in seconds. If no data is received for this many seconds, the stream is closed. Default: 120."},"max_conns_per_host":{"type":"integer","minimum":1,"maximum":10000,"description":"Maximum number of TCP connections per provider host. For HTTP/2 (e.g. Bedrock), each connection supports ~100 concurrent streams. Default: 5000."},"beta_header_overrides":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Override default Anthropic beta header support per provider. Keys are header prefixes (e.g. 'redact-thinking-'), values are true (supported) or false (unsupported). Headers not listed use the built-in defaults."},"allow_private_network":{"type":"boolean","description":"Allow connections to RFC 1918 private IPs (10.x, 172.16.x, 192.168.x). Enable for providers on a k8s pod network, LAN, or private VPC. Loopback addresses (localhost, 127.0.0.1, ::1) remain allowed regardless of this setting. Link-local addresses (169.254.x.x) are always blocked.","default":false}},"additionalProperties":false},"openai_config":{"type":"object","description":"OpenAI-specific provider settings","properties":{"disable_store":{"type":"boolean","description":"Disable OpenAI Responses API conversation storage."}},"additionalProperties":false},"concurrency_and_buffer_size":{"type":"object","properties":{"concurrency":{"type":"integer","minimum":1,"description":"Number of concurrent requests"},"buffer_size":{"type":"integer","minimum":1,"description":"Buffer size for requests"}},"required":["concurrency","buffer_size"],"additionalProperties":false},"base_key":{"type":"object","properties":{"name":{"type":"string","description":"Name of the key"},"value":{"type":"string","description":"API key value (can use env. prefix)"},"models":{"type":"array","items":{"type":"string"},"description":"Models this key can access. Use [\"*\"] to allow all models; empty array denies all (deny-by-default)."},"weight":{"type":"number","minimum":0,"description":"Weight for load balancing"},"use_for_batch_api":{"type":"boolean","description":"Whether this key can be used for batch API operations (default: false)","default":false},"aliases":{"type":"object","additionalProperties":{"oneOf":[{"type":"string","minLength":1,"description":"Legacy shape: a bare provider-specific identifier. Equivalent to {\"model_id\": \"<value>\"}."},{"type":"object","properties":{"model_id":{"type":"string","minLength":1,"description":"Provider-specific identifier sent on the wire (deployment name, inference profile ID, fine-tuned model ID, etc.)."},"model_name":{"type":"string","description":"Canonical model name used for pricing, logging, and family inference."},"model_family":{"type":"string","enum":["anthropic","openai","mistral","cohere","gemini","nova","titan"],"description":"Underlying model family. Used by provider routing without substring-sniffing the wire model ID."},"description":{"type":"string"},"region":{"type":"string","description":"Per-alias region override (can use env. prefix)."},"api_version":{"type":"string","description":"Azure OpenAI api-version override for this alias."},"anthropic_version":{"type":"string","description":"Azure anthropic-version header override for Claude-on-Azure deployments."},"endpoint":{"type":"string","description":"Per-alias Azure endpoint override (can use env. prefix)."},"project_id":{"type":"string","description":"Per-alias project override shared across providers: Vertex uses it as the GCP project; Bedrock and Bedrock Mantle send it as the AWS project via the OpenAI-Project / anthropic-workspace-id header (can use env. prefix)."},"project_number":{"type":"string","description":"Per-alias Vertex project number override (can use env. prefix)."},"force_single_region":{"type":"boolean","description":"Per-alias Vertex override: when true, call the alias region as-is and skip promoting multi-region-only models to a multi-region endpoint."},"inference_profile_arn":{"type":"string","description":"Per-alias Bedrock inference profile ARN (can use env. prefix)."},"use_deployments_endpoint":{"type":"boolean","description":"Replicate: use the deployments endpoint instead of the predictions endpoint for this alias."}},"required":["model_id"],"additionalProperties":false}]},"propertyNames":{"minLength":1},"description":"Model alias mappings: each entry maps a user-facing model name to either a bare provider identifier (legacy string shape) or an AliasConfig object carrying the wire identifier plus optional canonical name, family, and provider-specific overrides."}},"required":["name","weight"]},"bedrock_key":{"allOf":[{"$ref":"#/$defs/base_key"},{"type":"object","properties":{"bedrock_key_config":{"type":"object","properties":{"access_key":{"type":"string","description":"AWS access key (can use env. prefix)"},"secret_key":{"type":"string","description":"AWS secret key (can use env. prefix)"},"session_token":{"type":"string","description":"AWS session token (can use env. prefix)"},"region":{"type":"string","description":"AWS region"},"arn":{"type":"string","description":"AWS ARN"},"role_arn":{"type":"string","description":"AWS IAM role ARN for AssumeRole (can use env. prefix)"},"external_id":{"type":"string","description":"External ID for AssumeRole (can use env. prefix)"},"session_name":{"type":"string","description":"Role session name for AssumeRole (can use env. prefix)"},"project_id":{"type":"string","description":"Bedrock project ID scoping the Mantle sub-surface (OpenAI-compatible gpt-*/Gemma routing) via the OpenAI-Project header. When empty, AWS routes to the account's default project. No effect on the Converse/bedrock-runtime paths (can use env. prefix)."},"deployments":{"type":"object","additionalProperties":{"type":"string"},"description":"Model to deployment mappings"},"batch_s3_config":{"type":"object","description":"S3 bucket configuration for Bedrock batch operations","properties":{"buckets":{"type":"array","description":"List of S3 bucket configurations","items":{"type":"object","properties":{"bucket_name":{"type":"string","description":"S3 bucket name"},"prefix":{"type":"string","description":"S3 key prefix for batch files"},"is_default":{"type":"boolean","description":"Whether this is the default bucket for batch operations"}},"required":["bucket_name"],"additionalProperties":false}}},"additionalProperties":false}},"required":["region"],"additionalProperties":false}}}]},"bedrock_mantle_key":{"allOf":[{"$ref":"#/$defs/base_key"},{"type":"object","properties":{"bedrock_mantle_key_config":{"type":"object","properties":{"access_key":{"type":"string","description":"AWS access key for SigV4 (can use env. prefix)"},"secret_key":{"type":"string","description":"AWS secret key for SigV4 (can use env. prefix)"},"session_token":{"type":"string","description":"AWS session token for temporary credentials (can use env. prefix)"},"region":{"type":"string","description":"AWS region used to build the bedrock-mantle endpoint host"},"role_arn":{"type":"string","description":"AWS IAM role ARN for AssumeRole (can use env. prefix)"},"external_id":{"type":"string","description":"External ID for AssumeRole (can use env. prefix)"},"session_name":{"type":"string","description":"Role session name for AssumeRole (can use env. prefix)"},"project_id":{"type":"string","description":"Bedrock project ID scoping inference and model listing. Sent as the OpenAI-Project header on the OpenAI-compatible surface and the anthropic-workspace-id header on the native-Anthropic (Claude) surface. When empty, AWS routes to the account's default project (can use env. prefix)."}},"required":["region"],"additionalProperties":false}}}]},"vllm_key":{"allOf":[{"$ref":"#/$defs/base_key"},{"type":"object","properties":{"vllm_key_config":{"type":"object","properties":{"url":{"type":"string","minLength":1,"description":"VLLM server base URL (can use env. prefix)"},"model_name":{"type":"string","minLength":1,"description":"Exact model name served on this VLLM instance"}},"required":["url","model_name"],"additionalProperties":false}},"required":["vllm_key_config"]}]},"replicate_key":{"allOf":[{"$ref":"#/$defs/base_key"},{"type":"object","properties":{"replicate_key_config":{"type":"object","properties":{"use_deployments_endpoint":{"type":"boolean","description":"Whether to use the deployments endpoint instead of the models endpoint (default: false)"}},"additionalProperties":false}}}]},"ollama_key":{"allOf":[{"$ref":"#/$defs/base_key"},{"type":"object","properties":{"ollama_key_config":{"type":"object","properties":{"url":{"type":"string","minLength":1,"description":"Ollama server base URL (can use env. prefix)"}},"required":["url"],"additionalProperties":false}},"required":["ollama_key_config"]}]},"sgl_key":{"allOf":[{"$ref":"#/$defs/base_key"},{"type":"object","properties":{"sgl_key_config":{"type":"object","properties":{"url":{"type":"string","minLength":1,"description":"SGLang server base URL (can use env. prefix)"}},"required":["url"],"additionalProperties":false}},"required":["sgl_key_config"]}]},"azure_key":{"allOf":[{"$ref":"#/$defs/base_key"},{"type":"object","properties":{"azure_key_config":{"type":"object","properties":{"endpoint":{"type":"string","description":"Azure endpoint (can use env. prefix)"},"client_id":{"type":"string","description":"Azure client ID for Entra authentication (can use env. prefix)"},"client_secret":{"type":"string","description":"Azure client secret for Entra authentication (can use env. prefix)"},"tenant_id":{"type":"string","description":"Azure tenant ID for Entra authentication (can use env. prefix)"},"scopes":{"type":"array","items":{"type":"string"},"description":"OAuth2 scopes for Entra authentication"},"api_version":{"type":"string","description":"Deprecated: Bifrost now uses the Azure OpenAI v1 API which does not require an api-version parameter."}},"required":["endpoint"],"dependentRequired":{"client_id":["client_secret","tenant_id"],"client_secret":["client_id","tenant_id"],"tenant_id":["client_id","client_secret"]},"additionalProperties":false}},"required":["azure_key_config"]}]},"vertex_key":{"allOf":[{"$ref":"#/$defs/base_key"},{"type":"object","properties":{"vertex_key_config":{"type":"object","properties":{"project_id":{"type":"string","description":"Google Cloud project ID (can use env. prefix)"},"project_number":{"type":"string","description":"Google Cloud project number"},"region":{"type":"string","description":"Google Cloud region"},"auth_credentials":{"type":"string","description":"Authentication credentials (can use env. prefix)"},"force_single_region":{"type":"boolean","description":"When true, always call the configured region and skip automatic promotion of multi-region-only models to a multi-region endpoint. Enable for provisioned throughput.","default":false}},"required":["project_id","region"],"additionalProperties":false}},"required":["vertex_key_config"]}]},"provider":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/base_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"required":["keys"],"additionalProperties":false},"provider_with_bedrock_config":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/bedrock_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"required":["keys"],"additionalProperties":false},"provider_with_bedrock_mantle_config":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/bedrock_mantle_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"required":["keys"],"additionalProperties":false},"provider_with_vllm_config":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/vllm_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config_without_base_url"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"required":["keys"],"additionalProperties":false},"provider_with_replicate_config":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/replicate_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"required":["keys"],"additionalProperties":false},"provider_with_azure_config":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/azure_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"required":["keys"],"additionalProperties":false},"provider_with_vertex_config":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/vertex_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"required":["keys"],"additionalProperties":false},"provider_with_ollama_config":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/ollama_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"additionalProperties":false},"provider_with_sgl_config":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/$defs/sgl_key"},"minItems":1,"description":"API keys for this provider"},"network_config":{"$ref":"#/$defs/network_config"},"concurrency_and_buffer_size":{"$ref":"#/$defs/concurrency_and_buffer_size"},"proxy_config":{"$ref":"#/$defs/proxy_config"},"send_back_raw_request":{"type":"boolean","description":"Include raw request in BifrostResponse (default: false)"},"send_back_raw_response":{"type":"boolean","description":"Include raw response in BifrostResponse (default: false)"},"store_raw_request_response":{"type":"boolean","description":"Capture raw request/response for internal logging only; strip from API responses returned to clients (default: false)"},"custom_provider_config":{"$ref":"#/$defs/custom_provider_config"}},"additionalProperties":false},"mcp_client_config":{"type":"object","properties":{"client_id":{"type":"string","description":"MCP client identifier"},"name":{"type":"string","description":"Name of the MCP client"},"is_code_mode_client":{"type":"boolean","description":"Whether this client is a code mode client"},"connection_type":{"type":"string","enum":["stdio","http","sse","inprocess"],"description":"Connection type for MCP client"},"connection_string":{"type":"string","description":"HTTP or SSE URL (alternative to http_config sub-object, required for HTTP or SSE connections)"},"auth_type":{"type":"string","enum":["none","headers","oauth","per_user_oauth","per_user_headers"],"description":"Authentication type for MCP connection"},"oauth_config_id":{"type":"string","description":"OAuth config ID reference (required when auth_type is 'oauth' or 'per_user_oauth')"},"headers":{"type":"object","description":"Headers to send with the request (for headers auth type)","additionalProperties":{"type":"string"}},"per_user_header_keys":{"type":"array","description":"Header names each caller must supply when auth_type is 'per_user_headers'. Required (non-empty) for that auth type.","items":{"type":"string"}},"stdio_config":{"type":"object","properties":{"command":{"type":"string","description":"Command to execute"},"args":{"type":"array","items":{"type":"string"},"description":"Command arguments"},"envs":{"type":"array","items":{"type":"string"},"description":"Environment variables"}},"required":["command"],"additionalProperties":false},"tools_to_execute":{"type":"array","items":{"type":"string"},"description":"Include-only list of tools to execute. ['*'] means all, [] means none."},"tools_to_auto_execute":{"type":"array","items":{"type":"string"},"description":"Auto-execute list of tools. ['*'] means all, [] means none."},"tool_sync_interval":{"description":"Per-client override for tool sync interval. Prefer Go duration strings (e.g. '10m', '-1s', '0s' = use global). Legacy integer nanoseconds are also supported for backward compatibility.","oneOf":[{"type":"string","pattern":"^-?(?:\\d+(?:\\.\\d+)?(?:ns|us|µs|ms|s|m|h))+$"},{"type":"integer"}]},"tool_execution_timeout":{"description":"Per-client override for tool execution timeout. Accepts a Go duration string (e.g. '30s', '2m') or a bare integer treated as seconds. When set, overrides the global tool_manager_config.tool_execution_timeout for this MCP server only. Omit or set to 0 to use the global default.","oneOf":[{"type":"string","pattern":"^(?:\\d+(?:\\.\\d+)?(?:ns|us|µs|ms|s|m|h))+$"},{"type":"integer","minimum":0}]},"allowed_extra_headers":{"type":"array","items":{"type":"string"},"description":"Allowlist of request-level headers that callers may forward to this MCP server at execution time. Use ['*'] to allow all headers."},"is_ping_available":{"type":"boolean","description":"Whether the MCP server supports ping for health checks (default: true)","default":true},"tool_pricing":{"type":"object","description":"Tool pricing map (tool name to cost per execution)","additionalProperties":{"type":"number","minimum":0}},"allow_on_all_virtual_keys":{"type":"boolean","description":"When true, this MCP server is accessible to all virtual keys without requiring explicit per-key assignment. All tools are allowed by default. If a virtual key has an explicit MCP config for this server, that config takes precedence and overrides this behaviour.","default":false},"disabled":{"type":"boolean","description":"When true, this MCP client is disabled (connection and workers are stopped while preserving configuration).","default":false},"tls_config":{"type":"object","description":"TLS configuration for HTTP and SSE connections. Not applicable to stdio or inprocess connection types.","properties":{"insecure_skip_verify":{"type":"boolean","description":"Disable TLS certificate verification. Takes priority over ca_cert_pem when both are set. Use only in development or trusted isolated environments. Not recommended for production."},"ca_cert_pem":{"type":"string","description":"PEM-encoded CA certificate to trust for MCP server connections. Use when the MCP server uses a self-signed or private CA certificate. Supports env.VAR_NAME syntax to read the certificate from an environment variable."}},"additionalProperties":false}},"required":["name","connection_type"],"additionalProperties":false,"if":{"properties":{"auth_type":{"enum":["oauth","per_user_oauth"]}},"required":["auth_type"]},"then":{"required":["oauth_config_id"]},"oneOf":[{"properties":{"connection_type":{"const":"stdio"}},"required":["stdio_config"]},{"properties":{"connection_type":{"const":"websocket"}},"required":["websocket_config"]},{"properties":{"connection_type":{"const":"http"}},"anyOf":[{"required":["http_config"]},{"required":["connection_string"]}]},{"properties":{"connection_type":{"const":"sse"}},"required":["connection_string"]}]},"mcp_tool_manager_config":{"type":"object","properties":{"tool_execution_timeout":{"type":["integer","string"],"description":"Tool execution timeout. Accepts a duration string (e.g. \"30s\", \"2m\") or an integer number of seconds (e.g. 30 means 30 seconds).","minimum":1,"default":30},"max_agent_depth":{"type":"integer","description":"Max agent depth","minimum":1,"default":10},"code_mode_binding_level":{"type":"string","enum":["server","tool"],"description":"How tools are exposed in VFS for code execution"},"disable_auto_tool_inject":{"type":"boolean","description":"When true, MCP tools are not automatically injected into requests. Tools are only included when explicitly specified via request context filters or headers, such as x-bf-mcp-include-tools or x-bf-mcp-include-clients.","default":false}}},"mcp_tool_group_config":{"type":"object","properties":{"id":{"type":"integer","minimum":1,"description":"DB ID of this tool group. When set, the reconciler updates the existing group with this ID rather than matching by name."},"name":{"type":"string","description":"Tool group name"},"description":{"type":"string","description":"Tool group description"},"enabled":{"type":"boolean","description":"Whether tool group is enabled","default":true},"tools":{"type":"array","minItems":1,"description":"MCP tools included in this group","items":{"type":"object","properties":{"mcp_client_id":{"type":"string","description":"MCP client ID"},"mcp_client_name":{"type":"string","description":"MCP client name (resolved to client_id at startup)"},"tool_names":{"type":"array","description":"Tool names to allow. Empty means all tools from this MCP client.","items":{"type":"string"}}},"oneOf":[{"required":["mcp_client_id"]},{"required":["mcp_client_name"]}],"additionalProperties":false}},"virtual_key_ids":{"type":"array","items":{"type":"string"}},"team_ids":{"type":"array","items":{"type":"string"}},"customer_ids":{"type":"array","items":{"type":"string"}},"user_ids":{"type":"array","items":{"type":"string"}},"provider_names":{"type":"array","items":{"type":"string"}},"api_key_ids":{"type":"array","items":{"type":"integer"}}},"required":["name","tools"],"additionalProperties":false},"weaviate_config":{"type":"object","description":"Weaviate configuration for vector store","properties":{"scheme":{"type":"string","description":"Weaviate server scheme (http or https) - REQUIRED"},"host":{"type":"string","description":"Weaviate server host (host:port) - REQUIRED"},"api_key":{"type":"string","description":"API key for Weaviate authentication (optional)"},"grpc_config":{"type":"object","properties":{"host":{"type":"string","description":"Weaviate server host (host:port). If host is without a port number then the 80 port for insecured and 443 port for secured connections will be used."},"secured":{"type":"boolean","description":"Secured set it to true if it's a secured connection"}}},"headers":{"type":"object","description":"Additional headers to send with requests"},"timeout":{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","description":"Timeout for Weaviate operations (e.g., '5s')"},"class_name":{"type":"string","description":"Class name for Weaviate vector store"},"properties":{"type":"array","items":{"type":"object"},"description":"Properties for Weaviate vector store"}},"required":["scheme","host"],"additionalProperties":false},"redis_config":{"type":"object","description":"Redis configuration for vector store (also used for Valkey-compatible endpoints)","properties":{"addr":{"type":"string","description":"Redis/Valkey server address (host:port) - REQUIRED (can use env. prefix)"},"username":{"type":"string","description":"Username for Redis AUTH (optional, can use env. prefix)"},"password":{"type":"string","description":"Password for Redis AUTH (optional, can use env. prefix)"},"db":{"type":"integer","description":"Redis database number (default: 0)","default":0},"use_tls":{"type":"boolean","description":"Use TLS for the Redis/Valkey connection (optional)","default":false},"insecure_skip_verify":{"type":"boolean","description":"Skip TLS certificate verification for Redis/Valkey connections. Use only when a trusted CA cannot be configured.","default":false},"ca_cert_pem":{"type":"string","description":"PEM-encoded CA certificate to trust for Redis/Valkey TLS connections"},"cluster_mode":{"type":"boolean","description":"Use Redis Cluster mode. Required for cluster configuration endpoints; when enabled, db must be 0.","default":false},"pool_size":{"type":"integer","description":"Maximum number of socket connections (optional)"},"max_active_conns":{"type":"integer","description":"Maximum number of active connections (optional)"},"min_idle_conns":{"type":"integer","description":"Minimum number of idle connections (optional)"},"max_idle_conns":{"type":"integer","description":"Maximum number of idle connections (optional)"},"conn_max_lifetime":{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","description":"Connection maximum lifetime (e.g., '30m')"},"conn_max_idle_time":{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","description":"Connection maximum idle time (e.g., '5m')"},"dial_timeout":{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","description":"Timeout for socket connection (e.g., '5s')"},"read_timeout":{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","description":"Timeout for socket reads (e.g., '3s')"},"write_timeout":{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","description":"Timeout for socket writes (e.g., '3s')"},"context_timeout":{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","description":"Timeout for Redis operations (e.g., '10s')"}},"required":["addr"],"additionalProperties":false},"qdrant_config":{"type":"object","description":"Qdrant configuration for vector store","properties":{"host":{"type":"string","description":"Qdrant server host - REQUIRED (can use env. prefix)"},"port":{"type":"integer","description":"Qdrant server port (default: 6334 for gRPC)","default":6334},"api_key":{"type":"string","description":"API key for authentication (optional, can use env. prefix)"},"use_tls":{"type":"boolean","description":"Use TLS for connection (optional)","default":false},"max_recv_msg_size_mb":{"type":"integer","description":"gRPC max receive message size in MB (default: 64). Increase when caching large payloads such as base64-encoded image generation responses.","minimum":1,"default":64}},"required":["host"],"additionalProperties":false},"pinecone_config":{"type":"object","description":"Pinecone configuration for vector store","properties":{"api_key":{"type":"string","description":"Pinecone API key - REQUIRED (can use env. prefix)"},"index_host":{"type":"string","description":"Index host URL from Pinecone console - REQUIRED (e.g., your-index.svc.environment.pinecone.io)"}},"required":["api_key","index_host"],"additionalProperties":false},"proxy_config":{"type":"object","description":"Proxy configuration for provider connections","properties":{"type":{"type":"string","enum":["none","http","socks5","environment"],"description":"Type of proxy to use"},"url":{"oneOf":[{"type":"string","pattern":"^env\\.[A-Za-z_][A-Za-z0-9_]*$"},{"type":"string","format":"uri"}],"description":"URL of the proxy server (supports env.VAR_NAME or a literal URI)"},"username":{"type":"string","description":"Username for proxy authentication (supports env.VAR_NAME)"},"password":{"type":"string","description":"Password for proxy authentication (supports env.VAR_NAME)"},"ca_cert_pem":{"type":"string","description":"PEM-encoded CA certificate to trust for TLS connections through the proxy (for SSL-intercepting proxies, supports env.VAR_NAME)"}},"required":["type"],"additionalProperties":false},"cluster_config":{"type":"object","description":"Cluster mode configuration","properties":{"enabled":{"type":"boolean","description":"Whether cluster mode is enabled"},"type":{"type":"string","enum":["mesh","broker"],"default":"mesh","description":"Clustering mode. 'mesh' (default) is peer-to-peer via memberlist gossip. 'broker' routes all cluster traffic through a central broker process, for platforms without peer-to-peer connectivity (e.g. Cloud Run)."},"region":{"type":"string","description":"Region label for cluster deployment (runtime default: unknown)"},"peers":{"type":"array","description":"List of peer addresses","items":{"type":"string","description":"Peer address in host:port format"}},"gossip":{"type":"object","description":"Gossip protocol configuration","properties":{"port":{"type":"integer","minimum":1,"maximum":65535,"description":"Port for gossip communication"},"config":{"type":"object","description":"Gossip protocol settings","properties":{"timeout_seconds":{"type":"integer","minimum":1,"description":"Timeout for operations in seconds"},"success_threshold":{"type":"integer","minimum":1,"description":"Number of successful probes required"},"failure_threshold":{"type":"integer","minimum":1,"description":"Number of failed probes before marking as failed"}},"required":["timeout_seconds","success_threshold","failure_threshold"],"additionalProperties":false}},"required":["port","config"],"additionalProperties":false},"grpc":{"type":"object","description":"gRPC transport settings for the cluster counter-sync layer. Replaces the memberlist gossip broadcast path for governance usage counters; memberlist continues to handle cluster membership and other entity sync.","properties":{"port":{"type":"integer","minimum":1,"maximum":65535,"description":"TCP port the gRPC server listens on","default":10102},"dial_timeout_seconds":{"type":"integer","minimum":1,"description":"How long to wait when dialing a peer, in seconds","default":5}},"additionalProperties":false},"discovery":{"type":"object","description":"Auto-discovery configuration for cluster nodes","properties":{"enabled":{"type":"boolean","description":"Whether auto-discovery is enabled"},"type":{"type":"string","enum":["kubernetes","dns","udp","consul","etcd","mdns"],"description":"Discovery mechanism type"},"service_name":{"type":"string","description":"Service name used for discovery (used by consul, etcd, UDP, and mDNS)"},"bind_port":{"type":"integer","minimum":1,"maximum":65535,"description":"Port to bind for cluster communication"},"dial_timeout":{"type":"string","description":"Timeout for discovery dial operations as a Go duration string (e.g. '5s', '1m')"},"allowed_address_space":{"type":"array","items":{"type":"string"},"description":"CIDR notation for allowed address spaces (e.g., ['10.0.0.0/8', '192.168.0.0/16'])"},"k8s_namespace":{"type":"string","description":"Kubernetes namespace for service discovery"},"k8s_label_selector":{"type":"string","description":"Kubernetes label selector for filtering pods"},"dns_names":{"type":"array","items":{"type":"string"},"description":"DNS names to resolve for node discovery. Supports env.VAR_NAME for environment variable substitution."},"udp_broadcast_port":{"type":"integer","minimum":1,"maximum":65535,"description":"Port for UDP broadcast discovery"},"consul_address":{"type":"string","description":"Consul server address for service discovery"},"etcd_endpoints":{"type":"array","items":{"type":"string"},"description":"Etcd endpoints for service discovery"},"mdns_service":{"type":"string","description":"mDNS service name for local network discovery"}},"required":["type"],"additionalProperties":false},"broker":{"type":"object","description":"Broker settings, used when type is 'broker'","properties":{"address":{"type":"string","description":"host:port of the broker that nodes dial"},"tls":{"type":"boolean","description":"Whether to dial the broker over TLS"},"auth_token":{"type":"string","description":"Optional shared secret sent on connect"},"listen_port":{"type":"integer","minimum":1,"maximum":65535,"description":"Port the broker process serves on (default: 50051)"}},"required":["address"],"additionalProperties":false}},"required":["enabled"],"additionalProperties":false},"scim_config":{"type":"object","description":"SAML/SCIM (System for Cross-domain Identity Management) configuration","properties":{"enabled":{"type":"boolean","description":"Whether SAML/SCIM authentication is enabled"},"provider":{"type":"string","enum":["okta","entra","keycloak","zitadel","google","sailpoint","generic"],"description":"SCIM provider type"},"config":{"type":"object","description":"Provider-specific configuration"}},"required":["enabled"],"additionalProperties":false,"allOf":[{"if":{"properties":{"enabled":{"const":true},"provider":{"const":"okta"}},"required":["enabled","provider"]},"then":{"properties":{"config":{"$ref":"#/$defs/okta_config"}}}},{"if":{"properties":{"enabled":{"const":true},"provider":{"const":"entra"}},"required":["enabled","provider"]},"then":{"properties":{"config":{"$ref":"#/$defs/entra_config"}}}},{"if":{"properties":{"enabled":{"const":true},"provider":{"const":"keycloak"}},"required":["enabled","provider"]},"then":{"properties":{"config":{"$ref":"#/$defs/keycloak_config"}}}},{"if":{"properties":{"enabled":{"const":true},"provider":{"const":"generic"}},"required":["enabled","provider"]},"then":{"properties":{"config":{"$ref":"#/$defs/generic_config"}}}},{"if":{"properties":{"enabled":{"const":true},"provider":{"const":"zitadel"}},"required":["enabled","provider"]},"then":{"properties":{"config":{"$ref":"#/$defs/zitadel_config"}}}},{"if":{"properties":{"enabled":{"const":true},"provider":{"const":"google"}},"required":["enabled","provider"]},"then":{"properties":{"config":{"$ref":"#/$defs/google_config"}}}},{"if":{"properties":{"enabled":{"const":true},"provider":{"const":"sailpoint"}},"required":["enabled","provider"]},"then":{"properties":{"config":{"$ref":"#/$defs/sailpoint_config"}}}}]},"okta_config":{"type":"object","description":"Okta JWT authentication configuration","properties":{"issuerUrl":{"type":"string","format":"uri","description":"Okta issuer URL (e.g., https://your-domain.okta.com/oauth2/default)"},"authServerType":{"type":"string","enum":["org","custom"],"description":"'org' for Org Authorization Server or 'custom' for Custom Authorization Server. Auto-detected from issuer URL when omitted."},"clientId":{"type":"string","description":"Okta application client ID"},"clientSecret":{"type":"string","description":"Okta client secret"},"apiToken":{"type":"string","description":"Okta API token for Admin API access"},"audience":{"type":"string","description":"JWT audience for validation (optional)"},"userIdField":{"type":"string","description":"JWT claim field for user ID (default: 'sub')","default":"sub"},"teamIdsField":{"type":"string","description":"JWT claim field for team IDs (default: 'groups')","default":"groups"},"rolesField":{"type":"string","description":"JWT claim field for roles (default: 'roles')","default":"roles"},"attributeRoleMappings":{"$ref":"#/$defs/scim_attribute_role_mappings"},"attributeTeamMappings":{"$ref":"#/$defs/scim_attribute_team_mappings"},"attributeBusinessUnitMappings":{"$ref":"#/$defs/scim_attribute_business_unit_mappings"},"claimScimAttributes":{"$ref":"#/$defs/scim_claim_attributes"},"provisioningToken":{"$ref":"#/$defs/scim_provisioning_token"}},"required":["issuerUrl","clientId","clientSecret","apiToken"],"additionalProperties":false},"entra_config":{"type":"object","description":"Microsoft Entra ID (formerly Azure AD) JWT authentication configuration","properties":{"tenantId":{"type":"string","description":"Azure tenant ID or 'common' for multi-tenant applications"},"clientId":{"type":"string","description":"Application (client) ID from Azure portal"},"clientSecret":{"type":"string","description":"Client secret (optional, required for token revocation)"},"cloud":{"type":"string","enum":["commercial","gcc-high","dod"],"default":"commercial","description":"Cloud environment: 'commercial' (default), 'gcc-high' for US Government GCC High, or 'dod' for Department of Defense"},"audience":{"type":"string","description":"JWT audience for validation (default: clientId)"},"appIdUri":{"type":"string","format":"uri","description":"App ID URI for v1.0 tokens (e.g., api://{clientId})"},"userIdField":{"type":"string","description":"JWT claim field for user ID (default: 'oid')","default":"oid"},"teamIdsField":{"type":"string","description":"JWT claim field for team IDs (default: 'groups')","default":"groups"},"rolesField":{"type":"string","description":"JWT claim field for roles (default: 'roles')","default":"roles"},"attributeRoleMappings":{"$ref":"#/$defs/scim_attribute_role_mappings"},"attributeTeamMappings":{"$ref":"#/$defs/scim_attribute_team_mappings"},"attributeBusinessUnitMappings":{"$ref":"#/$defs/scim_attribute_business_unit_mappings"},"claimScimAttributes":{"$ref":"#/$defs/scim_claim_attributes"},"provisioningToken":{"$ref":"#/$defs/scim_provisioning_token"}},"required":["tenantId","clientId"],"additionalProperties":false},"keycloak_config":{"type":"object","description":"Keycloak OIDC/SCIM authentication configuration","properties":{"serverUrl":{"type":"string","format":"uri","description":"Base URL of the Keycloak server (e.g., https://keycloak.company.com). Must NOT include the /realms/{realm} suffix."},"realm":{"type":"string","description":"Keycloak realm name (e.g., 'bifrost-prod')"},"clientId":{"type":"string","description":"Keycloak client ID for the confidential client used by Bifrost"},"clientSecret":{"type":"string","description":"Keycloak client secret. Supports env. prefix for environment variable references (e.g., 'env.KEYCLOAK_CLIENT_SECRET')"},"audience":{"type":"string","description":"Expected JWT audience (default: clientId)"},"userIdField":{"type":"string","description":"JWT claim field for user ID (default: 'sub')","default":"sub"},"teamIdsField":{"type":"string","description":"JWT claim field for team IDs (default: 'groups')","default":"groups"},"rolesField":{"type":"string","description":"JWT claim field for roles (default: 'roles')","default":"roles"},"attributeRoleMappings":{"$ref":"#/$defs/scim_attribute_role_mappings"},"attributeTeamMappings":{"$ref":"#/$defs/scim_attribute_team_mappings"},"attributeBusinessUnitMappings":{"$ref":"#/$defs/scim_attribute_business_unit_mappings"}},"required":["serverUrl","realm","clientId","clientSecret"],"additionalProperties":false},"generic_config":{"type":"object","description":"Generic OIDC authentication configuration for any standards-compliant OIDC identity provider. Endpoints are resolved via OIDC discovery (.well-known/openid-configuration) from issuerUrl unless overridden.","properties":{"issuerUrl":{"type":"string","format":"uri","description":"OIDC issuer URL (e.g., https://idp.company.com)"},"clientId":{"type":"string","description":"OAuth2/OIDC application client ID"},"clientSecret":{"type":"string","description":"OAuth2/OIDC client secret (optional, for confidential clients). Supports env. prefix for environment variable references."},"audience":{"type":"string","description":"JWT audience for token validation (optional)"},"authorizationEndpoint":{"type":"string","format":"uri","description":"Manual override for the authorization endpoint (used in preference to discovery when set)"},"tokenEndpoint":{"type":"string","format":"uri","description":"Manual override for the token endpoint (used in preference to discovery when set)"},"userinfoEndpoint":{"type":"string","format":"uri","description":"Manual override for the userinfo endpoint (used in preference to discovery when set)"},"teamIdsField":{"type":"string","description":"JWT claim field for team/group IDs (default: 'groups')","default":"groups"},"rolesField":{"type":"string","description":"JWT claim field for role names (optional)"},"scopes":{"type":"array","description":"Override the default OIDC scopes requested during login","items":{"type":"string"}},"attributeRoleMappings":{"$ref":"#/$defs/scim_attribute_role_mappings"},"attributeTeamMappings":{"$ref":"#/$defs/scim_attribute_team_mappings"},"attributeBusinessUnitMappings":{"$ref":"#/$defs/scim_attribute_business_unit_mappings"},"claimScimAttributes":{"$ref":"#/$defs/scim_claim_attributes"},"provisioningToken":{"$ref":"#/$defs/scim_provisioning_token"}},"required":["issuerUrl","clientId"],"additionalProperties":false},"zitadel_config":{"type":"object","description":"Zitadel OIDC authentication configuration","properties":{"domain":{"type":"string","format":"hostname","pattern":"^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$","description":"Zitadel instance domain (e.g., 'my-instance.zitadel.cloud' or 'auth.company.com'). Bare host only - do NOT include the scheme, port, or path."},"clientId":{"type":"string","description":"Zitadel application client ID"},"clientSecret":{"type":"string","description":"Zitadel client secret (optional, required for confidential clients and token revocation)"},"projectId":{"type":"string","description":"Optional Zitadel project ID for project-scoped role claims"},"audience":{"type":"string","description":"Access-token audience override (default: clientId)"},"serviceAccountClientId":{"type":"string","description":"Service account client ID for Zitadel Management API (required for user provisioning - web apps cannot use client_credentials)"},"serviceAccountClientSecret":{"type":"string","description":"Service account client secret for Zitadel Management API"},"teamIdsField":{"type":"string","description":"JWT claim field for team/group IDs (default: 'groups')","default":"groups"},"attributeRoleMappings":{"$ref":"#/$defs/scim_attribute_role_mappings"},"attributeTeamMappings":{"$ref":"#/$defs/scim_attribute_team_mappings"},"attributeBusinessUnitMappings":{"$ref":"#/$defs/scim_attribute_business_unit_mappings"},"claimScimAttributes":{"$ref":"#/$defs/scim_claim_attributes"}},"required":["domain","clientId"],"additionalProperties":false},"google_config":{"type":"object","description":"Google Workspace OIDC authentication configuration","properties":{"domain":{"type":"string","format":"hostname","pattern":"^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$","description":"Google Workspace primary domain (e.g., 'company.com'). Bare host only - do NOT include the scheme, port, or path."},"clientId":{"type":"string","description":"Google OAuth2 client ID"},"clientSecret":{"type":"string","description":"Google client secret (optional, used for token revocation)"},"credentialMode":{"type":"string","enum":["","inherit","env","file"],"description":"How Directory API credentials are sourced. 'inherit' uses Application Default Credentials; 'env' uses serviceAccountEnvVar; 'file' uses serviceAccountFile."},"serviceAccountEnvVar":{"type":"string","description":"Name of the environment variable containing the service account JSON (used when credentialMode is 'env'). Required for Directory API access without ADC."},"serviceAccountFile":{"type":"string","description":"Filesystem path to the service account JSON key file (used when credentialMode is 'file')."},"adminEmail":{"type":"string","format":"email","description":"Admin email for domain-wide delegation. Required whenever Directory API access is configured."},"impersonateServiceAccount":{"type":"string","description":"GCP service account email to impersonate when using ADC (Workload Identity); must have domain-wide delegation configured."},"audience":{"type":"string","description":"JWT audience override (default: clientId)"},"teamIdsField":{"type":"string","description":"Claim field for team/group IDs (default: 'groups')","default":"groups"},"attributeRoleMappings":{"$ref":"#/$defs/scim_attribute_role_mappings"},"attributeTeamMappings":{"$ref":"#/$defs/scim_attribute_team_mappings"},"attributeBusinessUnitMappings":{"$ref":"#/$defs/scim_attribute_business_unit_mappings"},"claimScimAttributes":{"$ref":"#/$defs/scim_claim_attributes"}},"required":["domain","clientId"],"additionalProperties":false,"allOf":[{"if":{"properties":{"credentialMode":{"const":"env"}},"required":["credentialMode"]},"then":{"required":["serviceAccountEnvVar"]}},{"if":{"properties":{"credentialMode":{"const":"file"}},"required":["credentialMode"]},"then":{"required":["serviceAccountFile"]}},{"if":{"properties":{"credentialMode":{"enum":["inherit","env","file"]}},"required":["credentialMode"]},"then":{"required":["adminEmail"]}}]},"sailpoint_config":{"type":"object","description":"SailPoint identity security platform configuration","properties":{"product":{"type":"string","enum":["isc","iiq"],"description":"SailPoint product type: 'isc' for Identity Security Cloud, 'iiq' for IdentityIQ"},"tenant":{"type":"string","description":"ISC tenant identifier (required for ISC product)"},"baseUrl":{"type":"string","format":"uri","description":"IdentityIQ base URL (required for IIQ product)"},"username":{"type":"string","description":"Username for IdentityIQ authentication"},"password":{"type":"string","description":"Password for IdentityIQ authentication"},"clientId":{"type":"string","description":"OAuth2 client ID"},"clientSecret":{"type":"string","description":"OAuth2 client secret"},"teamIdsField":{"type":"string","description":"JWT claim field for team IDs"},"attributeRoleMappings":{"$ref":"#/$defs/scim_attribute_role_mappings"},"attributeTeamMappings":{"$ref":"#/$defs/scim_attribute_team_mappings"},"attributeBusinessUnitMappings":{"$ref":"#/$defs/scim_attribute_business_unit_mappings"},"claimScimAttributes":{"$ref":"#/$defs/scim_claim_attributes"},"provisioningToken":{"$ref":"#/$defs/scim_provisioning_token"}},"required":["product"],"additionalProperties":false},"scim_claim_attributes":{"type":"object","description":"Per-claim SCIM interpretation. Maps each claim name to its SCIM source type and attribute key.","additionalProperties":{"type":"object","properties":{"attributeType":{"type":"string","enum":["user","group"],"description":"'user' reads from SCIM User resource attributes; 'group' matches SCIM Group resource."},"attributeValue":{"type":"string","description":"SCIM attribute key or group match field for this claim."}},"required":["attributeType","attributeValue"],"additionalProperties":false}},"scim_provisioning_token":{"type":"string","description":"Bearer token that inbound SCIM 2.0 provisioning clients (the IdP's SCIM app) must present in the Authorization header to push users and groups to Bifrost. Normally minted in the dashboard (Governance -> User Provisioning) and shown once, but may be seeded here for declarative/GitOps deployments; supports the env. prefix for environment-variable references. Generate one with: openssl rand -base64 32 | tr '+/' '-_' | tr -d '='"},"load_balancer_config":{"type":"object","description":"Load balancer configuration for intelligent request routing","properties":{"enabled":{"type":"boolean","description":"Whether load balancing is enabled"},"direction_selection_enabled":{"type":"boolean","description":"Enable adaptive provider (direction) selection. Defaults to true; omit to leave on."},"route_selection_enabled":{"type":"boolean","description":"Enable adaptive per-key (route) selection. Defaults to true; omit to leave on."},"reroute_failed_directions":{"type":"boolean","description":"When a pinned provider's direction is unhealthy, re-route the request to a healthy provider. Defaults to false."},"prune_failed_fallbacks":{"type":"boolean","description":"Drop unhealthy directions from a request's configured fallbacks. Defaults to false."},"tracker_config":{"type":"object","description":"Configuration for tracking route metrics and performance"},"bootstrap":{"type":"object","description":"Bootstrap data for initializing load balancer with historical metrics","properties":{"route_metrics":{"type":"object","description":"Historical metrics per route"},"direction_metrics":{"type":"object","description":"Historical metrics per direction"},"routes":{"type":"object","description":"Known routes"}}}},"required":["enabled"],"additionalProperties":false},"guardrails_config":{"type":"object","description":"Guardrails configuration for content moderation and policy enforcement","properties":{"guardrail_rules":{"type":"array","description":"List of guardrail rules","items":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the rule"},"name":{"type":"string","description":"Name of the guardrail rule"},"description":{"type":"string","description":"Description of what the rule does"},"enabled":{"type":"boolean","description":"Whether this rule is enabled"},"cel_expression":{"type":"string","description":"CEL (Common Expression Language) expression for rule evaluation"},"query":{"description":"Visual rule builder state for the management UI (react-querybuilder). Omitted unless exported from the dashboard. Not evaluated at runtime (cel_expression is).","anyOf":[{"type":"null"},{"type":"object","required":["combinator","rules"],"properties":{"combinator":{"type":"string","enum":["and","or"]},"rules":{"type":"array","items":{"type":"object"},"description":"Leaf rules and/or nested combinator+rules groups from the query builder."}},"additionalProperties":true}]},"apply_to":{"type":"string","enum":["input","output","both"],"description":"When to apply the guardrail (input, output, or both)"},"sampling_rate":{"type":"integer","minimum":0,"maximum":100,"description":"Percentage of requests to apply this rule to (0-100)"},"timeout":{"type":"integer","minimum":0,"description":"Timeout in seconds for rule execution"},"max_turns_to_send":{"type":"integer","minimum":0,"description":"Number of historical conversation turns to send to the guardrail provider; the latest message is always included on top. 0 sends all turns."},"evaluation_mode":{"type":"string","enum":["bundled","per_turn"],"default":"bundled","description":"How the rule's turns are sent to its guardrail providers. 'bundled' (default) concatenates all turns into one guardrail call. 'per_turn' sends each turn in its own call, evaluated in isolation, to avoid context-sensitive classifiers (e.g. Bedrock prompt-attack) combining unrelated turns into a false-positive block; this scans every turn but uses more provider calls."},"provider_config_ids":{"type":"array","items":{"type":"integer"},"description":"IDs of provider configurations to use with this rule"}},"required":["id","name","enabled","cel_expression","apply_to"],"additionalProperties":false}},"guardrail_providers":{"type":"array","description":"List of guardrail provider configurations","items":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the provider config"},"provider_name":{"type":"string","description":"Name of the guardrail provider (e.g., 'bedrock', 'azure')"},"policy_name":{"type":"string","description":"Name of the specific policy to use"},"enabled":{"type":"boolean","description":"Whether this provider config is enabled"},"timeout":{"type":"integer","minimum":0,"description":"Timeout in seconds for provider execution"},"config":{"type":"object","description":"Provider-specific configuration"}},"required":["id","provider_name","policy_name","enabled"],"additionalProperties":false}}},"additionalProperties":false},"access_profiles":{"type":"array","description":"Enterprise access profile templates for RBAC-driven governance controls","items":{"$ref":"#/$defs/access_profile"}},"budget_line":{"type":"object","properties":{"id":{"type":"string","description":"Budget ID"},"max_limit":{"type":"number","description":"Maximum spend limit in USD"},"reset_duration":{"type":"string","description":"Reset window, e.g. \"1M\", \"1h\""},"calendar_aligned":{"type":"boolean","description":"Deprecated: set calendar_aligned on the parent access profile instead. Kept for backward compatibility with older config.json files; the access-profile reconciler promotes any true value here to the profile's top-level calendar_aligned at load time.","default":false}},"required":["id","max_limit","reset_duration"],"additionalProperties":false},"rate_limit_line":{"type":"object","properties":{"id":{"type":"string","description":"Rate limit ID"},"token_max_limit":{"type":"integer","description":"Maximum number of tokens allowed in the reset window"},"token_reset_duration":{"type":"string","description":"Token reset window, e.g. \"1M\", \"1h\""},"request_max_limit":{"type":"integer","description":"Maximum number of requests allowed in the reset window"},"request_reset_duration":{"type":"string","description":"Request reset window, e.g. \"1M\", \"1h\""},"calendar_aligned":{"type":"boolean","description":"Deprecated: set calendar_aligned on the parent access profile instead. Kept for backward compatibility with older config.json files; the access-profile reconciler promotes any true value here to the profile's top-level calendar_aligned at load time.","default":false}},"required":["id"],"additionalProperties":false},"access_profile":{"type":"object","properties":{"name":{"type":"string","description":"Unique access profile name"},"description":{"type":"string","description":"Optional profile description"},"is_active":{"type":"boolean","description":"Whether this access profile is active","default":true},"tags":{"type":"array","items":{"type":"string"},"description":"Optional list of tags for filtering and grouping profiles"},"budgets":{"type":"array","items":{"$ref":"#/$defs/budget_line"},"description":"Profile-level budgets"},"rate_limit":{"$ref":"#/$defs/rate_limit_line"},"calendar_aligned":{"type":"boolean","description":"Snap budget and rate-limit reset windows to clean calendar boundaries (day, week, month, year) for this profile","default":false},"provider_configs":{"type":"array","description":"Per-provider restrictions and limits for this profile","items":{"$ref":"#/$defs/access_profile_provider_config"}},"mcp_tool_groups":{"type":"array","description":"MCP tool group associations","items":{"$ref":"#/$defs/access_profile_mcp_tool_group"}},"mcp_servers":{"type":"array","description":"MCP server associations","items":{"$ref":"#/$defs/access_profile_mcp_server"}},"mcp_tool_overrides":{"type":"array","description":"Per-tool include/exclude MCP overrides","items":{"$ref":"#/$defs/access_profile_mcp_tool_override"}}},"required":["name"],"additionalProperties":false},"access_profile_provider_config":{"type":"object","properties":{"provider_name":{"type":"string","description":"Provider name"},"all_models_allowed":{"type":"boolean","description":"Whether all models under this provider are allowed","default":false},"allowed_models":{"type":"array","items":{"type":"string"},"description":"Allowed model names (ignored when all_models_allowed is true)"},"budgets":{"type":"array","items":{"$ref":"#/$defs/budget_line"}},"rate_limit":{"$ref":"#/$defs/rate_limit_line"},"key_ids":{"type":"array","description":"Key IDs allowed for this provider config. Use [\"*\"] to allow all keys; empty array or omitted denies all keys. Specific IDs restrict access to those keys only.","items":{"type":"string"}}},"required":["provider_name"],"additionalProperties":false},"access_profile_mcp_tool_group":{"type":"object","properties":{"tool_group_id":{"type":"integer","minimum":1,"description":"MCP tool group ID"}},"required":["tool_group_id"],"additionalProperties":false},"access_profile_mcp_server":{"type":"object","properties":{"mcp_server_id":{"type":"string","description":"MCP server identifier"}},"required":["mcp_server_id"],"additionalProperties":false},"access_profile_mcp_tool_override":{"type":"object","properties":{"mcp_client_id":{"type":"string","description":"MCP client identifier"},"tool_name":{"type":"string","description":"Tool name"},"action":{"type":"string","enum":["include","exclude"],"description":"Override action"}},"required":["mcp_client_id","tool_name","action"],"additionalProperties":false},"audit_logs_config":{"type":"object","description":"Audit logs configuration for CADF-compliant activity logging","properties":{"disabled":{"type":"boolean","description":"Whether audit logging is disabled (default: false)","default":false},"hmac_key":{"type":"string","description":"HMAC secret key for signing audit events (minimum 32 bytes). Can use env. prefix for environment variables (e.g., 'env.AUDIT_HMAC_KEY')."},"retention_days":{"type":"integer","minimum":0,"description":"Number of days to retain audit logs (0 means no retention limit)"},"object_storage":{"type":"object","description":"Optional object storage for archiving audit events to S3/GCS. When configured, each flushed batch of audit events is written as a gzipped JSONL object at {prefix}/audit-logs/YYYY/MM/DD/HH/{id}.jsonl[.gz], in addition to the database (which remains the source of truth). Archival is going-forward only; existing rows are not backfilled.","properties":{"type":{"type":"string","enum":["s3","gcs"],"description":"Object storage backend type"},"bucket":{"anyOf":[{"type":"string","minLength":1},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"Bucket name. Supports env var reference (e.g. env.S3_BUCKET) or a structured secret reference."},"prefix":{"type":"string","description":"Configurable base key path for stored audit objects; the 'audit-logs/' segment is appended under it (default: bifrost)","default":"bifrost"},"compress":{"type":"boolean","description":"Enable gzip compression for stored objects. Default: false","default":false}},"required":["type","bucket"],"if":{"properties":{"type":{"const":"s3"}}},"then":{"properties":{"type":true,"bucket":true,"prefix":true,"region":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS region. Supports env var reference"},"endpoint":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"Custom S3-compatible endpoint for MinIO/R2. Supports env var reference"},"access_key_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS access key ID. Omit to use default credential chain (instance role, env vars, etc.). Supports env var reference"},"secret_access_key":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS secret access key. Supports env var reference"},"session_token":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS session token for STS temporary credentials. Supports env var reference"},"role_arn":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"AWS IAM role ARN for STS AssumeRole. Works with static creds or instance role. Supports env var reference"},"force_path_style":{"type":"boolean","description":"Use path-style URLs for S3 (required for MinIO). Default: false","default":false},"compress":true},"dependentRequired":{"access_key_id":["secret_access_key"],"secret_access_key":["access_key_id"],"session_token":["access_key_id","secret_access_key"]},"additionalProperties":false},"else":{"properties":{"type":true,"bucket":true,"prefix":true,"credentials_json":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"GCP service account credentials JSON or file path. Omit to use Application Default Credentials. Supports env var reference"},"credentials":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"Deprecated: use credentials_json. Kept for backwards compatibility."},"project_id":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"ref":{"type":"string"},"type":{"type":"string","enum":["plain_text","env","vault"]},"env_var":{"type":"string"},"from_env":{"type":"boolean"}},"required":["value"],"additionalProperties":false}],"description":"GCP project ID override. Supports env var reference"},"compress":true},"additionalProperties":false}}},"additionalProperties":false},"large_payload_optimization":{"type":"object","description":"Large payload streaming optimization configuration. Detects large request/response payloads and streams them through without full materialization.","properties":{"enabled":{"type":"boolean","description":"Master toggle for large payload optimization (default: false)","default":false},"request_threshold_bytes":{"type":"integer","minimum":0,"description":"Request body size in bytes above which streaming kicks in (default: 10MB)","default":10485760},"response_threshold_bytes":{"type":"integer","minimum":0,"description":"Response body size in bytes above which streaming kicks in (default: 10MB)","default":10485760},"prefetch_size_bytes":{"type":"integer","minimum":0,"description":"How much of the request to prefetch for metadata extraction in bytes (default: 64KB)","default":65536},"max_payload_bytes":{"type":"integer","minimum":0,"description":"Maximum allowed payload size in bytes; reject above this (default: 500MB)","default":524288000},"truncated_log_bytes":{"type":"integer","minimum":0,"description":"How many bytes to store as truncated preview in logs (default: 1MB)","default":1048576}},"additionalProperties":false},"websocket_config":{"type":"object","description":"Optional tuning for the WebSocket gateway (Responses API WebSocket Mode, Realtime API). WebSocket is always enabled; these fields override the high defaults.","properties":{"max_connections_per_user":{"type":"integer","minimum":1,"description":"Maximum concurrent WebSocket connections per user","default":100},"transcript_buffer_size":{"type":"integer","minimum":1,"description":"Number of transcript entries to buffer for Realtime API mid-session fallback","default":100},"pool":{"type":"object","description":"Upstream WebSocket connection pool configuration","properties":{"max_idle_per_key":{"type":"integer","minimum":1,"description":"Maximum idle connections per provider/key combination","default":50},"max_total_connections":{"type":"integer","minimum":1,"description":"Maximum total idle connections across all providers","default":1000},"idle_timeout_seconds":{"type":"integer","minimum":1,"description":"Seconds before an idle connection is evicted","default":600},"max_connection_lifetime_seconds":{"type":"integer","minimum":1,"description":"Maximum lifetime of a connection in seconds","default":7200}},"additionalProperties":false}},"additionalProperties":false},"provider_pricing_override":{"type":"object","description":"Scoped pricing override applied at runtime by the model catalog","properties":{"id":{"type":"string","description":"Unique pricing override ID"},"name":{"type":"string","description":"Human-readable name for this override"},"scope_kind":{"type":"string","description":"Scope level for this override","enum":["global","provider","provider_key","virtual_key","virtual_key_provider","virtual_key_provider_key"]},"virtual_key_id":{"type":"string","description":"Virtual key ID (required for virtual_key* scopes)"},"provider_id":{"type":"string","description":"Provider name (required for provider* scopes; field key remains provider_id for compatibility)"},"provider_key_name":{"type":"string","description":"Provider key name alias. Resolved to internal provider key ID at config load time."},"match_type":{"type":"string","description":"How the pattern is matched against model names","enum":["exact","wildcard"]},"pattern":{"type":"string","description":"Model name pattern to match (exact name or wildcard prefix ending with *)"},"request_types":{"type":"array","description":"Request types this override applies to. At least one value is required.","minItems":1,"items":{"type":"string"}},"pricing_patch":{"type":"string","description":"JSON-encoded pricing fields to override (e.g. '{\"input_cost_per_token\":0.000001}')"},"config_hash":{"type":"string","description":"Internal hash for change detection (auto-managed)"}},"required":["id","name","scope_kind","match_type","pattern","request_types"],"additionalProperties":false},"pricing_override_match_type":{"type":"string","enum":["exact","wildcard"]},"pricing_override_request_type":{"type":"string","enum":["chat_completion","text_completion","responses","embedding","rerank","speech","transcription","image_generation","image_variation","image_edit","video_generation","video_remix","compaction"]},"custom_provider_config":{"type":"object","description":"Custom provider configuration for extending or customizing provider behavior","properties":{"is_key_less":{"type":"boolean","description":"Whether the custom provider requires a key"},"base_provider_type":{"type":"string","enum":["openai","azure","anthropic","bedrock","bedrock_mantle","cohere","vertex","mistral","ollama","groq","opencode-go","opencode-zen","sgl","parasail","perplexity","cerebras","deepseek","gemini","openrouter","elevenlabs","huggingface","nebius","xai","replicate","vllm","runway","runware","fireworks","sarvam"],"description":"Base provider type to extend"},"request_path_overrides":{"type":"object","description":"Mapping of request type to custom path overriding the default provider path","additionalProperties":{"type":"string"}},"allowed_requests":{"type":"object","description":"Allowed request types for the custom provider","properties":{"list_models":{"type":"boolean"},"text_completion":{"type":"boolean"},"text_completion_stream":{"type":"boolean"},"chat_completion":{"type":"boolean"},"chat_completion_stream":{"type":"boolean"},"responses":{"type":"boolean"},"responses_stream":{"type":"boolean"},"responses_retrieve":{"type":"boolean","description":"GET stored response by id (OpenAI Responses lifecycle)"},"responses_delete":{"type":"boolean","description":"DELETE stored response (OpenAI Responses lifecycle)"},"responses_cancel":{"type":"boolean","description":"POST cancel in-flight stored response (OpenAI Responses lifecycle)"},"responses_input_items":{"type":"boolean","description":"GET list input items for a stored response (OpenAI Responses lifecycle)"},"count_tokens":{"type":"boolean"},"compaction":{"type":"boolean"},"embedding":{"type":"boolean"},"rerank":{"type":"boolean"},"ocr":{"type":"boolean"},"speech":{"type":"boolean"},"speech_stream":{"type":"boolean"},"transcription":{"type":"boolean"},"transcription_stream":{"type":"boolean"},"image_generation":{"type":"boolean"},"image_generation_stream":{"type":"boolean"},"image_edit":{"type":"boolean"},"image_edit_stream":{"type":"boolean"},"image_variation":{"type":"boolean"},"video_generation":{"type":"boolean"},"video_retrieve":{"type":"boolean"},"video_download":{"type":"boolean"},"video_delete":{"type":"boolean"},"video_list":{"type":"boolean"},"video_remix":{"type":"boolean"},"batch_create":{"type":"boolean"},"batch_list":{"type":"boolean"},"batch_retrieve":{"type":"boolean"},"batch_cancel":{"type":"boolean"},"batch_delete":{"type":"boolean"},"batch_results":{"type":"boolean"},"file_upload":{"type":"boolean"},"file_list":{"type":"boolean"},"file_retrieve":{"type":"boolean"},"file_delete":{"type":"boolean"},"file_content":{"type":"boolean"},"container_create":{"type":"boolean"},"container_list":{"type":"boolean"},"container_retrieve":{"type":"boolean"},"container_delete":{"type":"boolean"},"container_file_create":{"type":"boolean"},"container_file_list":{"type":"boolean"},"container_file_retrieve":{"type":"boolean"},"container_file_content":{"type":"boolean"},"container_file_delete":{"type":"boolean"},"passthrough":{"type":"boolean"},"passthrough_stream":{"type":"boolean"},"websocket_responses":{"type":"boolean"},"realtime":{"type":"boolean"},"cached_content_create":{"type":"boolean"},"cached_content_list":{"type":"boolean"},"cached_content_retrieve":{"type":"boolean"},"cached_content_update":{"type":"boolean"},"cached_content_delete":{"type":"boolean"}},"additionalProperties":false}},"required":["base_provider_type"],"additionalProperties":false},"circuit_breaker_config":{"type":"object","description":"Circuit breaker configuration for automatic failover when a provider endpoint degrades","properties":{"policies":{"type":"array","description":"List of circuit breaker policies","items":{"type":"object","description":"A single circuit breaker policy that monitors a primary provider+model and redirects to a fallback when the circuit opens","properties":{"name":{"type":"string","description":"Unique name for this policy"},"enabled":{"type":"boolean","description":"Whether this policy is active. Disabled policies are ignored by all hooks."},"primary_provider":{"type":"string","description":"Provider to monitor (e.g. 'azure', 'openai')"},"primary_model":{"type":"string","description":"Model to monitor as it appears in requests (e.g. 'gpt-4-ptu')"},"primary_key_ids":{"type":"array","description":"Optional list of key UUIDs to monitor individually. Each key gets its own sub-circuit; the main circuit opens only when all listed keys are exhausted. Leave empty to use a single shared circuit for all keys serving this provider+model.","items":{"type":"string"}},"fallback_provider":{"type":"string","description":"Provider to route to when the circuit is open"},"fallback_model":{"type":"string","description":"Model to request from the fallback provider when the circuit is open"},"condition":{"type":"object","description":"Response signals that trigger the circuit to open","properties":{"operator":{"type":"string","enum":["OR","AND"],"default":"OR","description":"OR (default): circuit opens when any signal matches. AND: circuit opens only when all signals match simultaneously."},"signals":{"type":"array","description":"List of response signals to evaluate","items":{"type":"object","properties":{"source":{"type":"string","enum":["response_header"],"description":"What part of the HTTP response to inspect"},"header_name":{"type":"string","description":"HTTP response header name to inspect"},"header_value":{"type":"string","description":"Trips when the header equals this value (case-insensitive). Mutually exclusive with header_contains."},"header_contains":{"type":"string","description":"Trips when the header value contains this substring (case-insensitive). Mutually exclusive with header_value. If neither is set, trips when the header is present."}},"required":["source","header_name"],"not":{"required":["header_value","header_contains"]},"additionalProperties":false},"minItems":1}},"required":["signals"],"additionalProperties":false},"default_cooldown":{"type":"string","pattern":"^[0-9]+(ns|us|µs|ms|s|m|h)$","description":"How long to keep the circuit open when no header-based cooldown is available. Accepts a Go duration string (e.g. '30s', '5m'). Defaults to 30s."},"cooldown_header":{"type":"string","description":"Response header whose value (in milliseconds) overrides default_cooldown (e.g. 'retry-after-ms'). Falls back to default_cooldown when absent or unparsable."}},"required":["name","primary_provider","primary_model","fallback_provider","fallback_model","condition"],"additionalProperties":false}}},"additionalProperties":false},"scim_attribute_role_mappings":{"type":"array","description":"Ordered list of attribute -> role mappings (first match wins).","items":{"type":"object","properties":{"attribute":{"type":"string","description":"JWT claim name (supports dot paths, e.g. 'realm_access.roles')"},"value":{"type":"string","description":"Claim value to match (case-insensitive)"},"role":{"type":"string","description":"Bifrost role to assign on match"}},"required":["attribute","value","role"],"additionalProperties":false}},"scim_attribute_team_mappings":{"type":"array","description":"Attribute -> team mappings (all matches apply). Use value '*' for pass-through.","items":{"type":"object","properties":{"attribute":{"type":"string","description":"JWT claim name"},"value":{"type":"string","description":"Claim value to match, or '*' for pass-through"},"team":{"type":"string","description":"Bifrost team slug to assign. In case of '*' value, leave this empty"}},"required":["attribute","value"],"additionalProperties":false}},"scim_attribute_business_unit_mappings":{"type":"array","description":"Attribute -> business-unit mappings (all matches apply).","items":{"type":"object","properties":{"attribute":{"type":"string","description":"JWT claim name"},"value":{"type":"string","description":"Claim value to match. Wildcard '*' will use the claim as the name of the business unit to assign."},"business_unit":{"type":"string","description":"Bifrost business unit slug to assign. In case of '*' value, leave this empty"}},"required":["attribute","value"],"additionalProperties":false}}}}