Skip to main content
The governance block lets you seed all governance resources directly in config.json. On startup, Bifrost loads these into the configuration store. This is the recommended approach for GitOps workflows where governance state is managed as code.
Governance enforcement is always active in OSS — you do not need a plugin entry to enable it. To require a virtual key on every inference request, set client.enforce_auth_on_inference: true. This is the global default, but a more specific inference-auth flag such as governance.auth_config.disable_auth_on_inference overrides it; if no specific override is set, client.enforce_auth_on_inference applies.

Admin Authentication

Protect the Bifrost dashboard and management API with username/password auth:
{
  "governance": {
    "auth_config": {
      "is_enabled": true,
      "admin_username": "env.BIFROST_ADMIN_USERNAME",
      "admin_password": "env.BIFROST_ADMIN_PASSWORD",
      "disable_auth_on_inference": false
    }
  }
}
FieldDefaultDescription
is_enabledfalseEnable admin username/password auth
admin_usernameAdmin username (supports env. prefix)
admin_passwordAdmin password (supports env. prefix)
disable_auth_on_inferencefalseSkip auth check on /v1/* inference routes

Virtual Keys

Virtual keys are issued to clients and act as scoped API tokens. Each key specifies which providers, models, and API keys the bearer is allowed to use.
{
  "governance": {
    "virtual_keys": [
      {
        "id": "vk-team-platform",
        "name": "platform-team",
        "value": "env.VK_PLATFORM_TEAM",
        "is_active": true,
        "provider_configs": [
          {
            "provider": "openai",
            "allowed_models": ["gpt-4o", "gpt-4o-mini"],
            "key_ids": ["*"],
            "weight": 1
          },
          {
            "provider": "anthropic",
            "allowed_models": ["*"],
            "key_ids": ["*"],
            "weight": 1
          }
        ]
      }
    ]
  }
}

Virtual Key Fields

FieldRequiredDescription
idYesUnique virtual key ID (referenced by budgets / rate limits)
nameYesHuman-readable name
valueNoThe key token sent by clients (use env. prefix). Auto-generated if omitted
is_activeNoDefault true. Set false to disable without deleting
team_idNoAssociate with a team (mutually exclusive with customer_id)
customer_idNoAssociate with a customer
rate_limit_idNoAttach a rate limit
calendar_alignedNoSnap budget resets to day/week/month/year boundaries
provider_configsNoAllowed provider/model/key combinations (empty = deny all)

Provider Config Fields

FieldRequiredDescription
providerYesProvider name (e.g. "openai")
allowed_modelsNoModel allow-list. ["*"] = all models; [] = deny all
key_idsNoProvider key names allowed for this VK. ["*"] = all keys; [] = deny all. Use key name values (not UUIDs) in config.json
weightNoLoad-balancing weight when multiple provider configs are present
rate_limit_idNoAttach a per-provider-config rate limit

Budgets

Budgets cap cumulative spend (in USD) for a virtual key or provider config over a rolling window:
{
  "governance": {
    "budgets": [
      {
        "id": "budget-platform-monthly",
        "max_limit": 500.00,
        "reset_duration": "1M",
        "virtual_key_id": "vk-team-platform"
      }
    ]
  }
}
FieldRequiredDescription
idYesUnique budget ID
max_limitYesMaximum spend in USD
reset_durationYesWindow length: "30s", "5m", "1h", "1d", "1w", "1M", "1Y"
virtual_key_idNoAttach to a virtual key (mutually exclusive with provider_config_id)
provider_config_idNoAttach to a provider config ID

Rate Limits

Rate limits cap requests or tokens over a rolling window:
{
  "governance": {
    "rate_limits": [
      {
        "id": "rl-platform-hourly",
        "request_max_limit": 1000,
        "request_reset_duration": "1h",
        "token_max_limit": 1000000,
        "token_reset_duration": "1h"
      }
    ]
  }
}
FieldRequiredDescription
idYesUnique rate limit ID
request_max_limitNoMaximum requests in window
request_reset_durationNoWindow for request counter
token_max_limitNoMaximum tokens (input + output) in window
token_reset_durationNoWindow for token counter
Attach a rate limit to a virtual key via virtual_keys[].rate_limit_id, or to a provider config via virtual_keys[].provider_configs[].rate_limit_id.

Routing Rules

Routing rules dynamically select the provider and model for each request based on a CEL expression. They are evaluated in priority order before the request is dispatched.
{
  "governance": {
    "routing_rules": [
      {
        "id": "route-gpt4-to-azure",
        "name": "Redirect GPT-4o to Azure",
        "cel_expression": "request.model == 'gpt-4o'",
        "targets": [
          { "provider": "azure", "model": "gpt-4o", "weight": 1.0 }
        ]
      },
      {
        "id": "route-cost-split",
        "name": "Split traffic 70/30 between providers",
        "cel_expression": "true",
        "targets": [
          { "provider": "openai",    "weight": 0.7 },
          { "provider": "anthropic", "weight": 0.3 }
        ]
      }
    ]
  }
}

Rule Fields

FieldRequiredDescription
idYesUnique rule ID
nameYesHuman-readable name
cel_expressionNoCEL expression. "true" matches every request
targetsYesWeighted target list (weights must sum to 1.0)
enabledNoDefault true
priorityNoEvaluation order within scope — lower numbers run first
scopeNo"global" (default), "team", "customer", "virtual_key"
scope_idConditionalRequired when scope is not "global"
chain_ruleNoIf true, re-evaluates the chain after this rule matches
fallbacksNoOrdered fallback provider list if primary target fails

Target Fields

FieldRequiredDescription
weightYesFraction of traffic (all weights in a rule must sum to 1.0)
providerNoTarget provider. Omit to keep the incoming request’s provider
modelNoTarget model. Omit to keep the incoming request’s model
key_idNoPin a specific API key by name

Customers & Teams

Define organizational entities and attach budgets or rate limits to them:
{
  "governance": {
    "customers": [
      {
        "id": "customer-acme",
        "name": "Acme Corp",
        "budget_id": "budget-acme-monthly",
        "rate_limit_id": "rl-acme-hourly"
      }
    ],
    "teams": [
      {
        "id": "team-ml",
        "name": "ML Team",
        "customer_id": "customer-acme",
        "budget_id": "budget-team-ml"
      }
    ]
  }
}

Full Governance Example

{
  "$schema": "https://www.getbifrost.ai/schema",
  "encryption_key": "env.BIFROST_ENCRYPTION_KEY",

  "client": {
    "enforce_auth_on_inference": true
  },

  "governance": {
    "auth_config": {
      "is_enabled": true,
      "admin_username": "env.BIFROST_ADMIN_USERNAME",
      "admin_password": "env.BIFROST_ADMIN_PASSWORD"
    },

    "budgets": [
      {
        "id": "budget-platform",
        "max_limit": 1000.00,
        "reset_duration": "1M",
        "virtual_key_id": "vk-platform"
      }
    ],

    "rate_limits": [
      {
        "id": "rl-platform",
        "request_max_limit": 5000,
        "request_reset_duration": "1h",
        "token_max_limit": 5000000,
        "token_reset_duration": "1h"
      }
    ],

    "virtual_keys": [
      {
        "id": "vk-platform",
        "name": "platform-key",
        "value": "env.VK_PLATFORM",
        "is_active": true,
        "rate_limit_id": "rl-platform",
        "provider_configs": [
          {
            "provider": "openai",
            "allowed_models": ["*"],
            "key_ids": ["*"],
            "weight": 1
          }
        ]
      }
    ],

    "routing_rules": [
      {
        "id": "fallback-to-anthropic",
        "name": "Fallback on error",
        "cel_expression": "true",
        "targets": [{ "provider": "openai", "weight": 1.0 }],
        "fallbacks": ["anthropic"]
      }
    ]
  },

  "providers": {
    "openai": {
      "keys": [{ "name": "openai-primary", "value": "env.OPENAI_API_KEY", "models": ["*"], "weight": 1.0 }]
    },
    "anthropic": {
      "keys": [{ "name": "anthropic-primary", "value": "env.ANTHROPIC_API_KEY", "models": ["*"], "weight": 1.0 }]
    }
  },

  "config_store": {
    "enabled": true,
    "type": "postgres",
    "config": {
      "host": "env.PG_HOST",
      "port": "5432",
      "user": "env.PG_USER",
      "password": "env.PG_PASSWORD",
      "db_name": "bifrost"
    }
  }
}