Policies

Change which detectors run and what they are allowed to do, for one project and environment.

Every profile starts with the same defaults: all of its detectors run, and every action counts. A policy is the exception list for one project and one environment. It turns single detectors off or holds them in monitor mode, so you can tune detection without changing application code.

  • Disable a detector that does not fit your traffic: it is removed from the plan and never appears in a verdict
  • Monitor a detector to learn what it would catch while its action is capped at flag
  • Publish per profile: an override on balanced does not touch deterministic or audit
  • Set it in the dashboard or over HTTP - the SDKs check text, they do not manage policies

What a policy changes

A policy holds overrides for one profile in one project and environment. Two settings can change on each detector:

  • Enabled: turn a detector off and it is removed from the plan. It does not run, and it is absent from the verdict and from Events. Leave it on and it runs as always
  • Mode: enforce (the default) lets the detector act as documented - text.pii redacts, output.secret_leak blocks. monitor still runs the detector and records its true outcome, but caps its action at flag (see Monitor mode)

Every detector you do not override keeps the default: enabled and enforcing. Everything else about the profile - its detector list, budget and normalization - is fixed; see What you cannot change.

A policy is stored per profile. Publishing an override for balanced changes checks that ask for balanced, and nothing else. Set the override on each profile your traffic uses.

Monitor mode

A monitored detector runs for real. Its true score and action are still recorded in the verdict's detectors array and in Events, but its action is capped at flag when the verdict is built. A monitored detector never blocks a turn and never rewrites text.

  • Monitored secret leak still reports the credential it found, but the reply reaches your user with a flag instead of being blocked
  • Monitored PII still reports the email or card number, but the text is returned unchanged - the data goes through
  • The cap is visible - the trace shows the detector's true action next to a monitor label, so nothing is silently dropped

Monitor mode is how you try a detector on real traffic before enforcing it: publish it, watch what fires in Events, then switch it to enforce.

Monitor mode is measurement, not protection
The finding is recorded and can still raise a verdict to flag, but nothing is blocked or redacted. A monitored detector that finds PII lets the text through untouched. Enforce it once you have seen what it catches.

Scope

  • A policy belongs to one project and one environment. The dashboard project and environment switchers decide the pair the matrix edits
  • The key decides the scope of a check. A vx_test_... key resolves to dev and a vx_live_... key to prod, so the right policy applies to a check without any extra request fields
  • Keys in the same pair share one policy. Scoping stops at project and environment: two API keys in the same project and environment get the same overrides. Give an app its own project when it needs its own policy

Create your own profile

The three built-in profiles are starting points. When two apps need different protection, create a profile for each and name it on the check: a chatbot can stay on deterministic while an agent that touches money or data uses agent, a profile you built from audit.

Use a profile for one call
const verdict = await guard.checkInput(userMessage, { profile: "agent" });
  • In the dashboard, open Policy, choose New profile, give it a name and pick the built-in it starts from, then switch detectors off or to monitor like any other tab
  • Over HTTP, POST /v1/policy/profiles creates one and DELETE /v1/policy/profiles/{name} removes it:
Create a profile from audit
curl -X POST https://api.verexa.dev/v1/policy/profiles \  -H "Authorization: Bearer $VEREXA_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "name": "agent",    "base": "audit",    "detectors": {      "text.pii": { "enabled": false, "mode": "enforce" }    }  }'
  • A new profile inherits its base. Its detector list, time budget and judge behavior are those of the built-in it starts from, so one based on audit still sends every check to the judge
  • Names are 2 to 32 characters: a lowercase letter, then lowercase letters, digits, - or _. deterministic, balanced and audit are reserved
  • Each project and environment holds up to 20. A profile created while the dashboard is on dev does not exist in prod
  • A check that names a profile that does not exist is rejected with a 400 unknown profile. The SDKs log one warning with that reason and return the degraded fallback, so fix the name or create the profile
  • The project default profile is still one of the three built-ins. Name a created profile on each check that should use it

Set a policy in the dashboard

Open Policy in the dashboard sidebar. The screen is one matrix with a tab per profile and a row per detector.

  • Profile tabs. deterministic, balanced and audit each keep their own overrides, so a detector can be enforced in one and monitored in another
  • Enabled. The switch turns a detector on or off in the plan
  • Mode. enforce or monitor, per detector
  • Action and Fires (24h). What the detector does when it fires, and how often it has fired in the last 24 hours - useful before you monitor or enforce something

Changes are staged, so nothing changes until you publish:

  1. Change the switches you want, on any profile tab
  2. Click Review & publish to see the diff
  3. Confirm to apply it to the selected project and environment

The publish dialog flags changes worth a second look: a detector leaving the plan, monitor mode on an output detector, or a profile with every detector disabled. The matrix edits the project and environment selected in the top bar; other projects keep their own policy.

Set a policy over HTTP

The SDKs only check text - they have no policy methods - so scripted changes go through the API. The key scopes the request to its project and environment. Read the current policy first:

Read the policy
curl https://api.verexa.dev/v1/policy \  -H "Authorization: Bearer $VEREXA_API_KEY"
Response (trimmed)
{  "profiles": {    "balanced": {      "detectors": {        "output.markdown_exfil": { "enabled": true, "mode": "enforce" },        "output.secret_leak": { "enabled": true, "mode": "enforce" },        "prompt.injection_classifier": { "enabled": true, "mode": "monitor" },        "text.pii": { "enabled": false, "mode": "enforce" }      }    }  }}

Publish an override with PUT:

Monitor the classifier and disable PII on balanced
curl -X PUT https://api.verexa.dev/v1/policy \  -H "Authorization: Bearer $VEREXA_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "profile": "balanced",    "detectors": {      "prompt.injection_classifier": { "enabled": true, "mode": "monitor" },      "text.pii": { "enabled": false, "mode": "enforce" }    }  }'
  • The profile is required and must be deterministic, balanced, audit or a profile you created
  • The body replaces the overrides stored for that profile. Include every override you want to keep; a detector you leave out returns to the default, enabled and enforcing
  • To clear a profile, send an empty detectors object; every detector returns to its default
  • The response is the full policy view, the same shape the GET returns
Send enabled explicitly
In a request body it is an ordinary boolean, and a missing field reads as false. A detector object like {"mode": "monitor"} disables the detector instead of monitoring it.
StatusBodyWhen
400unknown profileprofile is not a built-in profile or one you created
400invalid request bodyThe body is not valid JSON
503could not persist policyThe override could not be stored; the policy in force is unchanged

When changes apply

  • On the next check. A publish affects checks that start after it; a check already in flight finishes under the plan it started with
  • Not from an old cache. The change gives the profile a new plan hash, and cached verdicts are keyed by it, so no verdict cached under the previous policy is served again
  • Durably, when there is a database. With a control-plane database the overrides are stored and survive restarts; without one they live in the service memory and reset when the service restarts
  • All or nothing. A publish that cannot be stored is rejected, and the policy already in force keeps serving

What you cannot change

  • No custom detectors. Patterns, thresholds and phases are fixed; a policy can only switch a detector off or cap it in monitor mode
  • No time budget or normalization tuning. They come from the profile, or from the built-in a profile you created starts from
  • The judge is not on the list. It has no row and cannot be disabled; whether it reviews a verdict comes from the profile - balanced runs it in the background and audit before answering. See Core concepts
  • The classifier is input only. Turning it off affects input checks; output text was never sent to it

Next steps