Policies
Policy Controls Catalog
This page lists every policy control that the gateway runs, grouped by the phase in which it runs. Find the control for the result you need, then open its page for the settings and a test. A control runs only when it is in the applicable policies.chain.
New to policies? Start with the Policy Configuration Overview.
Select controls by outcome
| Outcome | Start with | Add when necessary |
|---|---|---|
| Block prompt attacks | prompt-injection | embedding-detector for similarity signals |
| Remove personal identifiers | pii-detector | hipaa-phi-detector for more identifier patterns |
| Protect organization data | dlp-filter | data-routing-policy to limit eligible providers |
| Control agent tools | tool-validation | tool-security, tool-budget, and agent-firewall |
| Control output quality or evidence | quality-scorer | citation-verifier and human-oversight |
| Change prompts or responses | request-rewriter | response-rewriter for non-streaming output |
| Add compliance text controls | Compliance Policy Configuration | One compliance control at a time, after you read its limits |
| Record an audit marker | audit-logger | Events and Trail for evidence, storage, and integrity |
Controls with similar names do different work. For example, tool-budget compares the max_tokens value of the request with a tool limit and does not measure cost. audit-logger adds an allow-only marker and does not configure retention.
In the tables below, Families shows the request families that a control accepts:
- All: Chat Completions, Completions, Responses, Messages, Embeddings, Audio, and Moderation
- Text: Chat Completions, Completions, Responses, and Messages
- Tools: Chat Completions, Responses, and Messages
At this time, the gateway evaluates the chain only on Chat Completions, Responses, and Messages requests. The embeddings, audio, moderation, and legacy completions routes do not run any control. See Runtime Request Families.
Input phase controls
These controls examine the request before the gateway forwards it.
| Control | What it does | Families |
|---|---|---|
prompt-injection | Detects jailbreak and prompt-injection signals | Text |
pii-detector | Redacts or blocks personal identifiers in the request, and redacts them in the buffered response | All |
hipaa-phi-detector | Adds HIPAA-style PHI checks to the shared redaction pipeline | Text |
dlp-filter | Applies pattern-based data loss prevention | All |
safety-filter | Blocks or escalates configured dangerous terms | Text |
rbac | Enforces role, identity, and data-sensitivity access rules | All |
cjis-mode | Enforces CJIS-style constraints on the authenticated identity | All |
student-privacy | Detects student-record markers and replaces student-ID phrases | Text |
case-privacy | Detects built-in case-number patterns | Text |
itar-ear-filter | Blocks export-control reference terms | Text |
entity-list-filter | Matches denied or watch-listed entities | Text |
dual-use-filter | Detects dual-use and sensitive capability signals | Text |
data-routing-policy | Limits the provider targets that can receive the request | All |
bot-detector | Flags matching fingerprints or near-identical prompts on one gateway | All |
language-validator | Blocks or warns when the request language is not allowed | Text |
request-rewriter | Changes selected request text fields before forwarding | Text |
gdpr-compliance | Blocks a request without the consent header when consent_required is set | All |
audit-logger | Adds an allow-only audit marker to the decision | All |
Input and output phase controls
These controls examine request fields or tool data. Some also check responses. A stage override does not add support for a response format that the control does not read.
| Control | What it does | Families |
|---|---|---|
agent-firewall | Allows or denies tool use and enforces action and transaction limits | Tools |
embedding-detector | Compares text with references by word overlap or configured embeddings | All |
external-moderation | Sends content to a third-party moderation service | Text |
content-extractor | Fetches content from URLs in request messages, within host and size limits | Text |
document-analyzer | Examines documents in the request JSON | Text |
code-sanitizer | Matches message text against built-in and custom code-safety patterns | Text |
tool-validation | Validates declared tool names and schema syntax, but not generated arguments | Tools |
tool-security | Blocks unsafe tool definitions in the request | Tools |
tool-budget | Blocks a request when max_tokens is more than a tool limit | Tools |
Output phase controls
These controls examine the complete response. Send requests with stream: false.
| Control | What it does | Families |
|---|---|---|
quality-scorer | Scores output quality and blocks or replaces output below the threshold | Text |
human-oversight | Returns an escalated result instead of the assistant content | Text |
flagged-review | Reviews each response with a model, or escalates it without one | Text |
citation-verifier | Checks that the request context supports the citations in the output | Text |
mnpi-filter | Blocks output that contains configured MNPI phrases | Text |
financial-compliance | Applies finance-oriented output controls | Text |
healthcare-compliance | Enforces medical blocked patterns and disclaimers | Text |
legal-privilege | Blocks output that contains privilege markers | Text |
upl-filter | Matches legal-advice phrases and adds a disclaimer or blocks the response | Text |
bias-monitor | Escalates when the HR bias score reaches the threshold | Text |
response-rewriter | Applies deterministic text rules to the response | Text |
Reporting-only controls
eu-ai-act exists for compliance reports only. Lint accepts it in policies.chain, but the gateway then blocks every request with reason code policy.reporting_only. Put its settings in policy.eu-ai-act and generate the report with POST /verdictan/compliance/report.
How the chain selects controls
policies.chain decides which controls run. policy.<kind> only holds their settings. A settings block without a chain entry does nothing:
policies:
chain:
- prompt-injection
policy:
prompt-injection: {}A route chain, a when condition, or targeting can also include or remove a control for a request. The output phase controls ignore when, so use routes for them. See Conditional Chain Configuration.
When a control returns block or escalate, the rest of that phase does not run. Put audit-logger first if blocked requests must also have its marker.
Lint checks structure. It does not prove that a control runs for live traffic. The active chain, route, conditions, and gateway version decide that.
Starter configurations
Save one of these as policy-config.yaml in a new test directory. Each passes verdictan policy lint. Add your provider settings before you send live requests.
PII redaction with audit logging
pack:
name: pii-redaction
version: "1.0.0"
enabled: true
policies:
chain:
- audit-logger
- pii-detector
policy:
pii-detector:
action: redact
redaction:
marker_format: label
include_metadata: true
audit-logger: {}Prompt-injection protection
pack:
name: prompt-injection-protection
version: "1.0.0"
enabled: true
policies:
chain:
- audit-logger
- prompt-injection
policy:
prompt-injection:
attack_patterns:
- "ignore.*previous.*instructions"
- "forget.*system.*prompt"
encoding:
decode_base64: true
normalize_unicode: true
detect_homoglyphs: true
boundaries:
enforce_delimiters: true
reject_fake_boundaries: true
audit-logger: {}Agent firewall with role-based tool access
pack:
name: agent-tool-access
version: "1.0.0"
enabled: true
policies:
chain:
- audit-logger
- agent-firewall
- rbac
policy:
agent-firewall:
tools:
roles:
analyst:
allowed:
- search
- summarize
denied:
- execute_code
- shell_command
rbac:
require_auth: true
roles:
analyst:
allowed_tools:
- search
- summarize
denied_tools:
- execute_code
- shell_command
audit-logger: {}Both controls read the role from the authenticated policy identity. They do not trust a role header that the caller sends.
Healthcare redaction stack
pack:
name: healthcare-redaction
version: "1.0.0"
enabled: true
providers:
targets:
- id: healthcare-provider
provider: openai
model: <model>
secret_key_ref:
env: VERDICTAN_OPENAI_API_KEY
data_policy:
zero_data_retention: true
training_opt_out: true
policies:
chain:
- audit-logger
- data-routing-policy
- pii-detector
- hipaa-phi-detector
- healthcare-compliance
policy:
data-routing-policy:
require_zero_data_retention: true
on_no_compliant_provider: block
pii-detector:
action: redact
healthcare_mode: true
pci_mode: false
redaction:
marker_format: label
include_metadata: true
hipaa-phi-detector:
action: redact
healthcare-compliance: {}
audit-logger: {}Replace <model> with a model ID from GET /v1/models on the gateway. A target with zero_data_retention: true must also set training_opt_out: true, or lint reports a contradiction.
Finance output controls
pack:
name: finance-output-controls
version: "1.0.0"
enabled: true
policies:
chain:
- audit-logger
- mnpi-filter
- financial-compliance
- quality-scorer
policy:
mnpi-filter:
detect_patterns:
- "earnings before announcement"
- "merger not public"
financial-compliance: {}
quality-scorer:
min_output_chars: 100
min_sentences: 2
audit-logger: {}Send requests through this stack with stream: false.
Validate a chain
-
Lint the file. A valid file exits with code
0:verdictan policy lint --file policy-config.yaml -
Add the offline test cases from the page of each control, and run
verdictan policy test --json. -
Apply the file to a test agent with the config-first workflow.
-
Send a usual request and a request that matches the control. Examine the nested policy results with
verdictan events tail --since 5m --json.
For redaction, check the forwarded or returned text. A redact verdict without replacement targets does not prove that sensitive content was removed.
Limits and failure behavior
- The gateway does not load a config with an unknown control in
policies.chainorpolicy.verdictan policy lintreportsunknown policy kindfirst. human-oversightsupports onlyaction: escalate. The gateway rejects removed fields such asrequire_human_forandtimeout_seconds.language-validatorchecks input text only.apply_to: outputdoes not add output enforcement.- Output controls read the buffered response. A streaming request through
flagged-reviewfails withstreaming.policy_cannot_enforce. gdpr-complianceandeu-ai-acthave no control page of their own. Compliance Policy Configuration describes them.- These controls do not make you compliant on their own. You still own legal review, operating processes, and provider governance.
Troubleshooting
| Problem | Likely cause | What to examine |
|---|---|---|
| The file lints but the control does not run | The chain does not include it, or a route, when, or targeting removes it | The applied global or route chain and the request context |
| A valid field has no effect | The schema accepts more fields than the runtime enforces | The supported fields on the page of the control |
| An output control works only for some clients | The response structure or the streaming mode is different | The request family, the stream value, and the supported response paths |
| A later result is missing | An earlier control stopped the phase | The chain order and the block or escalation reason code |
| Pack tests pass but live requests fail | The test runner does not simulate every gateway handler and transport | The same request through a test gateway and provider |
The decision reason code is ok after an allow | A nested allow reason does not replace the envelope reason | The policy_results array and the decision envelope |
Next steps
- Declarative Config Reference: the full schema of the chain and each section.
- Conditional Chain Configuration: run a control only for some paths, headers, or models.
- Test Configuration: write tests that show each verdict before rollout.