Skip to main content

Policy Parameters Explained

Policy Syntax and Managing Policies list every policy field and its valid values. This page answers the next question: what does each parameter actually do, and when should you change it?

It is built around the two parameters users find most confusing:

  • Severity is not "how strict." It does not block anything by itself. It influences a category's default action, the depth of redaction masking, and the risk label attached to a match.
  • Priority is not a tier or a strength dial. It is pure relative ordering: a higher number is evaluated first. The absolute value (200 vs 600) only matters when two policies overlap.

Every behavior described here is grounded in the enforcement engine. Use this page to tune policies; use Managing Policies for the create, edit, and API mechanics.


How to read this page

Each parameter below is documented as:

  • What it does -- the behavior the engine actually applies.
  • When to change it -- the situations where the default is wrong for you.
  • Worked example -- a minimal policy that exercises the parameter.

Two families of policies use these parameters, and a few parameters apply to only one family:

ParameterSystem (static) policiesTenant (dynamic) policies
category / typecategorytype (+ category for filtering)
severityYesNo (dynamic policies act through actions)
priorityYes (default 50)Yes (default 100, range 0-1000)
phaseYes (request / response / both)No (dynamic policies are evaluated per request)
action / actionssingle actionactions array
conditionsNo (uses pattern)Yes
enabledYesYes
tierYesYes

Category and type

What it does

The category of a system policy (and the type of a tenant policy) is more than a label. For system policies, the category drives the redaction strategy (see the severity table) and whether a critical-severity match defaults to a block. For tenant policies, the type selects how the policy is evaluated -- a rate-limit policy is evaluated against a request counter, a time-access policy against the clock, and so on.

The system-policy categories are listed in Policy Syntax. The tenant-policy types are: content, user, risk, cost, context_aware, media, rate-limit, budget, time-access, role-access, mcp, and connector.

When to change it

  • Pick the category that matches the data class you are protecting, because the category, not the severity, decides how a match is masked. A pii-us match is masked differently from a sensitive-data match at the same severity.
  • Pick the type that matches the control you want. The four access-control types (rate-limit, budget, time-access, role-access) have dedicated worked examples below.

Severity

severity is one of low, medium, high, or critical, and it applies to system (static) policies. It defaults to medium.

What it does

Severity never blocks a request on its own. The action field is what blocks, redacts, warns, or logs. Severity influences three downstream behaviors:

  1. Default action for security categories. When a system policy has no explicit action set for the phase being evaluated, the engine falls back to a category default. For the SQL-injection and dangerous-query security categories, a critical severity falls back to block; PII categories fall back to redact; admin-access falls back to warn; everything else falls back to log. This fallback only applies when the explicit action is empty -- an action you set always wins.
  2. Redaction depth. When a policy redacts, severity (together with category) selects how aggressively the matched text is masked. See the severity-to-redaction-depth table.
  3. Risk classification. When a match escalates to a human-in-the-loop approval, severity maps to an EU AI Act risk label: critical and high map to high-risk, medium to limited-risk, and low to minimal-risk.

Severity is not a restrictiveness ranking. A low-severity policy with action: block blocks; a critical-severity policy with action: log only logs. Always set action to the behavior you want, and use severity to tune masking depth and risk labeling.

When to change it

  • Raise to critical when you want the strongest masking for a PII or security policy, or when you want a security-category policy to default to block in the fallback case.
  • Lower to medium or low for global-PII policies where partial masking (keeping more of the value visible) is acceptable.
  • Set it to match the risk label you want surfaced in audit and HITL records.

Severity to redaction depth

When a system policy's action is redact, the engine chooses a masking strategy from the policy's category and severity. The strategies are:

  • Mask -- full masking: the value is replaced with asterisks, keeping only the first and last character as anchors (values of four characters or fewer are fully masked).
  • Partial -- light masking: the first two and last two characters stay visible.
  • Remove -- the match is replaced entirely with a [REDACTED:<type>] token.
CategorySeverityStrategyWhat the reader sees
Any PII categorycriticalMask (full)j••••••••e
pii-globalhighMask (full)j••••••••e
pii-globalmedium or lowPartialjo••••le
pii-us, pii-india, pii-eu, pii-singaporeanyMask (full)j••••••••e
Any other categorynon-criticalRemove[REDACTED:email]

Two consequences worth knowing:

  • For region-specific PII (pii-us, pii-india, pii-eu, pii-singapore), masking is full regardless of severity, so lowering the severity of those policies does not loosen masking.
  • A non-critical pii-indonesia policy is not in the full-mask set, so it uses Remove like other non-PII-region categories. Set it to critical if you want masking instead of removal.

Priority

priority is an integer. System policies default to 50; tenant policies default to 100 and are validated to the range 0-1000.

What it does

