Skip to main content
A policy decides what a request may do: which models it may call, which host keys it may spend, how those keys are picked, and which rate limit applies. Every request made with a relay key or an inference token is governed by at most one policy.

What a policy holds

A policy you create is owned by a user, a project, or the deployment (system); host-owned policies are the catalog’s tier policies.

Granting models

models is an allow-list of references. A reference has up to three parts, and a missing part matches everything: Rules:
  • Names are normalized, so openai/gpt-5.5 and openai/gpt-5-5 are the same reference.
  • There are no patterns. A part containing *, such as openai/gpt-*, is refused with 400; leave the part out to match everything.
  • References with a missing part expand against the live catalog, so a model added later is covered without editing the policy.
  • Those wildcard references skip deprecated and sunset models unless includeDeprecated is set. A provider/model reference grants the model whatever its status.
  • There is no deny syntax. To exclude a model, list what you do want.
  • An empty models list grants every model reachable through the policy’s host keys, except models on keyless (noAuth) hosts, which always need an explicit reference.
A grant alone does not make a model callable: the request also needs a host key in hostKeyIds for a host that serves the model, unless the host is keyless. When a model is granted on several hosts, routing uses the first granted binding whose host has a usable key; pin a host with model@host in the request to choose. See Naming a model in a request. To check what a reference expands to before saving it:

Which policy governs a request

Relay resolves the governing policy once per request, in this order, and stops at the first match:
  1. The relay key’s own spec.policyId.
  2. The service account’s spec.policyId, when the key belongs to a service account.
  3. The project’s policy bindings, lowest priority first, ties broken by name. The first enabled binding that names one of the caller’s subjects wins.
A disabled policy found at any step is the answer: Relay returns 403 policy_disabled instead of falling through to a broader one. A credential scoped to a project that resolves no policy gets 403 no_policy. Inference tokens carry no policy of their own, so they always resolve through the project’s policy bindings.

Policy bindings

A policy binding points subjects inside one project at one policy: The caller’s subjects are its identity plus its groups:
  • A user (personal relay key or inference token): user:<id>, every group the user belongs to, and system:authenticated.
  • A service account: serviceaccount:<id>, system:serviceaccounts, system:serviceaccounts:<project>, and system:authenticated.
Bind system:authenticated at a high priority number to give a project a default policy, and bind specific users, groups or service accounts at lower numbers to override it.

Personal keys and project policies

A relay key that belongs to a user and points at a project-owned policy is attributed to that project: its usage carries the project and team, and it shares the policy’s rate-limit counters with the project’s other callers. A personal key that points at no policy and belongs to no project uses the policy-less flow below.

Requests without a policy

A personal relay key with no policy and no project is served only when the inference setting allowMissingPolicy is true, and never under RELAY_AUTHZ=rbac. Such requests have no model grant and no policy rate limit: they reach any model whose host has a system-owned host key or one of the caller’s own, and they skip deprecated models. With the setting off, they get 403 policyless_disabled.
PUT replaces the whole section; read it first with GET /api/settings/inference and change only this field. See Settings.

Tier policies on host keys

The catalog also ships tier policies, owned by a host, that describe a provider’s account tiers (for example OpenAI’s usage tiers). They never govern a request. Every host key names one in spec.policyId, and it must belong to the key’s own host. The tier policy does two things for that key:
  • Its model grant narrows which models the key may serve. A key whose tier policy does not grant the requested model is left out of the pool.
  • Its rate limit caps the key upstream, shared by every policy that lists the key. See Upstream limits per host key.
List a host’s tier policies, with their limits, to pick one for a new host key:

Example manifest

A project-owned rate limit and policy, and a binding that makes the policy the project’s default. Apply it with relay apply:
Manifests reference other rows by name; the control API takes ids (hostKeyIds, rateLimitId, projectId, policyId).

Control API

Changes reach every pod within about a second. See Control API for authentication and the shared CRUD conventions.