Skip to main content

Policy Syntax

AxonFlow system policies and tenant policies are defined as JSON objects and managed through the Static Policy API (/api/v1/static-policies). This page documents the policy field structure, category model, and validation rules engineers need when they build governed AI applications around prompt inspection, MCP access, code-generation controls, and regulated data handling.

Policy Structure

The same schema is used for built-in system policies in API responses and for custom tenant or organization policies you create yourself:

{
"name": "Block UNION SQL Injection",
"description": "Detect UNION-based SQL injection in prompts",
"category": "security-sqli",
"pattern": "(?i)union\\s+select",
"action": "block",
"severity": "critical",
"enabled": true,
"message": "Potential SQL injection detected."
}

Policy Fields Reference

FieldTypeRequiredDescriptionValidation
namestringYesHuman-readable policy name1-255 characters, must be unique within a tier
descriptionstringNoExplanation of what the policy detectsMax 1000 characters
categorystringYesPolicy category (see categories below)Must be a valid category
patternstringYesRegex pattern to match against inputMust be a valid Go-compatible regex
actionstringYesAction taken when pattern matchesblock, redact, warn, log, or require_approval
severitystringYesSeverity level of the policycritical, high, medium, or low
enabledbooleanNoWhether the policy is activeDefaults to true
messagestringNoMessage returned when policy triggersMax 500 characters

Read-Only Fields (returned in responses)

FieldTypeDescription
idstringAuto-generated unique identifier
tierstringPolicy tier: system, organization, or tenant
has_overridebooleanWhether an Enterprise override exists
created_atstringISO 8601 creation timestamp
updated_atstringISO 8601 last update timestamp

Categories

The category field determines how the policy is classified. Use the category that best describes your policy's purpose:

CategoryDescriptionExample Use Case
security-sqliSQL injection detectionUNION SELECT, stacked queries, blind injection
security-adminAdmin access controlUsers table access, audit log access
pii-globalUniversal PII detectionEmail, phone, credit card, passport
pii-usUS-specific PIISSN, bank account numbers
pii-euEU-specific PIIIBAN
pii-indiaIndia-specific PIIPAN, Aadhaar (DPDP Act 2023)
pii-singaporeSingapore-specific PIINRIC, FIN, UEN
code-secretsSecret/credential patternsAWS keys, API tokens, private keys
code-unsafeUnsafe code patternseval(), exec(), shell injection
code-complianceCode compliance patternsLicense violations, deprecated APIs
sensitive-dataGeneral sensitive dataFinancial data, internal IPs

Custom tenant policies can use any of the categories above.

Actions

The action field determines what happens when a policy pattern matches:

ActionDescriptionEffect on Request
blockImmediately reject the requestRequest returns an error with the policy message
redactRemove or mask sensitive contentRequest proceeds with content filtered
warnAllow request but log a warningRequest proceeds; warning appears in policy evaluations
logAllow request and record a log entryRequest proceeds; match recorded for audit
require_approvalPause for human approval (HITL)Request queued for approval (Enterprise)

Action Hierarchy

Actions have a restrictiveness hierarchy: block > require_approval > redact > warn > log

When overriding system policies (Enterprise only), you can only make policies more restrictive or disable them. You cannot downgrade a block policy to warn or log.

Severities

The severity field indicates the importance of a policy match:

SeverityDescriptionTypical Use
criticalHighest severity, immediate attention requiredSQL injection, credit card exposure, SSN detection
highImportant security or compliance issueAdmin access patterns, sensitive table access
mediumModerate concern, should be reviewedEmail detection, IP address exposure
lowInformational, for audit purposesBooking references, general logging

Pattern Syntax

The pattern field accepts Go-compatible regular expressions (RE2 syntax). Patterns are evaluated against query input text.

Pattern Examples