Priority is relative evaluation order, nothing more. Policies are evaluated highest-priority-first (ties broken by creation time). A larger number is not a higher tier or a stronger rule -- priority: 600 is simply evaluated before priority: 200. The absolute value carries no meaning on its own; it only matters when two policies could both apply to the same request.

When multiple policies match, the most restrictive action wins (see the action hierarchy). So priority changes the order policies are applied, not the winner of a block-vs-warn contest.

Priority matters in exactly two situations:

  • Redaction sequencing. When several redact policies match the same content, the higher-priority policy is evaluated first, so its redaction is collected ahead of lower-priority ones. This matters when you want one policy considered before another.
  • Override precedence. When overlapping rules could each take effect, the higher-priority policy is considered first.

It does not matter for a terminal block: a block is the most restrictive action, so it takes effect regardless of whether its priority number is high or low.

When to change it

  • Raise a redaction policy's priority when its masking must run before another redaction on the same field.
  • Leave priority at the default for an independent policy that does not overlap with any other rule. Picking 999 for a single block buys you nothing.
  • Do not use priority to express "importance." Use severity for that.

Priority ordering walkthrough

Suppose two tenant policies can both match a support transcript that contains an email address:

[
{
"name": "Mask emails (light)",
"type": "content",
"category": "dynamic-compliance",
"priority": 200,
"actions": [ { "type": "redact", "config": { "fields": ["email"] } } ]
},
{
"name": "Mask emails (strict, internal docs)",
"type": "content",
"category": "dynamic-compliance",
"priority": 600,
"actions": [ { "type": "redact", "config": { "fields": ["email"] } } ]
}
]

Because 600 > 200, the strict policy is evaluated first and its redaction is collected ahead of the light one. If you swap the numbers, the light policy is evaluated first. The evaluation order is the only thing the priority numbers change here -- both policies redact, so both contribute, but the sequence in which they are considered is set by priority.

Now add a block:

{
"name": "Block exfiltration attempts",
"type": "content",
"category": "dynamic-compliance",
"priority": 10,
"actions": [ { "type": "block", "config": { "reason": "Bulk export blocked" } } ]
}

Even at priority: 10 -- far below the redaction policies -- this block wins the moment it matches, because block is the most restrictive action. Its low priority does not weaken it. This is why priority is moot for a terminal block: the action hierarchy, not the number, decides the outcome.


Phase

phase applies to system (static) policies. It is one of request, response, or both, and defaults to both.

What it does

Phase controls when a system policy is evaluated: against the inbound request, against the outbound response, or both. A policy with phase: request inspects the user's prompt before it reaches the model; phase: response inspects the model's output before it returns to the user; both inspects each.

When to change it

  • Use request for input-side checks like SQL-injection or prompt-injection patterns that only make sense on the way in.
  • Use response for output-side checks like PII that the model might emit in its answer.
  • Use both (the default) when the same pattern is a concern in either direction.

Tenant (dynamic) policies do not have a phase field; they are evaluated per request and can inspect either the query or the response field through a condition.


Actions

The action (system policies) or actions array (tenant policies) is the parameter that actually changes what happens to a request.

What it does

For system policies, the valid actions are block, require_approval, redact, warn, and log. (allow is not a settable system action -- it is the implicit result when nothing matches.) Their meaning and restrictiveness ordering are documented in Policy Syntax → Actions.

For tenant policies, the action vocabulary additionally includes the dynamic-executor actions alert, route, and modify_risk on top of block, redact, warn, log, and require_approval. See Managing Policies → Actions for the full table.

When to change it

  • Start a new policy at warn or log, watch the match rate, then promote to redact or block once you trust it. This is the safest rollout path.
  • Use require_approval instead of block when a human should make the final call (Enterprise human-in-the-loop).
  • Use redact when the request should proceed with sensitive content masked rather than rejected.

Conditions and operators

Conditions apply to tenant (dynamic) policies. Each condition is a { field, operator, value } object, and all conditions in a policy must match for it to trigger.

What it does

A condition inspects one request attribute and compares it to a value. The supported operators are equals, not_equals, contains, not_contains, contains_any, regex, greater_than, less_than, in, and not_in. The supported fields include query, response, user.email, user.role, user.department, user.tenant_id, risk_score, request_type, connector, cost_estimate, the media.* governance fields, and the step.* retry-aware fields. The full lists are in Managing Policies → Conditions.

When to change it

  • Add conditions to narrow a policy. A single risk_score > 0.8 condition fires broadly; adding user.role equals contractor scopes it to one role (remember: all conditions must match, so adding conditions makes a policy stricter about when it fires).
  • Use greater_than / less_than for numeric attributes (risk_score, cost_estimate), contains_any / in for set membership, and regex for pattern matching inside query or response.

Risk thresholds are conditions, not a field

There is no settable risk_threshold parameter on the policy API. To gate on risk, write a condition against the computed risk_score attribute:

{ "field": "risk_score", "operator": "greater_than", "value": 0.8 }

