Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.
Creating a relay gives it an address. Grants decide which callers may use it. Access is deny-by-default: a virtual key reaches a relay only through an explicit grant for that relay, exactly like its agent and MCP grants.Relay access is separate from provider access, MCP tool access and agent access. A key that may call tavily gains nothing on /v1/chat/completions and the other way round.
Relays this key may call, one { "relay_name": "..." } each. When the key syncs from the file this is its whole list: omitted or [] leaves it with none. In split mode an unchanged entry is not synced, so grants made in the dashboard stay until the entry is next edited. Not applied when an access profile governs the key’s team, customer or user (Enterprise): that profile’s relay_grants decide the key’s relays.
Relays declared in config.json are loaded before governance, so a virtual key in the same file may grant them. A name that matches no relay is skipped with a warning. The key is reconciled again only when its entry changes (or on every start with config.json as the source of truth), so after fixing the relay, the grant is applied the next time the key’s entry is synced.Like the rest of the key, relay_grants is synced from the file when the key’s entry changes, and on every start when config.json is the source of truth. The declared list is then the key’s whole list, and omitting it leaves the key with no grants, so grants made in the dashboard are replaced. In split mode an unchanged entry is not synced, so dashboard grants on it stay until the entry is next edited.
bifrost: governance: virtualKeys: - id: vk-research name: research-assistant value: "env.RESEARCH_VK" relay_grants: - relay_name: tavily - relay_name: textract# The pod reads RESEARCH_VK from its environment; envFrom loads it from a Kubernetes SecretenvFrom: - secretRef: name: research-virtual-key # a Secret with the key RESEARCH_VK; the value must start with sk-bf-
RESEARCH_VK must hold a strong random value that starts with sk-bf- (for example sk-bf-$(openssl rand -hex 24)); a value without that prefix is replaced by a generated key and requests sending the Secret’s value are refused.Projects (bifrost.governance.projects[].relay_grants) and access profiles (bifrost.accessProfiles[].relay_grants) take the same list, with the same sync behaviour as config.json. One difference: a virtual key skips only the grant that names an unknown relay, while a project or access profile naming one is skipped as a whole, with a warning.A key whose team, customer or user is governed by an access profile (Enterprise) takes its relays from that profile, so its own relay_grants are not applied. Grant the relay on the access profile instead.
Send the key on every relay request:
curl -X POST "http://localhost:8080/relay/tavily/search" \ -H "Content-Type: application/json" \ -H "x-bf-vk: sk-bf-your-virtual-key" \ -d '{"query": "Bifrost AI gateway"}'
Any header that carries a virtual key on the inference endpoints (x-bf-vk, Authorization: Bearer sk-bf-..., x-api-key, …) carries it here too. Whatever the caller sends in those headers is consumed by Bifrost and never forwarded; the relay signs in with its own credential.A key without a grant is refused before any upstream effect:
{ "is_bifrost_error": true, "status_code": 403, "type": "relay_blocked", "error": { "message": "Relay 'tavily' is not allowed for virtual key 'research-assistant'" }}
The relay path uses the same authentication middleware as inference. With client.enforce_auth_on_inference on, a request must present a credential the deployment accepts (a virtual key, an API key or a user token) or it is refused; grants then restrict what the identified caller may reach. The setting defaults to on for new deployments, while an existing deployment keeps its stored value when the key is omitted, so check it: with enforcement off, a request carrying no credential is relayed without any grant check.
A relay call is governed the way an MCP tool execution is: the caller’s identity is resolved, then every budget and rate limit the caller’s holders carry is checked, before the upstream is contacted.
Applies
Does not apply
Virtual key, team, customer budgets (and business unit and project budgets in Enterprise)
Provider configs and allowed providers
Request rate limits on the key
Model budgets and model rate limits
Key status and expiry
Routing rules and fallbacks
Required headers (client.required_headers)
Token rate limits (a relay has no tokens to count)
Model restrictions: a relay names no model to govern, even when the mapping reads a model_path for the logs
After the call, every reply the relay forwarded counts one request against the request rate limits, whether or not the route is billable, exactly as every MCP tool execution does: a limit on calls bounds calls. Only a counted call (billable route, 2xx reply) carries a cost, which is charged to the budgets. A call that never got a reply (the upstream could not be reached) counts nothing. A stream the caller abandoned still reports what was forwarded, so hanging up does not avoid the charge.The budget and rate-limit ids a call was charged against are recorded on its Relay Logs row.
On Bifrost Enterprise, relay_grants are also available on access profiles and projects, as grant rows only, like their agent grants. A request is allowed when its permits allow it under the same composition rules as agents and MCP tools; a refusal names the profile or project that denied it, for example Relay 'tavily' is not allowed for access profile 'contractors'.The Relays page itself is gated on the RelaysRBAC resource: a user with Relays:View can view relays, and one with Relays:Create, Update or Delete can manage them. Relay Logs are read under the separate RelayLogs resource, which has its own data access control scope. On upgrade, the default roles receive their Relays and RelayLogs permissions as for the Agent Gateway resources; a custom role gets nothing until an admin grants it.
Relay Logs — See which key, team and customer each call was attributed to.
Was this page helpful?
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/schema.json","name":"Bifrost","colors":{"primary":"#0C3B43","light":"#07C983"},"logo":{"light":"https://mintcdn.com/bifrost/qFMmk8bNSnvgFYDI/media/bifrost-logo.png?fit=max\u0026auto=format\u0026n=qFMmk8bNSnvgFYDI\u0026q=85\u0026s=6af701a560aee4103444fa017b226cf0","dark":"https://mintcdn.com/bifrost/qFMmk8bNSnvgFYDI/media/bifrost-logo-dark.png?fit=max\u0026auto=format\u0026n=qFMmk8bNSnvgFYDI\u0026q=85\u0026s=84d264aad5f421c526dd17893e7c5739"},"favicon":"https://mintcdn.com/bifrost/qFMmk8bNSnvgFYDI/favicon.ico?fit=max\u0026auto=format\u0026n=qFMmk8bNSnvgFYDI\u0026q=85\u0026s=a57bad8c37d798efcb53dca5d96d8b45","navbar":{"links":[{"href":"https://www.getmaxim.ai/enterprise?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Navbar#free-license","label":"Request License"}],"primary":{"type":"button","label":"Book a Demo","href":"https://www.getmaxim.ai/book-a-demo?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Navbar"}},"footer":{"socials":{"x":"https://x.com/getbifrost","linkedin":"https://linkedin.com/company/maxim-ai","github":"https://github.com/maximhq/bifrost"},"links":[{"header":"Company","items":[{"label":"Book a Demo","href":"https://www.getmaxim.ai/book-a-demo?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Partner Program","href":"https://www.getmaxim.ai/partners-program?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Careers","href":"https://www.getmaxim.ai/careers?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Contact Us","href":"mailto:[email protected]"},{"label":"Security","href":"https://docs.getbifrost.ai/security"},{"label":"Trust Center","href":"https://trust.getmaxim.ai/"},{"label":"Terms of Service","href":"https://www.getmaxim.ai/terms-of-service?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Privacy Policy","href":"https://www.getmaxim.ai/privacy-policy?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"}]},{"header":"Products","items":[{"label":"LLM Gateway","href":"https://www.getmaxim.ai/llm-gateway?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"MCP Gateway","href":"https://www.getmaxim.ai/mcp-gateway?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Governance","href":"https://www.getmaxim.ai/ai-governance?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Guardrails","href":"https://www.getmaxim.ai/ai-guardrails?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Observability","href":"https://www.getmaxim.ai/ai-observability?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Bifrost Edge","href":"https://www.getmaxim.ai/edge?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"}]},{"header":"Resources","items":[{"label":"Bifrost Enterprise","href":"https://www.getmaxim.ai/enterprise?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Performance Benchmarks","href":"https://www.getmaxim.ai/bifrost/resources/benchmarks?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"LLM Gateway Buyer's Guide","href":"https://www.getmaxim.ai/bifrost/resources/buyers-guide?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Claude Code Integration","href":"https://www.getmaxim.ai/bifrost/resources/claude-code?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Migrating from LiteLLM","href":"https://www.getmaxim.ai/bifrost/resources/migrating-from-litellm?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"},{"label":"Blogs","href":"https://www.getmaxim.ai/bifrost/blog?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"}]},{"header":"For LLMs","items":[{"label":"llms-full.txt","href":"https://docs.getbifrost.ai/llms-full.txt"},{"label":"llms.txt","href":"https://docs.getbifrost.ai/llms.txt"},{"label":"llm-info","href":"https://www.getmaxim.ai/llm-info?utm_source=bifrost_docs\u0026utm_medium=Bifrost_Footer"}]}]},"styling":{"latex":true},"navigation":{"global":{"anchors":[{"anchor":"Discord","icon":"discord","href":"https://discord.gg/exN5KAydbU"},{"anchor":"GitHub","icon":"github","href":"https://github.com/maximhq/bifrost"},{"anchor":"Try Enterprise","icon":"building","href":"https://www.getmaxim.ai/bifrost/enterprise"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"bifrost","hasAudioNarration":false,"actualSubdomain":"bifrost","customDomains":["docs.getbifrost.ai"],"gitSource":{"type":"github","owner":"maximhq","repo":"bifrost","deployBranch":"main","contentDirectory":"docs","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae34223c5540a38c0905011","collectionId":"0344de93-1cb8-4f37-816d-49cb8da030e3","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae34223c5540a38c0905011"},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6ae348a6217e82a3b924da4f","clientVersion":"0.0.4006","searchFilterCounts":[{"language":"default","tag":"API","count":690},{"language":"default","tag":"Changelogs","count":314},{"language":"default","tag":"Integrations","count":248},{"language":"default","tag":"Platform","count":237},{"language":"default","tag":"Open Source","count":163},{"language":"default","tag":"OSS","count":152},{"language":"default","tag":"Governance","count":132},{"language":"default","tag":"Enterprise","count":101},{"language":"default","tag":"Helm","count":75},{"language":"default","tag":"Inference","count":71}]},"assistantConfig":{},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":".nav-logo{height:1.5rem}div:has(>nav[aria-label=Main]){gap:1.5rem}nav[aria-label=Main]>ul{gap:1rem}nav[aria-label=Main] a[href*=book-a-demo]{padding:.4375rem .625rem}nav[aria-label=Main] a[href*=book-a-demo] svg{display:none}div:has(>nav[aria-label=Main])>*,nav[aria-label=Main]>ul>*{margin-inline:0}nav[aria-label=Main] .navbar-link a[href*=\"#free-license\"]{display:inline-flex;align-items:center;border:1px solid rgb(var(--primary-dark));border-radius:.75rem;box-sizing:border-box;padding:calc(.4375rem - 1px) .625rem;color:rgb(var(--primary-dark));background:0 0;font-size:.875rem;font-weight:500;line-height:1.25rem}nav[aria-label=Main] .navbar-link a[href*=\"#free-license\"]:hover{background-color:rgb(var(--primary-dark)/.1)}.dark nav[aria-label=Main] .navbar-link a[href*=\"#free-license\"]{border-color:rgb(var(--primary-light));color:rgb(var(--primary-light))}.dark nav[aria-label=Main] .navbar-link a[href*=\"#free-license\"]:hover{background-color:rgb(var(--primary-light)/.12)}#sidebar-group>li>button>div{line-height:normal}.footer-compliance{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem;max-width:100%}.footer-compliance img{width:2.5rem;height:2.5rem;flex:none;object-fit:contain}@media (max-width:767px){footer.advanced-footer>div>div:first-child>div:first-child{flex-direction:column;align-items:flex-start;justify-content:flex-start;row-gap:1rem;width:100%;height:auto}footer.advanced-footer>div>div:first-child>div:first-child>div:last-child{justify-content:flex-start;min-width:0;max-width:100%}footer.advanced-footer a[class*=truncate],footer.advanced-footer>div>div:first-child>div:last-child,footer.advanced-footer>div>div:first-child>div:last-child>div{white-space:normal!important}}@media (min-width:768px){footer.advanced-footer>div>div:first-child{justify-content:flex-start;column-gap:3rem}footer.advanced-footer>div>div:first-child>div:first-child{min-width:0;justify-content:flex-start;align-items:flex-start;row-gap:1.25rem}footer.advanced-footer>div>div:first-child>div:first-child>div:last-child{margin-top:auto}footer.advanced-footer>div>div:first-child>div:last-child{flex:0 1 auto;justify-content:start;grid-template-columns:repeat(4,max-content)!important;column-gap:4rem!important}footer.advanced-footer>div>div:first-child>div:last-child>div{align-items:flex-start;width:auto;flex:none}footer.advanced-footer a[class*=truncate]{max-width:none!important;overflow:visible!important;text-overflow:unset!important;white-space:nowrap!important}}"}],"page":{"pagePath":"relays/access","slug":"/relays/access","pageMetadata":{"title":"Virtual key access","description":"Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.","icon":"key","href":"/relays/access"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Tab,Table,Tabs,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Tab)_missingMdxReference(`Tab`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tabs)_missingMdxReference(`Tabs`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`Creating a relay gives it an address. Grants decide which callers may use it. Access is deny-by-default: a virtual key reaches a relay only through an explicit grant for that relay, exactly like its agent and MCP grants.`}),`\n`,_jsxs(_components.p,{children:[`Relay access is separate from provider access, MCP tool access and agent access. A key that may call `,_jsx(_components.code,{children:`tavily`}),` gains nothing on `,_jsx(_components.code,{children:`/v1/chat/completions`}),` and the other way round.`]}),`\n`,_jsx(Heading,{level:`2`,id:`grant-a-virtual-key-access`,children:`Grant a virtual key access`}),`\n`,_jsxs(Tabs,{group:`config-method`,children:[_jsx(Tab,{title:`Web UI`,id:`web-ui`,children:_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Open `,_jsx(_components.strong,{children:`Virtual Keys`}),` and add or edit a key.`]}),`\n`,_jsxs(_components.li,{children:[`Find `,_jsx(_components.strong,{children:`Relay access`}),`.`]}),`\n`,_jsx(_components.li,{children:`Select each relay to grant from the picker; a granted relay appears as a row you can remove again.`}),`\n`,_jsx(_components.li,{children:`Save the key.`}),`\n`]})}),_jsxs(Tab,{title:`API`,id:`api`,children:[_jsx(CodeBlock,{filename:``,numberOfLines:`9`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`9`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -X`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` POST`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` http://localhost:8080/api/governance/virtual-keys`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Content-Type: application/json\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -d`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '{`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"name\": \"research-assistant\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"relay_grants\": [`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` { \"relay_name\": \"tavily\" },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` { \"relay_name\": \"textract\" }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` }'`})}),`\n`]})})}),_jsxs(_components.p,{children:[`On update, `,_jsx(_components.code,{children:`relay_grants`}),` replaces the key’s grants as a whole:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -X`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` PUT`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` http://localhost:8080/api/governance/virtual-keys/{vk_id}`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Content-Type: application/json\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -d`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '{ \"relay_grants\": [ { \"relay_name\": \"tavily\" } ] }'`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`An omitted `,_jsx(_components.code,{children:`relay_grants`}),` leaves the grants unchanged and `,_jsx(_components.code,{children:`[]`}),` clears them.`]})]}),_jsxs(Tab,{title:`config.json`,id:`config-json`,children:[_jsx(CodeBlock,{filename:``,numberOfLines:`15`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`15`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"governance\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"virtual_keys\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"vk-research\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"research-assistant\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"value\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"env.RESEARCH_VK\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"relay_grants\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"relay_name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"tavily\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"relay_name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"textract\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Field`}),_jsx(_components.th,{children:`Type`}),_jsx(_components.th,{children:`Default`}),_jsx(_components.th,{children:`Description`})]})}),_jsx(_components.tbody,{children:_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`relay_grants`})}),_jsx(_components.td,{children:`array`}),_jsx(_components.td,{children:`omitted`}),_jsxs(_components.td,{children:[`Relays this key may call, one `,_jsx(_components.code,{children:`{ \"relay_name\": \"...\" }`}),` each. When the key syncs from the file this is its whole list: omitted or `,_jsx(_components.code,{children:`[]`}),` leaves it with none. In split mode an unchanged entry is not synced, so grants made in the dashboard stay until the entry is next edited. Not applied when an access profile governs the key’s team, customer or user (Enterprise): that profile’s `,_jsx(_components.code,{children:`relay_grants`}),` decide the key’s relays.`]})]})})]}),_jsxs(_components.p,{children:[`Relays declared in `,_jsx(_components.code,{children:`config.json`}),` are loaded before governance, so a virtual key in the same file may grant them. A name that matches no relay is skipped with a warning. The key is reconciled again only when its entry changes (or on every start with `,_jsx(_components.code,{children:`config.json`}),` as the source of truth), so after fixing the relay, the grant is applied the next time the key’s entry is synced.`]}),_jsxs(_components.p,{children:[`Like the rest of the key, `,_jsx(_components.code,{children:`relay_grants`}),` is synced from the file when the key’s entry changes, and on every start when `,_jsx(_components.code,{children:`config.json`}),` is the source of truth. The declared list is then the key’s whole list, and omitting it leaves the key with no grants, so grants made in the dashboard are replaced. In split mode an unchanged entry is not synced, so dashboard grants on it stay until the entry is next edited.`]})]}),_jsxs(Tab,{title:`Helm`,id:`helm`,children:[_jsx(CodeBlock,{filename:``,numberOfLines:`14`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`14`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`bifrost`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` governance`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` virtualKeys`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`id`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`vk-research`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` name`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`research-assistant`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` value`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"env.RESEARCH_VK\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` relay_grants`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`relay_name`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`tavily`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`relay_name`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`textract`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# The pod reads RESEARCH_VK from its environment; envFrom loads it from a Kubernetes Secret`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`envFrom`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`secretRef`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` name`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`research-virtual-key`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # a Secret with the key RESEARCH_VK; the value must start with sk-bf-`})]}),`\n`]})})}),_jsxs(_components.p,{children:[_jsx(_components.code,{children:`RESEARCH_VK`}),` must hold a strong random value that starts with `,_jsx(_components.code,{children:`sk-bf-`}),` (for example `,_jsx(_components.code,{children:`sk-bf-$(openssl rand -hex 24)`}),`); a value without that prefix is replaced by a generated key and requests sending the Secret’s value are refused.`]}),_jsxs(_components.p,{children:[`Projects (`,_jsx(_components.code,{children:`bifrost.governance.projects[].relay_grants`}),`) and access profiles (`,_jsx(_components.code,{children:`bifrost.accessProfiles[].relay_grants`}),`) take the same list, with the same sync behaviour as `,_jsx(_components.code,{children:`config.json`}),`. One difference: a virtual key skips only the grant that names an unknown relay, while a project or access profile naming one is skipped as a whole, with a warning.`]}),_jsxs(_components.p,{children:[`A key whose team, customer or user is governed by an access profile (Enterprise) takes its relays from that profile, so its own `,_jsx(_components.code,{children:`relay_grants`}),` are not applied. Grant the relay on the access profile instead.`]})]})]}),`\n`,_jsx(_components.p,{children:`Send the key on every relay request:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`4`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -X`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` POST`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"http://localhost:8080/relay/tavily/search\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Content-Type: application/json\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"x-bf-vk: sk-bf-your-virtual-key\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -d`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '{\"query\": \"Bifrost AI gateway\"}'`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Any header that carries a virtual key on the inference endpoints (`,_jsx(_components.code,{children:`x-bf-vk`}),`, `,_jsx(_components.code,{children:`Authorization: Bearer sk-bf-...`}),`, `,_jsx(_components.code,{children:`x-api-key`}),`, …) carries it here too. Whatever the caller sends in those headers is consumed by Bifrost and never forwarded; the relay signs in with its `,_jsx(_components.a,{href:`/relays/configuration#authentication-types`,children:`own credential`}),`.`]}),`\n`,_jsx(_components.p,{children:`A key without a grant is refused before any upstream effect:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`8`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"is_bifrost_error\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"status_code\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`403`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"relay_blocked\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"error\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"message\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Relay 'tavily' is not allowed for virtual key 'research-assistant'\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`The relay path uses the same authentication middleware as inference. With `,_jsx(_components.code,{children:`client.enforce_auth_on_inference`}),` on, a request must present a credential the deployment accepts (a virtual key, an API key or a user token) or it is refused; grants then restrict what the identified caller may reach. The setting defaults to on for new deployments, while an existing deployment keeps its stored value when the key is omitted, so check it: with enforcement off, a request carrying no credential is relayed without any grant check.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`what-governance-evaluates`,children:`What governance evaluates`}),`\n`,_jsx(_components.p,{children:`A relay call is governed the way an MCP tool execution is: the caller’s identity is resolved, then every budget and rate limit the caller’s holders carry is checked, before the upstream is contacted.`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Applies`}),_jsx(_components.th,{children:`Does not apply`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Virtual key, team, customer budgets (and business unit and project budgets in Enterprise)`}),_jsx(_components.td,{children:`Provider configs and allowed providers`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Request rate limits on the key`}),_jsx(_components.td,{children:`Model budgets and model rate limits`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Key status and expiry`}),_jsx(_components.td,{children:`Routing rules and fallbacks`})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[`Required headers (`,_jsx(_components.code,{children:`client.required_headers`}),`)`]}),_jsx(_components.td,{children:`Token rate limits (a relay has no tokens to count)`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{}),_jsxs(_components.td,{children:[`Model restrictions: a relay names no model to govern, even when the mapping reads a `,_jsx(_components.code,{children:`model_path`}),` for the logs`]})]})]})]}),`\n`,_jsxs(_components.p,{children:[`After the call, every reply the relay forwarded counts one request against the request rate limits, whether or not the route is billable, exactly as every MCP tool execution does: a limit on calls bounds calls. Only a counted call (billable route, `,_jsx(_components.code,{children:`2xx`}),` reply) carries a cost, which is charged to the budgets. A call that never got a reply (the upstream could not be reached) counts nothing. A stream the caller abandoned still reports what was forwarded, so hanging up does not avoid the charge.`]}),`\n`,_jsxs(_components.p,{children:[`The budget and rate-limit ids a call was charged against are recorded on its `,_jsx(_components.a,{href:`/relays/logs`,children:`Relay Logs`}),` row.`]}),`\n`,_jsx(Heading,{level:`2`,id:`enterprise-access-profiles-and-projects`,children:`Enterprise: access profiles and projects`}),`\n`,_jsxs(_components.p,{children:[`On Bifrost Enterprise, `,_jsx(_components.code,{children:`relay_grants`}),` are also available on `,_jsx(_components.a,{href:`/enterprise/access-profiles`,children:`access profiles`}),` and `,_jsx(_components.a,{href:`/enterprise/projects`,children:`projects`}),`, as grant rows only, like their agent grants. A request is allowed when its permits allow it under the same composition rules as agents and MCP tools; a refusal names the profile or project that denied it, for example `,_jsx(_components.code,{children:`Relay 'tavily' is not allowed for access profile 'contractors'`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.strong,{children:`Relays`}),` page itself is gated on the `,_jsx(_components.code,{children:`Relays`}),` `,_jsx(_components.a,{href:`/enterprise/rbac`,children:`RBAC resource`}),`: a user with `,_jsx(_components.code,{children:`Relays:View`}),` can view relays, and one with `,_jsx(_components.code,{children:`Relays:Create`}),`, `,_jsx(_components.code,{children:`Update`}),` or `,_jsx(_components.code,{children:`Delete`}),` can manage them. `,_jsx(_components.a,{href:`/relays/logs`,children:`Relay Logs`}),` are read under the separate `,_jsx(_components.code,{children:`RelayLogs`}),` resource, which has its own `,_jsx(_components.a,{href:`/enterprise/data-access-control`,children:`data access control`}),` scope. On upgrade, the default roles receive their `,_jsx(_components.code,{children:`Relays`}),` and `,_jsx(_components.code,{children:`RelayLogs`}),` permissions as for the Agent Gateway resources; a custom role gets nothing until an admin grants it.`]}),`\n`,_jsx(Heading,{level:`2`,id:`next-steps`,children:`Next steps`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.a,{href:`/features/governance/budget-and-limits`,children:`Budgets and rate limits`})}),` — How the budgets a relay call charges are defined.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.a,{href:`/relays/logs`,children:`Relay Logs`})}),` — See which key, team and customer each call was attributed to.`]}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Virtual key access","description":"Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.","icon":"key","href":"/relays/access"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Grant a virtual key access","slug":"grant-a-virtual-key-access","depth":2,"children":[]},{"title":"What governance evaluates","slug":"what-governance-evaluates","depth":2,"children":[]},{"title":"Enterprise: access profiles and projects","slug":"enterprise-access-profiles-and-projects","depth":2,"children":[]},{"title":"Next steps","slug":"next-steps","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/_mintlify/custom/bifrost/62ad9b1aea461302/googleTag.js","/_mintlify/custom/bifrost/c4c9272fd1c525e5/jsonLd.js","/_mintlify/custom/bifrost/5a8b9314a2dac891/supportWidget.js","/_mintlify/custom/bifrost/088e287583b748b0/baseUrlSwitcher.js","/_mintlify/custom/bifrost/aa532cead633d329/tally-embed.js","/_mintlify/custom/bifrost/fe58824b4f1a0ad5/footerCompliance.js"],"subdomain":"bifrost","siteName":"Bifrost","title":"Virtual key access - Bifrost","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-29T12:57:40.379Z","originalFileLocation":"relays/access.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Bifrost\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Virtual key access - Bifrost\">\u003cmeta data-mint-head property=\"og:description\" content=\"Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Bifrost\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.getbifrost.ai/relays/access\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://bifrost.mintlify.app/_mintlify/api/og/v2?division=Relays\u0026amp;title=Virtual+key+access\u0026amp;description=Grant+relays+to+virtual+keys%2C+and+understand+how+budgets+and+rate+limits+apply+on+the+relay+path.\u0026amp;theme=4d1d84bec9a8c3ee0c7cd8ee\u0026amp;signature=728908a74dc5e60fbac2784dd80b868cf31a1b1cd89cf9903d5e83728f662549\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Virtual key access - Bifrost\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://bifrost.mintlify.app/_mintlify/api/og/v2?division=Relays\u0026amp;title=Virtual+key+access\u0026amp;description=Grant+relays+to+virtual+keys%2C+and+understand+how+budgets+and+rate+limits+apply+on+the+relay+path.\u0026amp;theme=4d1d84bec9a8c3ee0c7cd8ee\u0026amp;signature=728908a74dc5e60fbac2784dd80b868cf31a1b1cd89cf9903d5e83728f662549\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/bifrost/kXIL-Qs6IzN4ZLK4/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Bifrost\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0C3B43\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.getbifrost.ai/relays/access\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/relays/access.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.getbifrost.ai/#organization\",\"name\":\"Bifrost\",\"url\":\"https://docs.getbifrost.ai\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/bifrost/qFMmk8bNSnvgFYDI/media/bifrost-logo.png?fit=max\u0026auto=format\u0026n=qFMmk8bNSnvgFYDI\u0026q=85\u0026s=6af701a560aee4103444fa017b226cf0\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.getbifrost.ai#website\",\"name\":\"Bifrost\",\"url\":\"https://docs.getbifrost.ai\",\"publisher\":{\"@id\":\"https://docs.getbifrost.ai/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.getbifrost.ai/relays/access#webpage\",\"url\":\"https://docs.getbifrost.ai/relays/access\",\"name\":\"Virtual key access\",\"description\":\"Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.\",\"dateModified\":\"2026-10-29T12:57:40.379Z\",\"isPartOf\":{\"@id\":\"https://docs.getbifrost.ai#website\"},\"breadcrumb\":{\"@id\":\"https://docs.getbifrost.ai/relays/access#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.getbifrost.ai/relays/access#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Relays\",\"item\":\"https://docs.getbifrost.ai/relays/overview\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Virtual key access\",\"item\":\"https://docs.getbifrost.ai/relays/access\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.getbifrost.ai/relays/access#article\",\"headline\":\"Virtual key access\",\"name\":\"Virtual key access\",\"description\":\"Grant relays to virtual keys, and understand how budgets and rate limits apply on the relay path.\",\"url\":\"https://docs.getbifrost.ai/relays/access\",\"mainEntityOfPage\":{\"@id\":\"https://docs.getbifrost.ai/relays/access#webpage\"},\"dateModified\":\"2026-10-29T12:57:40.379Z\",\"publisher\":{\"@id\":\"https://docs.getbifrost.ai/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.getbifrost.ai#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Bifrost\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Bifrost","nav":{"global":{"anchors":[{"anchor":"Discord","icon":"discord","href":"https://discord.gg/exN5KAydbU"},{"anchor":"GitHub","icon":"github","href":"https://github.com/maximhq/bifrost"},{"anchor":"Try Enterprise","icon":"building","href":"https://www.getmaxim.ai/bifrost/enterprise"}]},"tabs":[{"tab":"OSS","icon":"book-open-cover","groups":[{"group":"Overview","icon":"book-open-cover","pages":[{"title":"Bifrost AI Gateway","icon":"bridge","href":"/overview"}]},{"group":"Quick Start","icon":"rocket","pages":[{"group":"Gateway","icon":"server","pages":[{"title":"Setting Up","icon":"play","href":"/quickstart/gateway/setting-up"},{"title":"Setting up auth","icon":"lock","href":"/quickstart/gateway/setting-up-auth"},{"title":"Provider Configuration","icon":"sliders","href":"/quickstart/gateway/provider-configuration"},{"title":"Streaming Responses","icon":"water","href":"/quickstart/gateway/streaming"},{"title":"Tool Calling","icon":"wrench","href":"/quickstart/gateway/tool-calling"},{"title":"Multimodal Support","icon":"images","href":"/quickstart/gateway/multimodal"},{"title":"Reranking","icon":"book-open-cover","href":"/quickstart/gateway/reranking"},{"title":"Decisions","icon":"scale-balanced","href":"/quickstart/gateway/decisions"},{"title":"Integrations","icon":"plug","href":"/quickstart/gateway/integrations"}]},{"group":"Bifrost CLI","icon":"laptop-code","pages":[{"title":"Bifrost CLI","sidebarTitle":"Overview","icon":"laptop-code","href":"/quickstart/cli/getting-started"},{"title":"OSS setup","icon":"server","href":"/quickstart/cli/oss-setup"},{"title":"Enterprise setup","icon":"building","href":"/quickstart/cli/enterprise-setup"},{"title":"Contexts and credentials","icon":"layer-group","href":"/quickstart/cli/contexts"},{"title":"Coding agents","icon":"terminal","href":"/quickstart/cli/coding-agents"},{"title":"Commands","icon":"list","href":"/quickstart/cli/commands"},{"title":"Troubleshooting","icon":"screwdriver-wrench","href":"/quickstart/cli/troubleshooting"}]},{"group":"Use as Go SDK","icon":"code","pages":[{"title":"Setting Up","icon":"play","href":"/quickstart/go-sdk/setting-up"},{"title":"Provider Configuration","icon":"sliders","href":"/quickstart/go-sdk/provider-configuration"},{"title":"Context Keys","icon":"key","href":"/quickstart/go-sdk/context-keys"},{"title":"Streaming Responses","icon":"water","href":"/quickstart/go-sdk/streaming"},{"title":"Tool Calling","icon":"wrench","href":"/quickstart/go-sdk/tool-calling"},{"title":"Multimodal Support","icon":"images","href":"/quickstart/go-sdk/multimodal"},{"title":"Reranking","icon":"book-open-cover","href":"/quickstart/go-sdk/reranking"},{"title":"Decisions","icon":"scale-balanced","href":"/quickstart/go-sdk/decisions"},{"title":"Logging","icon":"file-lines","href":"/quickstart/go-sdk/logger"}]}]},{"group":"Release Cadence","icon":"calendar","pages":[{"title":"Release Cadence","icon":"box-open","href":"/release-cadence"}]},{"group":"Migration Guides","icon":"arrow-up-right-dots","pages":[{"title":"Migrating to v2.0.0","href":"/migration-guides/v2.0.0"},{"title":"Migrating to v1.5.0","href":"/migration-guides/v1.5.0"}]},{"group":"Migrate from other Gateway","icon":"arrow-up","pages":[{"title":"Migrating from LiteLLM","icon":"train","href":"/migration-guides/litellm"}]},{"group":"SDK Integrations","icon":"plug","pages":[{"title":"What is an integration?","icon":"box","href":"/integrations/what-is-an-integration"}]},{"group":"Providers \u0026 Guides","icon":"solar-system","pages":[{"group":"Supported Providers","icon":"bars-progress","pages":[{"title":"Overview","icon":"circle-info","href":"/providers/supported-providers/overview"},{"title":"Anthropic","icon":"asterisk","href":"/providers/supported-providers/anthropic"},{"title":"Azure","icon":"microsoft","href":"/providers/supported-providers/azure"},{"title":"Azure Model Router","icon":"microsoft","href":"/providers/supported-providers/azure-model-router"},{"title":"AWS Bedrock","icon":"aws","href":"/providers/supported-providers/bedrock"},{"title":"AWS Bedrock Mantle","icon":"aws","href":"/providers/supported-providers/bedrock-mantle"},{"title":"BytePlus","icon":"b","href":"/providers/supported-providers/byteplus"},{"title":"Cerebras","icon":"c","href":"/providers/supported-providers/cerebras"},{"title":"Cloudflare","icon":"cloud","href":"/providers/supported-providers/cloudflare"},{"title":"Cohere","icon":"c","href":"/providers/supported-providers/cohere"},{"title":"Databricks","icon":"database","href":"/providers/supported-providers/databricks"},{"title":"DeepSeek","icon":"d","href":"/providers/supported-providers/deepseek"},{"title":"ElevenLabs","icon":"pause","href":"/providers/supported-providers/elevenlabs"},{"title":"Fireworks","icon":"sparkles","href":"/providers/supported-providers/fireworks"},{"title":"Google Gemini","icon":"diamond","href":"/providers/supported-providers/gemini"},{"title":"GitHub Copilot","icon":"github","href":"/providers/supported-providers/github-copilot"},{"title":"Groq","icon":"bolt","href":"/providers/supported-providers/groq"},{"title":"Hugging Face","icon":"face-smiling-hands","href":"/providers/supported-providers/huggingface"},{"title":"MiniMax","icon":"m","href":"/providers/supported-providers/minimax"},{"title":"Mistral","icon":"m","href":"/providers/supported-providers/mistral"},{"title":"Nebius","icon":"n","href":"/providers/supported-providers/nebius"},{"title":"Ollama","icon":"o","href":"/providers/supported-providers/ollama"},{"title":"OpenCode","icon":"code","href":"/providers/supported-providers/opencode"},{"title":"OpenAI","icon":"openai","href":"/providers/supported-providers/openai"},{"title":"OpenRouter","icon":"split","href":"/providers/supported-providers/openrouter"},{"title":"Parasail","icon":"p","href":"/providers/supported-providers/parasail"},{"title":"Perplexity","icon":"hexagon-nodes","href":"/providers/supported-providers/perplexity"},{"title":"Replicate","icon":"R","href":"/providers/supported-providers/replicate"},{"title":"Runware","icon":"https://mintlify.s3.us-west-1.amazonaws.com/bifrost/media/runware-nav.svg","href":"/providers/supported-providers/runware"},{"title":"Runway ML","icon":"film","href":"/providers/supported-providers/runway"},{"title":"Sarvam AI","icon":"s","href":"/providers/supported-providers/sarvam"},{"title":"SGLang","icon":"s","href":"/providers/supported-providers/sgl"},{"title":"TypeSafe","icon":"scale-balanced","href":"/providers/supported-providers/typesafe"},{"title":"Vertex AI","icon":"v","href":"/providers/supported-providers/vertex"},{"title":"vLLM","icon":"v","href":"/providers/supported-providers/vllm"},{"title":"Wafer","icon":"w","href":"/providers/supported-providers/wafer"},{"title":"xAI","icon":"x","href":"/providers/supported-providers/xai"}]},{"title":"Routing Rules","icon":"chart-diagram","href":"/providers/routing-rules"},{"title":"Provider Routing","icon":"route","href":"/providers/provider-routing"},{"title":"Session Affinity","icon":"link","href":"/providers/session-affinity"},{"title":"Aliasing Models","icon":"tag","href":"/providers/aliasing-models"},{"title":"Reasoning","icon":"brain","href":"/providers/reasoning"},{"title":"Performance Tuning","icon":"gauge-high","href":"/providers/performance"},{"title":"Custom Providers","icon":"gear","href":"/providers/custom-providers"},{"title":"Self-Hosted Decision Models","icon":"server","href":"/providers/self-hosted-decision-models"},{"title":"Custom Pricing","icon":"circle-dollar-to-slot","href":"/providers/custom-pricing"},{"title":"Request Options","icon":"list","href":"/providers/request-options"},{"title":"Response Headers","icon":"arrow-left-to-line","href":"/providers/response-headers"},{"title":"Test Harness Coverage","icon":"list-check","href":"/providers/test-harness-coverage"}]},{"group":"MCP Gateway","icon":"toolbox","pages":[{"title":"Overview","sidebarTitle":"Overview","icon":"circle-info","href":"/mcp/overview"},{"title":"Connecting to MCP Servers","sidebarTitle":"Connecting to Servers","icon":"plug","href":"/mcp/connecting-to-servers"},{"title":"OpenAPI Servers","sidebarTitle":"OpenAPI Specs","icon":"file-code","href":"/mcp/openapi-servers"},{"title":"Connections, States \u0026 Lifecycles","sidebarTitle":"Connections \u0026 States","icon":"diagram-project","href":"/mcp/connections"},{"title":"Virtual MCPs","icon":"layer-group","href":"/mcp/virtual-mcps"},{"group":"Authentication","icon":"shield-check","pages":[{"title":"MCP Authentication","sidebarTitle":"Overview","icon":"shield-check","href":"/mcp/auth/overview"},{"title":"No Authentication","sidebarTitle":"None","icon":"globe","href":"/mcp/auth/none"},{"title":"Header-Based Authentication","sidebarTitle":"Headers","icon":"key","href":"/mcp/auth/headers"},{"title":"Per-User Headers","sidebarTitle":"Per-User Headers","icon":"user-pen","href":"/mcp/auth/per-user-headers"},{"title":"OAuth 2.0 Authentication","sidebarTitle":"OAuth 2.0","icon":"lock","href":"/mcp/auth/oauth"},{"title":"Per-User OAuth","sidebarTitle":"Per-User OAuth","icon":"user-shield","href":"/mcp/auth/per-user-oauth"},{"title":"Token Exchange (On-Behalf-Of)","sidebarTitle":"Token Exchange","icon":"right-left","href":"/mcp/auth/token-exchange"},{"title":"Cross App Access (ID-JAG)","sidebarTitle":"Cross App Access","icon":"building-lock","href":"/mcp/auth/cross-app-access"}]},{"title":"MCP Sessions","sidebarTitle":"Sessions","icon":"table","href":"/mcp/sessions"},{"title":"Tool Execution","sidebarTitle":"Tool Execution","icon":"play","href":"/mcp/tool-execution"},{"title":"Agent Mode (Auto-Execution)","sidebarTitle":"Agent Mode","icon":"robot","href":"/mcp/agent-mode"},{"title":"Code Mode","sidebarTitle":"Code Mode","icon":"code","href":"/mcp/code-mode"},{"title":"Gateway Authentication","icon":"key","href":"/mcp/gateway-auth"},{"title":"Tool Hosting","sidebarTitle":"Tool Hosting","icon":"toolbox","href":"/mcp/tool-hosting"},{"title":"Tool Filtering","sidebarTitle":"Filtering","icon":"filter","href":"/mcp/filtering"}]},{"group":"Agent Gateway","icon":"robot","pages":[{"title":"Agent Gateway","sidebarTitle":"Overview","icon":"robot","href":"/features/agent-gateway/overview"},{"title":"Register your first agent","icon":"plus","href":"/features/agent-gateway/registration"},{"title":"Authentication","icon":"key","href":"/features/agent-gateway/authentication"},{"title":"Agent access","icon":"shield-check","href":"/features/agent-gateway/access-control"},{"title":"Messages, tasks, and events","icon":"comments","href":"/features/agent-gateway/messages-and-tasks"},{"title":"Connect model and tool calls","icon":"link","href":"/features/agent-gateway/integrating-your-agent"},{"title":"Read Agent Logs","icon":"magnifying-glass","href":"/features/agent-gateway/observability"},{"title":"Gateway settings and transports","icon":"gear","href":"/features/agent-gateway/configuration"},{"title":"Transport selection and recovery","icon":"arrows-rotate","href":"/features/agent-gateway/transports-and-recovery"},{"title":"Push notifications","icon":"bell","href":"/features/agent-gateway/push-notifications"},{"title":"Export agent telemetry","icon":"chart-line","href":"/features/agent-gateway/connectors"},{"title":"Troubleshooting","icon":"wrench","href":"/features/agent-gateway/troubleshooting"}]},{"group":"Relays","icon":"waypoints","pages":[{"title":"Relays","sidebarTitle":"Overview","icon":"circle-info","href":"/relays/overview"},{"title":"Create a relay","icon":"plus","href":"/relays/configuration"},{"title":"Routes and header matchers","icon":"route","href":"/relays/routes"},{"title":"Usage mapping and pricing","description":"Price every counted relay call with a flat fee, a per-unit rate read from the request or response, and the cost the upstream reports; test the mapping before you save.","icon":"calculator","href":"/relays/pricing"},{"title":"Virtual key access","icon":"key","href":"/relays/access"},{"title":"Streaming","description":"When a relayed reply is forwarded as it arrives, how to force it, and how a stream is priced.","icon":"wave-square","href":"/relays/streaming"},{"title":"Relay Logs","icon":"magnifying-glass","href":"/relays/logs"},{"title":"Troubleshooting","icon":"wrench","href":"/relays/troubleshooting"}]},{"group":"Custom plugins","icon":"puzzle-piece","pages":[{"title":"Getting Started","icon":"book","href":"/plugins/getting-started"},{"title":"Building Dynamically Linked Bifrost Binary","icon":"hammer","href":"/plugins/building-dynamic-binary"},{"title":"Plugin Sequencing","icon":"arrow-down-1-9","href":"/plugins/sequencing"},{"group":"Writing Plugins","icon":"code","pages":[{"title":"Writing Go Plugins","icon":"golang","href":"/plugins/writing-go-plugin"},{"title":"Writing WASM Plugins (Deprecated)","icon":"puzzle-piece","href":"/plugins/writing-wasm-plugin"}]},{"title":"Plugin Migration Guide","icon":"arrow-up-right-dots","href":"/plugins/migration-guide"}]},{"group":"Open Source Features","icon":"bolt","pages":[{"title":"Drop-in Replacement","icon":"shuffle","href":"/features/drop-in-replacement"},{"title":"Retries \u0026 Fallbacks","icon":"list-check","href":"/features/retries-and-fallbacks"},{"title":"Complexity Router","tag":"Beta","icon":"sliders","href":"/features/complexity-router"},{"title":"Warp","tag":"Alpha","icon":"sparkles","href":"/features/warp"},{"title":"Compatibility Plugin","icon":"train","href":"/features/compat-plugin"},{"title":"Load Balance","icon":"scale-balanced","href":"/features/keys-management"},{"title":"Async Inference","icon":"clock","href":"/features/async-inference"},{"title":"Webhooks","icon":"webhook","href":"/features/webhooks"},{"title":"News Feeds","icon":"newspaper","href":"/features/news-feeds"},{"group":"Governance","icon":"user-lock","pages":[{"title":"Virtual Keys","icon":"key","href":"/features/governance/virtual-keys"},{"title":"Routing","icon":"arrow-progress","href":"/features/governance/routing"},{"title":"Budget and Limits","icon":"money-bills","href":"/features/governance/budget-and-limits"},{"title":"Model Limits","icon":"sliders","href":"/features/governance/model-limits"},{"title":"MCP Tool Filtering","icon":"grid-2","href":"/features/governance/mcp-tools"},{"title":"Required Headers","icon":"shield-check","href":"/features/governance/required-headers"}]},{"title":"Telemetry","icon":"gauge","href":"/features/telemetry"},{"title":"OpenTelemetry","icon":"telescope","href":"/features/otel"},{"title":"Content Logging","icon":"eye-slash","href":"/features/observability/content-logging"},{"title":"Latency \u0026 Overhead Breakdown","icon":"gauge","href":"/features/observability/latency-breakdown"},{"title":"Semantic Caching","icon":"database","href":"/features/semantic-caching"},{"title":"Auto Prompt Caching","icon":"zap","href":"/features/prompt-caching"},{"title":"Skills Repository","icon":"book","href":"/features/skills-repository"},{"group":"Prompt Repository","icon":"folder","pages":[{"title":"Playground","icon":"square-terminal","href":"/features/prompt-repository/playground"},{"title":"Prompts plugin","icon":"puzzle-piece","href":"/features/prompt-repository/prompts-plugin"}]},{"group":"Plugins","icon":"puzzle-piece","pages":[{"title":"Mocker","icon":"mask","href":"/features/plugins/mocker"},{"title":"JSON Parser","icon":"code-branch","href":"/features/plugins/jsonparser"}]}]}]},{"tab":"Enterprise","icon":"building","pages":[{"title":"Enterprise","href":"/enterprise/overview"}]},{"tab":"Edge","icon":"globe","pages":[{"title":"Edge","href":"/edge/overview"}]},{"tab":"Integrations","icon":"plug","pages":[{"title":"Integrations","href":"/runbooks/claude-code-bedrock"}]},{"tab":"Deployment Guides","icon":"server","pages":[{"title":"Deployment Guides","href":"/deployment-guides/overview"}]},{"tab":"API","icon":"code","pages":[{"title":"API","href":"/api/procuring-api-keys"}]},{"tab":"Contributing","icon":"code-pull-request","pages":[{"title":"Contributing","href":"/contributing/setting-up-repo"}]},{"tab":"Benchmarks","icon":"chart-line","pages":[{"title":"Benchmarks","href":"/benchmarking/getting-started"}]},{"tab":"Changelogs","icon":"bolt","menu":[{"item":"Open Source","icon":"rocket","pages":[{"title":"Open Source","href":"/changelogs/v2.3.2"}]},{"item":"Enterprise","icon":"building","pages":[{"title":"Enterprise","href":"/changelogs/ent-v2.3.2"}]},{"item":"Edge","icon":"grip","pages":[{"title":"Edge","href":"/changelogs/edge-v0.9.4"}]},{"item":"Bifrost CLI","icon":"laptop-code","pages":[{"title":"Bifrost CLI","href":"/changelogs/cli-v1.0.0"}]},{"item":"Helm","icon":"box","pages":[{"title":"Helm","href":"/changelogs/helm-v2.1.46"}]}],"pages":[{"title":"Changelogs","href":"/changelogs/v2.3.2"}]}]},"title":"Virtual key access - Bifrost","buildId":"dpl_2xiSHD9XEvLsPGPcfoMtkLTB3dy9","deploymentId":"dpl_2xiSHD9XEvLsPGPcfoMtkLTB3dy9","dynamics":[],"chunks":[]}