Skip to main content

Policy Syntax

AxonFlow policies are defined as JSON objects and managed through the Static Policy API (/api/v1/static-policies). This page documents the policy field structure and validation rules.

Policy Structure

All AxonFlow static policies use this JSON format:

{
"name": "Block UNION SQL Injection",
"description": "Detect UNION-based SQL injection in prompts",
"category": "security",
"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, warn, or log
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
securitySecurity threat detectionSQL injection, command injection
complianceRegulatory compliance rulesGDPR, HIPAA, EU AI Act
sensitive-dataPII and sensitive data detectionSSN, credit cards, PAN
customBusiness-specific rulesInternal IP detection, competitor mentions

System policies use more specific sub-categories like security-sqli, security-admin, pii-global, pii-us, pii-eu, and pii-india. Custom tenant policies can use any of the four top-level 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
warnAllow request but log a warningRequest proceeds; warning appears in policy evaluations
logAllow request and record a log entryRequest proceeds; match recorded for audit

Action Hierarchy

Actions have a restrictiveness hierarchy: block > 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 (Agent, pattern-based) -- evaluated first, sub-5ms
  2. Organization policies (Enterprise only) -- merged next
  3. Tenant policies -- evaluated last

Within each tier, policies are evaluated by priority. The first matching block policy stops evaluation and rejects the request. warn and log policies are always evaluated and recorded.

Request → Agent evaluates system policies (pattern-based)
↓ (if not blocked)
→ Orchestrator evaluates tenant policies (condition-based)
↓ (if not blocked)
→ Request forwarded to LLM

Creating Policies

REST API

curl -X POST http://localhost:8080/api/v1/static-policies \
-H "Content-Type: application/json" \
-H "X-Org-ID: my-tenant" \
-d '{
"name": "Block Internal IPs",
"description": "Prevent exposure of internal IP addresses",
"category": "security",
"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",
"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, warn, log"
]
}

SDK

const policy = await client.createStaticPolicy({
name: 'Block Internal IPs',
description: 'Prevent exposure of internal IP addresses',
category: 'security',
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-pattern \
-H "Content-Type: application/json" \
-H "X-Org-ID: my-tenant" \
-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 the test-pattern API 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