risk_score is a value from 0.0 to 1.0 computed at evaluation time. The related modify_risk action nudges that score, and the system-managed risk_level classification (low / medium / high / critical) drives the session-override contract. See Managing Policies → How risk is expressed for the distinction between the three.


Enabled and tier

Enabled

enabled (default true) is the on/off switch. Disabling a policy keeps its definition and version history but stops it from being evaluated. Disable a policy to pause it during an incident or while tuning, rather than deleting and re-creating it.

Tier

tier is one of system, organization, or tenant, and it sets the scope a policy applies to. system policies are the immutable baseline and cannot be created through the API; organization-tier policies require an Evaluation or Enterprise license; tenant-tier policies are available on every edition. The merge order (system first, then organization, then tenant) is described in Policy Hierarchy.


Access-control policy types

The rate-limit, budget, time-access, and role-access tenant-policy types are designed for governing MCP tool and connector access. Unlike a content policy, each reads its configuration from specially named conditions rather than a regex pattern. The worked examples below use the exact field names the evaluator consumes.

All four require a category that begins with dynamic- (the dynamic-policy category rule), and like every tenant policy they take a priority, enabled flag, and one or more actions.

Rate-limit

A rate-limit policy caps how many requests are allowed in a time window. The evaluator reads the limit from a condition whose field is requests_per_minute, requests_per_hour, or max_requests, and the window length from a window_seconds condition (the window defaults to 60 seconds).

{
"name": "Cap MCP tool calls per minute",
"type": "rate-limit",
"category": "dynamic-rate-limit",
"priority": 500,
"enabled": true,
"conditions": [
{ "field": "requests_per_minute", "operator": "less_than", "value": 60 }
],
"actions": [
{ "type": "block", "config": { "reason": "Rate limit exceeded" } }
]
}

This allows up to 60 requests per minute and blocks the rest. To use a custom window, replace the limit field with max_requests and add a window_seconds condition (for example, max_requests of 1000 with window_seconds of 3600 for an hourly cap).

When to change it: lower the limit for expensive or destructive tools, raise it for read-only ones.

Budget

A budget policy caps spend over a rolling period. The evaluator reads the cap from a max_budget (or budget_limit) condition, the period from a period_days condition (default 30), and a cost_per_request estimate (default 0.001).

{
"name": "Cap monthly MCP spend",
"type": "budget",
"category": "dynamic-budget",
"priority": 500,
"enabled": true,
"conditions": [
{ "field": "max_budget", "operator": "less_than", "value": 100.0 },
{ "field": "period_days", "operator": "equals", "value": 30 },
{ "field": "cost_per_request", "operator": "equals", "value": 0.002 }
],
"actions": [
{ "type": "block", "config": { "reason": "Monthly budget exhausted" } }
]
}

This caps spend at 100 units over 30 days, estimating 0.002 per request.

For full LLM budget management -- organization, team, agent, workflow, and user scopes, budget checks, and alerts -- use the dedicated budget system documented in Cost Management and the Cost Controls API. The budget policy type above is a lightweight per-request MCP-access guard, not a replacement for that system.

When to change it: set max_budget to the cap for the connector, and cost_per_request to a realistic per-call estimate so the counter tracks reality.

Time-access

A time-access policy restricts access to a business-hours window. The evaluator reads business_hours_start and business_hours_end conditions, anchored to a timezone condition.

{
"name": "Restrict connector to business hours",
"type": "time-access",
"category": "dynamic-time-access",
"priority": 500,
"enabled": true,
"conditions": [
{ "field": "timezone", "operator": "equals", "value": "America/New_York" },
{ "field": "business_hours_start", "operator": "equals", "value": 9 },
{ "field": "business_hours_end", "operator": "equals", "value": 17 }
],
"actions": [
{ "type": "require_approval", "config": { "reason": "Outside business hours" } }
]
}

This treats 09:00-17:00 in America/New_York as the allowed window and escalates out-of-hours access for approval.

When to change it: widen the window for global teams, narrow it for tightly controlled connectors, and set timezone to the team's working timezone so the window is anchored correctly.

Role-access

A role-access policy restricts a connector or tool to specific roles. The evaluator reads a single user.role condition; with the in operator it is an allow-list, with not_in a deny-list, and with equals an exact match. A "*" entry in an in list matches any role.

{
"name": "Restrict admin connector to privileged roles",
"type": "role-access",
"category": "dynamic-role-access",
"priority": 500,
"enabled": true,
"conditions": [
{ "field": "user.role", "operator": "in", "value": ["admin", "security-engineer"] }
],
"actions": [
{ "type": "block", "config": { "reason": "Role not permitted for this connector" } }
]
}

This permits only admin and security-engineer roles. Switch the operator to not_in to express a deny-list instead.

When to change it: maintain the role list as your team's access model changes; prefer an allow-list (in) for sensitive connectors so new roles are denied by default.