PatternDescriptionMatches
(?i)union\s+selectCase-insensitive UNION SELECTUNION SELECT, union select
\b\d{3}-\d{2}-\d{4}\bSSN with dashes123-45-6789
\b[A-Z]{3}[PCHABGJLFT][A-Z]\d{4}[A-Z]\bIndian PANABCPD1234E
(?i)\b(drop|truncate)\s+table\bDestructive SQLDROP TABLE, truncate table

Pattern Tips

  • Use (?i) at the start for case-insensitive matching
  • Use \b for word boundaries to reduce false positives
  • Use non-capturing groups (?:...) when you don't need capture groups
  • Avoid catastrophic backtracking (nested quantifiers like (a+)+)
  • Test patterns with the SDK's testPattern() method before deploying

Evaluation Order

Policies are evaluated in tier order, with system policies evaluated first:

  1. System policies are evaluated first and provide the immutable baseline
  2. Organization policies (Enterprise only) are merged next
  3. Tenant policies are merged last for team-specific behavior

Within each tier, policies are evaluated by priority. The effective result is based on the merged policy set returned by the static-policy APIs, with more restrictive actions taking precedence when multiple matches apply.

Request → Agent evaluates system + custom static policies
↓ (if allowed)
→ Orchestrator evaluates tenant policies and workflow context
↓ (if allowed)
→ Request forwarded to LLM or workflow step

Creating Policies

REST API

curl -X POST http://localhost:8080/api/v1/static-policies \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-d '{
"name": "Block Internal IPs",
"description": "Prevent exposure of internal IP addresses",
"category": "security-admin",
"pattern": "\\b10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b",
"action": "block",
"severity": "medium",
"enabled": true,
"message": "Internal IP address detected."
}'

Successful Response (201):

{
"id": "pol_abc123",
"name": "Block Internal IPs",
"description": "Prevent exposure of internal IP addresses",
"tier": "tenant",
"category": "security-admin",
"pattern": "\\b10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b",
"action": "block",
"severity": "medium",
"enabled": true,
"message": "Internal IP address detected.",
"created_at": "2026-02-07T12:00:00Z",
"updated_at": "2026-02-07T12:00:00Z"
}

Validation Error Response (400):

{
"error": "validation_error",
"details": [
"pattern: invalid regex syntax",
"action: must be one of block, redact, warn, log, require_approval"
]
}

SDK

const policy = await client.createStaticPolicy({
name: 'Block Internal IPs',
description: 'Prevent exposure of internal IP addresses',
category: 'security-admin',
pattern: '\\b10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b',
action: 'block',
severity: 'medium',
enabled: true,
});

Testing Patterns

Validate a regex pattern against test inputs before creating a policy:

curl -X POST http://localhost:8080/api/v1/static-policies/test \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-d '{
"pattern": "\\b10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b",
"inputs": [
"Server at 10.0.1.5 is down",
"No internal IPs here",
"Multiple: 10.1.2.3 and 10.4.5.6"
]
}'
{
"pattern": "\\b10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b",
"matches": [
{ "input": "Server at 10.0.1.5 is down", "matched": true, "matchedText": "10.0.1.5" },
{ "input": "No internal IPs here", "matched": false },
{ "input": "Multiple: 10.1.2.3 and 10.4.5.6", "matched": true, "matchedText": "10.1.2.3" }
]
}

Best Practices

  1. Use descriptive names -- Block UNION SQL Injection not Policy 1
  2. Add descriptions -- Explain why the policy exists and what it protects against
  3. Test patterns first -- Use testPattern() or POST /api/v1/static-policies/test before creating policies
  4. Start with warn/log -- Deploy new policies as warn or log, then promote to block after monitoring
  5. Use word boundaries -- \b prevents partial matches (e.g., \bDROP\b won't match DROPDOWN)
  6. Use case-insensitive flag -- (?i) at the start of patterns for SQL keywords and other case-varying inputs
  7. One pattern per policy -- Simpler policies are easier to test, monitor, and disable independently
  8. Review regularly -- Audit custom policies quarterly for relevance and false positive rates