Quickstart: Write a Custom Policy
The AI Gateway's built-in policies cover model access, budgets, caching,
guardrails, and tracing—but your gateway can run any policy you can write in
TypeScript. A custom policy lives in your gateway's
repository, is declared in config/policies.json, and
from then on appears in the portal's Add Policy dialog like any built-in
policy. Apps add it to their policy chains, and it runs
on every request for those apps.
This quickstart builds a content filter that blocks prompts containing banned
terms. By the end, one app on your gateway rejects a prompt containing
"acme-secret-project" with a 400 response, while other apps are unaffected.
Prerequisites
- An AI Gateway project connected to a Git repository, with a provider, a team, and an app—the Getting Started guide covers this
- A local clone of the gateway's repository
-
Write the policy module
In your clone of the gateway repository, create a
modules/directory next toconfig/if it doesn't exist yet, and addmodules/content-filter.ts. A policy is a function that receives the request, a context, and the options configured for it—and returns the request to continue the chain, or aResponseto answer immediately:CodeThe calling app is available on
request.userwhen the request's API key resolves to one—subis the app's name—so a policy can log, branch, or report per app. It can beundefined, so use optional chaining. The example inspects chat and response payloads; embeddings requests pass through unfiltered. -
Declare the policy in
config/policies.jsonThe repository already contains
config/policies.jsonwith the built-in policy declarations. Add one more entry to itspoliciesarray—the entry'snameis how the policy appears in the portal. The declaration makes the policy available for apps to select; it doesn't run for any app yet:Code -
Deploy
Commit both files and push to your default branch:
CodeThe next production deploy puts the new policy on the menu—with GitHub, the push itself deploys; see Source Control for the other Git providers.
-
Add the policy to an app's chain
In the Zuplo Portal, open Apps, select your app, and open its Policies tab. Click Add Policy—
content-filternow appears alongside the built-in policies. Add it, drag it to where in the chain it should run, and save.Where in the chain?
If the chain has the Budgets and Costs policy, placing the filter before it means blocked requests aren't counted against the app's budget; placing it after means they are. The same reasoning applies to any policy that can answer a request itself.
The change applies within about a minute—no deploy.
-
Test it
Send a prompt containing a blocked term through the app, using the URL and API key from the app page (the URL below is a stand-in for it):
CodeThe gateway answers with the policy's
400response. Send a harmless prompt and the request flows through to the provider as usual. Apps that don't includecontent-filterin their chains are unaffected.
Per-app settings
An app's chain entry can override the declared options completely. In the portal, edit the entry's options to give one app its own list:
Code
An entry that overrides options replaces the declaration's entire options object —fields aren't merged. An entry without options inherits the declaration's options exactly.
Configure credentials
If a policy needs a credential—say it calls an external moderation API—set it in the declaration's options, and let chain entries inherit it:
Code
Leave the chain entry's options out so it inherits the declaration's values—an entry that sets its own options replaces them completely.
Beyond filtering
A custom policy can do more than block requests—the cookbooks walk through complete recipes:
- Route models dynamically. Read the live model catalog and select the model per request—for example, always the cheapest active model. See Dynamic model routing.
- Choose fallbacks from code. Enrich the model selection with a dynamically chosen backup. See Custom fallback logic.
- Enrich or annotate. Add headers, log structured events, or call out to other services.
Next steps
- Policy Chains: execution order, options inheritance, and the built-in policies
- Policy Templates: roll a custom policy out to every new app in a team
- Source Control: how repository changes deploy