Skip to main content
A
Docs

Policy Engine

Define keyword and regex rules to govern AI content with configurable action escalation.

How the Policy Engine Works

The policy engine evaluates content against a set of active rules and determines what action to take. Each policy defines a rule type, a configuration, and an action. When content is submitted for evaluation, Guard checks it against every active policy, collects violations, and escalates to the highest-severity action.

Action Escalation

Actions follow a strict priority order. When multiple policies trigger on the same content, the most severe action wins:

PriorityActionBehavior
0passContent is allowed with no side effects
1logContent is allowed but the evaluation is logged to the audit trail
2warnContent is allowed but flagged with a warning in the response
3blockContent is rejected and the request is denied

If a keyword policy triggers warn and a regex policy triggers block on the same content, the final action is block.

Rule Types

Keyword Rules

Keyword rules match individual words or phrases in the content. English keywords use word-boundary matching (case-insensitive), while Arabic keywords use substring matching to handle the lack of consistent word boundaries in Arabic text.

{
  "name": "No Medical Advice",
  "rule_type": "keyword",
  "rule_config": "{\"keywords\": [\"diagnosis\", \"prescribe\", \"medication dosage\", \"تشخيص\", \"وصفة طبية\"]}",
  "action": "block"
}

Arabic keywords are matched using normalization that handles common orthographic variations:

  • Diacritics (tashkeel) are stripped
  • Alef variants are unified (hamza above/below, madda all become bare alef)
  • Taa marbuta is normalized to haa
  • Alef maksura is normalized to yaa
  • Tatweel (kashida) characters are removed

This means a keyword like "تشخيص" will match "التشخيص" and "تَشْخِيص" regardless of diacritical marks or prefixes.

Regex Rules

Regex rules match patterns using Python regular expressions with case-insensitive mode. They are useful for detecting structured data like phone numbers, ID formats, or specific syntactic patterns.

{
  "name": "No Personal Data in Responses",
  "rule_type": "regex",
  "rule_config": "{\"patterns\": [\"(?:\\\\+|00)(?:971|966|974|968)\\\\d{8,10}\", \"784[\\\\-\\\\s]?\\\\d{4}[\\\\-\\\\s]?\\\\d{7}[\\\\-\\\\s]?\\\\d\"]}",
  "action": "warn"
}

The first pattern matches GCC phone numbers (UAE, Saudi, Qatar, Oman country codes). The second matches UAE Emirates ID format (784-XXXX-XXXXXXX-X).

Creating a Policy

POST
/api/v1/policies

Create a new governance policy. Requires admin role.

curl -X POST http://localhost:8002/api/v1/policies \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Block Financial Advice",
    "description": "Prevent AI from providing specific financial recommendations",
    "rule_type": "keyword",
    "rule_config": "{\"keywords\": [\"investment advice\", \"buy stock\", \"sell stock\", \"نصيحة استثمارية\"]}",
    "action": "block",
    "is_active": true
  }'

Response:

{
  "id": "a1b2c3d4-...",
  "name": "Block Financial Advice",
  "description": "Prevent AI from providing specific financial recommendations",
  "rule_type": "keyword",
  "rule_config": "{\"keywords\": [\"investment advice\", \"buy stock\", \"sell stock\", \"نصيحة استثمارية\"]}",
  "action": "block",
  "is_active": true,
  "created_at": "2026-02-16T10:00:00Z",
  "updated_at": "2026-02-16T10:00:00Z"
}

Evaluating Content

POST
/api/v1/governance/evaluate

Evaluate content against all active policies.

The evaluation endpoint runs content through three layers: the policy engine, the content filter (bilingual toxicity + restricted topics), and the PII detector. The combined result includes all violations, detected PII, a content toxicity score, and the final escalated action.

curl -X POST http://localhost:8002/api/v1/governance/evaluate \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Please provide your Emirates ID number 784-1234-5678901-2",
    "context": "customer_chat"
  }'

Response:

{
  "allowed": true,
  "action": "warn",
  "violations": [
    {
      "policy_id": "...",
      "policy_name": "No Personal Data in Responses",
      "action": "warn",
      "reason": "Matched pattern: 784[\\-\\s]?\\d{4}[\\-\\s]?\\d{7}[\\-\\s]?\\d",
      "matched": ["784[\\-\\s]?\\d{4}[\\-\\s]?\\d{7}[\\-\\s]?\\d"]
    }
  ],
  "pii_detected": [
    {"type": "NATIONAL_ID", "value": "784-1234-5678901-2", "start": 36, "end": 54}
  ],
  "content_score": 0.0,
  "redacted_content": "Please provide your Emirates ID number [REDACTED_NATIONAL_ID]"
}

Content Score

The content_score field ranges from 0.0 to 1.0 and reflects toxicity/restricted-topic density. Content is flagged when the score reaches 0.3 or above. Each toxic keyword adds 0.15 (capped at 0.5) and each restricted topic adds 0.1 (capped at 0.4).

Content Filtering

The content filter runs alongside policy evaluation and checks for two categories of problematic content:

Toxic Keywords

15 English terms (kill, murder, attack, bomb, weapon, terrorist, hate, racist, sexist, slur, abuse, threat, suicide, self-harm, violence) and 24 Arabic terms covering violence, extremism, corruption, and fraud.

Arabic toxic keywords are matched with morphological variant generation, combining common prefixes ("ال") and suffixes ("ون", "ات", "ين", "ة", "ي") to catch inflected forms.

Restricted Topics

28 bilingual terms across sensitive categories:

  • Political: election, opposition, protest, revolution, coup (+ Arabic equivalents)
  • Medical: diagnosis, prescribe, medication dosage, treatment plan (+ Arabic)
  • Legal: legal advice, sue, lawsuit (+ Arabic)

Managing Policies

Policies support full CRUD operations. Only users with the admin role can create, update, or delete policies. All authenticated users can list and view policies.

GET
/api/v1/policies

List all policies with optional filtering.

GET
/api/v1/policies/{id}

Get a specific policy by ID.

PUT
/api/v1/policies/{id}

Update a policy. Requires admin role.

DELETE
/api/v1/policies/{id}

Delete a policy. Requires admin role.

Listing Policies

curl http://localhost:8002/api/v1/policies?active_only=true&limit=10 \
  -H "Authorization: Bearer $TOKEN"

Updating a Policy

curl -X PUT http://localhost:8002/api/v1/policies/$POLICY_ID \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "block",
    "is_active": true
  }'

Only the fields you include in the request body are updated. Omitted fields remain unchanged.