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
| Field | Type | Required | Description | Validation |
|---|---|---|---|---|
name | string | Yes | Human-readable policy name | 1-255 characters, must be unique within a tier |
description | string | No | Explanation of what the policy detects | Max 1000 characters |
category | string | Yes | Policy category (see categories below) | Must be a valid category |
pattern | string | Yes | Regex pattern to match against input | Must be a valid Go-compatible regex |
action | string | Yes | Action taken when pattern matches | block, redact, warn, log, or require_approval |
severity | string | Yes | Severity level of the policy | critical, high, medium, or low |
enabled | boolean | No | Whether the policy is active | Defaults to true |
message | string | No | Message returned when policy triggers | Max 500 characters |
Read-Only Fields (returned in responses)
| Field | Type | Description |
|---|---|---|
id | string | Auto-generated unique identifier |
tier | string | Policy tier: system, organization, or tenant |
has_override | boolean | Whether an Enterprise override exists |
created_at | string | ISO 8601 creation timestamp |
updated_at | string | ISO 8601 last update timestamp |
Categories
The category field determines how the policy is classified. Use the category that best describes your policy's purpose:
| Category | Description | Example Use Case |
|---|---|---|
security-sqli | SQL injection detection | UNION SELECT, stacked queries, blind injection |
security-admin | Admin access control | Users table access, audit log access |
pii-global | Universal PII detection | Email, phone, credit card, passport |
pii-us | US-specific PII | SSN, bank account numbers |
pii-eu | EU-specific PII | IBAN |
pii-india | India-specific PII | PAN, Aadhaar (DPDP Act 2023) |
pii-singapore | Singapore-specific PII | NRIC, FIN, UEN |
code-secrets | Secret/credential patterns | AWS keys, API tokens, private keys |
code-unsafe | Unsafe code patterns | eval(), exec(), shell injection |
code-compliance | Code compliance patterns | License violations, deprecated APIs |
sensitive-data | General sensitive data | Financial 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:
| Action | Description | Effect on Request |
|---|---|---|
block | Immediately reject the request | Request returns an error with the policy message |
redact | Remove or mask sensitive content | Request proceeds with content filtered |
warn | Allow request but log a warning | Request proceeds; warning appears in policy evaluations |
log | Allow request and record a log entry | Request proceeds; match recorded for audit |
require_approval | Pause 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:
| Severity | Description | Typical Use |
|---|---|---|
critical | Highest severity, immediate attention required | SQL injection, credit card exposure, SSN detection |
high | Important security or compliance issue | Admin access patterns, sensitive table access |
medium | Moderate concern, should be reviewed | Email detection, IP address exposure |
low | Informational, for audit purposes | Booking references, general logging |
Pattern Syntax
The pattern field accepts Go-compatible regular expressions (RE2 syntax). Patterns are evaluated against query input text.
Pattern Examples
| Pattern | Description | Matches |
|---|---|---|
(?i)union\s+select | Case-insensitive UNION SELECT | UNION SELECT, union select |
\b\d{3}-\d{2}-\d{4}\b | SSN with dashes | 123-45-6789 |
\b[A-Z]{3}[PCHABGJLFT][A-Z]\d{4}[A-Z]\b | Indian PAN | ABCPD1234E |
(?i)\b(drop|truncate)\s+table\b | Destructive SQL | DROP TABLE, truncate table |
Pattern Tips
- Use
(?i)at the start for case-insensitive matching - Use
\bfor 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:
- System policies are evaluated first and provide the immutable baseline
- Organization policies (Enterprise only) are merged next
- 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
- Use descriptive names --
Block UNION SQL InjectionnotPolicy 1 - Add descriptions -- Explain why the policy exists and what it protects against
- Test patterns first -- Use
testPattern()orPOST /api/v1/static-policies/testbefore creating policies - Start with warn/log -- Deploy new policies as
warnorlog, then promote toblockafter monitoring - Use word boundaries --
\bprevents partial matches (e.g.,\bDROP\bwon't matchDROPDOWN) - Use case-insensitive flag --
(?i)at the start of patterns for SQL keywords and other case-varying inputs - One pattern per policy -- Simpler policies are easier to test, monitor, and disable independently
- Review regularly -- Audit custom policies quarterly for relevance and false positive rates
Related
- Policy Examples - Ready-to-use policy templates
- Policy Testing - Test and validate policies
- SDK Methods - Full API reference for policy CRUD
- System Policies - Complete list of 83 system policies
