Policies

Match requests on tenant, task, size, and sensitivity — then enforce.

Routing decides who answers. Policies decide what is allowed — which models a request may reach, what it may spend, how long it may take, and what happens when something fails. Every request resolves exactly one policy, and the verdict travels with the request into logs, metrics, and /explain.

What a policy matches on#

DimensionExample
Modelgpt-4o-mini, an alias, or a capability such as vision
Tenant / keyProduction tenant vs sandbox tenant
TaskThe rules-first classification (support, code, summarize, …)
Prompt sizeSmall prompts vs near-window contexts
RegionRoute EU tenants to EU providers
SensitivityFlagged content to approved providers only
EndpointA named endpoint scope

A policy, conceptually:

yaml
name: eu-support
match:
  tenant: acme-eu
  task: support
  region: eu
allow_models: ["support-draft"]   # aliases welcome
strategy: lowest_latency
fallback: [anthropic-eu, local-ollama]
limits:
  max_tokens: 512
  per_request_usd: 0.02
timeouts:
  total: 60s

Author policies in the dashboard (Policies page) or the admin API — no restarts, no config edits, effective immediately.

Specificity wins#

When several policies match, the most specific wins; ties break by priority. A rule for tenant + task + region always beats a rule for task alone. This is what makes policies composable: write broad defaults, then carve out precise exceptions without reordering anything.

What a policy enforces#

  • Access — deny with 403/429 and an explaining message, zero provider calls, the rule named.
  • Spend — per-request ceilings checked against projected cost before the call, plus token/request rate limits and daily/monthly budgets.
  • Time — per-attempt and total timeouts; a request cut short says so (truncated: true with the reason) rather than looking short.
  • Failure behavior — bounded retry with deterministic jitter, fallback chains, and circuit-breaker interaction per provider.

Denials explain themselves#

A denied request returns the rule that fired and why — in the response, in the error envelope's synapass block, and in the request log. Policy debugging is reading, not guessing.