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.5andopenai/gpt-5-5are the same reference. - There are no patterns. A part containing
*, such asopenai/gpt-*, is refused with400; 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
includeDeprecatedis set. Aprovider/modelreference grants the model whatever its status. - There is no deny syntax. To exclude a model, list what you do want.
- An empty
modelslist grants every model reachable through the policy’s host keys, except models on keyless (noAuth) hosts, which always need an explicit reference.
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:- The relay key’s own
spec.policyId. - The service account’s
spec.policyId, when the key belongs to a service account. - The project’s policy bindings, lowest
priorityfirst, ties broken by name. The first enabled binding that names one of the caller’s subjects wins.
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, andsystem:authenticated. - A service account:
serviceaccount:<id>,system:serviceaccounts,system:serviceaccounts:<project>, andsystem:authenticated.
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 theinference 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 inspec.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.
Example manifest
A project-owned rate limit and policy, and a binding that makes the policy the project’s default. Apply it withrelay apply:
hostKeyIds, rateLimitId, projectId, policyId).
Control API
Changes reach every pod within about a second. See Control API for authentication and the shared CRUD conventions.