Skip to main content
Routing rules are priority-ordered rewrites that PromptGuard applies between auth and policy evaluation. Each rule has a condition (when it fires) and an action (what it changes). The first matching rule wins. The three big use cases:
  1. Cost control — downgrade simple prompts to a cheaper model.
  2. Vendor pinning — force a specific tenant onto a specific provider, e.g. for compliance or data-residency reasons.
  3. Resilience — name the models to fall back to when a model is rate limited or down, without changing your code.

Anatomy

  • priority — lower numbers fire first. Use 100, 200, 300, … so you can wedge new rules between old ones without renumbering.
  • condition — JSON object describing what to match. See the conditions reference below.
  • action — JSON object describing the rewrite. Sets provider, model or fallback_models (at least one), and optionally failover_provider.

Conditions reference

Conditions are AND-ed together inside a rule. Use multiple rules with different priorities for OR semantics.

Actions reference

Smart failover

When failover_provider is set on a matched rule and the primary upstream returns 5xx on a non-streaming request, PromptGuard:
  1. Re-authenticates against the failover provider’s stored Provider Key. With no stored key for that provider, there is no retry and the caller sees the primary’s error.
  2. Issues exactly one retry. No exponential backoff, no recursion — if the failover also 5xx’s, the caller sees that error.
Streaming requests are not retried by failover_provider: the primary’s 5xx reaches the caller, unless the rule also names fallback_models. Non-5xx responses (rate limits, validation errors, timeouts) are surfaced as-is. The gateway does not switch vendors for a 429, because a 429 from the primary usually means your account is being rate limited, and switching providers without telling the caller is a great way to silently drop traffic. The retry shares the request’s one time limit with every other call to a provider, so it never makes a request take longer than a single call could. See One time limit for the whole request.

Fallback models

A rule’s fallback_models is the same chain a request can name for itself, applied to every request the rule matches. It works exactly as described in Fallback Models: the models are tried in order after a failure worth retrying, each one only on a vendor you have consented to, and the response’s X-PromptGuard-Model-Used header names the model that answered.
  • A chain in the request replaces the rule’s. A request that sends its own fallback_models field or X-PromptGuard-Fallback-Models header uses that chain and never the rule’s. The rest of the rule (its provider and model) still applies.
  • The chain follows the rule’s rewrite. When the rule also sets model, the fallbacks are for that model.
  • With failover_provider too, a non-streamed request’s model gets its retry on the failover provider first, and the fallback models are tried after it.
  • A model on a vendor you have not consented to — no stored provider key for it — is skipped for every request the rule matches, and the request goes ahead with its own model and the rule’s other fallback models. So is a model on another vendor on /api/v1/messages or /api/v1/responses, whose bodies only one vendor can read. A rule’s chain never stops a request that would otherwise have been answered. Saving the rule warns you about each model on a vendor with no stored key, and saves it anyway.
  • Saving the rule refuses a chain of more than 3 models, one that names a model twice, or a model no provider serves.
In the dashboard, set the chain in the rule editor’s Fallback models field, a comma-separated list, rather than in the action JSON.

Match counters

Every rule that fires increments match_count and updates last_matched_at. The dashboard surfaces these so you can spot dead rules (created six months ago, never matched) and aggressive ones (matching 90% of traffic — probably too broad).

Worked example

A gpt-4 request from an internal tenant gets rewritten to Claude Sonnet 4.5 (priority 50 fires first). A short prompt without that header goes to gpt-5-nano. Any other GPT request stays on OpenAI, and falls back to Claude 3.5 Haiku when OpenAI is rate limited or down, provided you have stored an Anthropic provider key.