Skip to main content

Managing Policies

This page is the complete reference for every policy field in AxonFlow and the two ways to manage policies: the customer portal and the policy CRUD API. Use it when you need to know exactly what a field means, whether you can change it, and how to create or edit a policy.

AxonFlow has two families of policies:

FamilyWhere it livesManaged in API asTypical use
System policies (also called static policies)The Agent/api/v1/static-policiesFast, pattern-based checks: PII detection, SQL-injection blocking, secret-leak detection
Tenant policies (also called dynamic policies)The Orchestrator/api/v1/dynamic-policiesContext-aware rules built from conditions and actions: risk, cost, user, content, and media governance

In the portal these appear as Static (read-only) and Dynamic (editable) sources. Both families share the same three-tier hierarchy — system, organization, and tenant — described in Policy Hierarchy.


Policy Field Reference

System (static) policy fields

System policies are pattern-based rules returned by /api/v1/static-policies. The table below lists every field, whether you can set it, and what it controls.

FieldTypeSettable?MeaningValid values
namestringSettableHuman-readable policy nameRequired on create; up to 255 characters
descriptionstringSettablePlain-English explanation of what the policy detects and why it existsOptional free text
categorystringSettableClassification that groups the policy (see Policy Syntax → Categories)Required on create, e.g. security-sqli, pii-global, pii-us, code-secrets, sensitive-data
patternstringSettableRegular expression matched against request contentRequired on create; Go (RE2) regular expression
actionstringSettableWhat the Agent does when the pattern matchesblock, redact, warn, log, require_approval
severitystringSettableHow serious a match islow, medium, high, critical (default medium)
priorityintegerSettableEvaluation order — higher values are evaluated firstDefault 50 for system policies
enabledbooleanSettableWhether the policy is activetrue / false (default true)
tagsarray of stringsSettableFree-form labels for grouping (for example compliance:hipaa)Optional
tierstringSettable on create onlyWhich tier the policy belongs toorganization or tenantsystem is rejected by the API
organization_idstringSettable on create onlyOrganization scope for organization-tier policiesRequired when tier is organization
risk_levelstringSystem-managedRisk classification used by the session-override contract. Seeded from the policy's categorylow, medium, high, critical (default medium)
allow_overridebooleanSystem-managedWhether an administrator may relax this policy with a session override. Forced to false whenever risk_level is criticaltrue / false
idstring (UUID)Read-onlyInternal unique identifierAssigned by AxonFlow
policy_idstringRead-onlyStable string identifier (slug)Assigned by AxonFlow
tenant_idstringRead-onlyTenant the policy belongs toDerived from your credentials
versionintegerRead-onlyIncrements on every changeAssigned by AxonFlow
created_at / updated_atstring (ISO 8601)Read-onlyCreation and last-modified timestampsAssigned by AxonFlow
created_by / updated_bystringRead-onlyWho created or last changed the policyFrom the X-User-ID header
deleted_atstring (ISO 8601)Read-onlySet when a policy is soft-deletedAssigned by AxonFlow
metadataobjectRead-onlyStructured metadata attached by AxonFlowAssigned by AxonFlow

When you read system policies through /api/v1/static-policies/effective, each policy also carries override information so you can see what is actually enforced:

FieldTypeMeaning
has_overridebooleanWhether an override is in effect for this policy
override_actionstringThe action the override enforces in place of action
override_enabledbooleanThe enabled state the override enforces in place of enabled
override_expires_atstring (ISO 8601)When a temporary override reverts
override_reasonstringWhy the override was created

When has_override is true, the override's override_action and override_enabled are what the Agent enforces; otherwise the policy's own action and enabled apply. (The customer portal's unified policy view surfaces the same result as effective_action and effective_enabled fields.)

System policies are read-only

You cannot create, modify, or delete system-tier policies through the API or the portal. They are maintained centrally and form your immutable security baseline. To change how a system policy behaves, create an override (Enterprise) — see Overriding system policies. The full catalog is documented in System Policies Reference.

Tenant (dynamic) policy fields

Tenant policies are condition-and-action rules returned by /api/v1/dynamic-policies. These are the policies you author yourself.

FieldTypeSettable?MeaningValid values
namestringSettableHuman-readable policy nameRequired; 3–100 characters
descriptionstringSettablePlain-English explanation of the ruleOptional; up to 500 characters
typestringSettableThe kind of policy, which determines the icon and grouping in the portalRequired; one of content, user, risk, cost, context_aware, media, rate-limit, budget, time-access, role-access, mcp, connector
categorystringSettableClassification for filtering and reportingRequired on the /api/v1/dynamic-policies endpoint; must start with dynamic- (for example dynamic-risk, dynamic-compliance) or media- (for example media-pii, media-safety)
conditionsarraySettableThe rules that decide whether the policy matches (see Conditions)Required; at least one condition
actionsarraySettableWhat happens when all conditions match (see Actions)Required; at least one action
priorityintegerSettableEvaluation order — higher values are evaluated first01000
enabledbooleanSettableWhether the policy is activetrue / false
tagsarray of stringsSettableFree-form labels for groupingOptional
tierstringSettable on create onlyWhich tier the policy belongs toorganization or tenantsystem is rejected by the API
idstring (UUID)Read-onlyInternal unique identifierAssigned by AxonFlow
tenant_idstringRead-onlyTenant the policy belongs toDerived from your credentials
organization_idstringRead-only (set from tier scope)Organization scope for organization-tier policiesAssigned by AxonFlow
versionintegerRead-onlyIncrements on every changeAssigned by AxonFlow
created_at / updated_atstring (ISO 8601)Read-onlyCreation and last-modified timestampsAssigned by AxonFlow
created_by / updated_bystringRead-onlyWho created or last changed the policyFrom the X-User-ID header
deleted_atstring (ISO 8601)Read-onlySet when a policy is soft-deletedAssigned by AxonFlow

Conditions

A condition is an object with three keys. All conditions in a policy must match for the policy to trigger.

{ "field": "risk_score", "operator": "greater_than", "value": 0.8 }
KeyMeaning
fieldThe request attribute to inspect
operatorHow to compare the field to value
valueThe value (or list of values) to compare against

Supported field values:

query, response, user.email, user.role, user.department, user.tenant_id, risk_score, request_type, connector, cost_estimate, the media-governance fields (media.has_faces, media.face_count, media.has_biometric_data, media.nsfw_score, media.violence_score, media.content_safe, media.document_type, media.is_sensitive_document, media.has_pii, media.pii_types, media.has_extracted_text, media.extracted_text_length), and the retry-aware workflow fields (step.gate_count, step.completion_count, step.prior_completion_status, step.prior_output_available, step.last_decision, step.first_attempt_age_seconds, step.idempotency_key).

Retry-aware fields require Evaluation or Enterprise

Policies that reference any step.* field require an Evaluation or Enterprise license. Creating, updating, or importing such a policy on the Community edition returns a tier error.

Supported operator values:

equals, not_equals, contains, not_contains, contains_any, regex, greater_than, less_than, in, not_in.

Actions

An action is an object with a type and an optional config:

{ "type": "redact", "config": { "fields": ["ssn", "salary"] } }

The canonical action vocabulary accepted by the policy API is:

typeWhat it doesTypical config
blockReject the request{ "reason": "…" }
redactMask the listed fields in the response{ "fields": ["field1", "field2"] }
require_approvalPause for human approval (HITL)
warnAllow the request but record a warning
logAllow the request and record an audit entry
alertSend an alert to your monitoring systemVaries by alerting integration
routeApply an LLM routing ruleVaries by routing rule
modify_riskAdjust the computed risk score{ "modifier": 1.5 }

allow is the implicit default when no policy matches; it is not something you set as an action type.

How risk is expressed

A common point of confusion is how "risk" maps to fields. AxonFlow models risk in three distinct ways, and none of them is a free-form numeric field you set on a policy:

  • risk_score is a request attribute computed at evaluation time (a value from 0.0 to 1.0). You reference it in a condition, for example { "field": "risk_score", "operator": "greater_than", "value": 0.8 }.
  • modify_risk is an action that nudges that computed score up or down for downstream policies.
  • risk_level is a system-assigned classification (low / medium / high / critical) on system policies that drives the session-override contract. It is not settable through the API.

The risk-scored example below shows the condition-based pattern in practice.


Managing policies in the portal

The Policies page in the customer portal gives you a single view of every system and tenant policy. (In an in-VPC deployment the page is titled Platform Policies and changes apply across all tenants.)

The summary and the list

At the top, four cards summarize your policies: Total Policies, Static (read-only), Dynamic (editable), and Enabled. Below them, each policy row shows:

  • the policy name and a version badge (for example v3);
  • a 🔒 lock icon when the policy is read-only (system-managed);
  • a source badge (Static or Dynamic) and a tier badge (System, Organization, or Tenant);
  • for system policies, the category and severity badges plus a preview of the regex pattern;
  • for tenant policies, the type badge and the priority;
  • an Overridden badge when an override is active, and a Disabled badge when the policy is off;
  • the description and the last-updated time.

Filtering

Use the filter bar to narrow the list by Source (All / Static / Dynamic), Tier (System / Organization / Tenant), Status (Enabled / Disabled), and — depending on the source — Type (for dynamic policies) or Category (for static policies).

What you can edit

ActionSystem (static) policiesTenant (dynamic) policies
CreateNot available (system-managed)Create Policy button
EditNot availableEdit button (name, description, type, conditions, actions, priority)
Enable / DisableNot availableEnable / Disable button
DeleteNot availableDelete button (with confirmation)
TestNot availableTest button
Preview ImpactNot availablePreview Impact button
Version historyNot availableHistory button
OverrideOverride / Remove Override (Enterprise)Not applicable

System policies show a System managed label instead of edit controls.

Creating or editing a tenant policy

  1. Click Create Policy (or Edit on an existing tenant policy).
  2. Give the policy a name and an optional plain-English description.
  3. Choose a type (content, user, risk, cost, …) and set a priority.
  4. Add one or more conditions (field, operator, value) and one or more actions (block, redact, require approval, …).
  5. Save. The policy takes effect within seconds.

Testing and previewing

  • Test runs the policy against a sample query and tells you whether it matched, whether the request would be blocked, which actions would fire, and the evaluation time.
  • Preview Impact estimates how the policy would affect recent traffic before you enable it.
  • Simulate Policies (top of the page) runs a what-if evaluation across your policy set.

Overriding system policies

Because system policies are read-only, Enterprise customers change their behavior with an override rather than an edit:

  1. Click Override on a system policy.
  2. Optionally choose an Action Override (you can only make a policy more restrictive, or disable it) and/or an Enabled Override.
  3. Enter a required Override Reason for the audit trail, and optionally an Expiration Date for a temporary override.
  4. Save. The policy now shows an Overridden badge and its effective action. Use Remove Override to revert.

Import and export

Export downloads your tenant policies as JSON. Import uploads a JSON file and lets you choose how to handle duplicates (skip, overwrite, or error). Up to 100 policies can be imported at once.


Managing policies via the API

Authentication and base URL

Policy endpoints are exposed by the Agent (default port 8080) and authenticated with your client credentials:

Authorization: Basic <base64(CLIENT_ID:CLIENT_SECRET)>

Your tenant is derived from those credentials. On mutating requests, add X-User-ID so changes are attributed in the audit trail.

Endpoints

Tenant (dynamic) policies — author your own condition-and-action rules:

MethodPathPurpose
GET/api/v1/dynamic-policiesList policies
POST/api/v1/dynamic-policiesCreate a policy
GET/api/v1/dynamic-policies/{id}Get one policy
PUT/api/v1/dynamic-policies/{id}Update a policy
DELETE/api/v1/dynamic-policies/{id}Delete a policy (soft delete)
POST/api/v1/dynamic-policies/{id}/testTest a policy against sample input
GET/api/v1/dynamic-policies/{id}/versionsList version history
POST/api/v1/dynamic-policies/importBulk import
GET/api/v1/dynamic-policies/exportBulk export
GET/api/v1/dynamic-policies/effectiveEffective policies for the tenant

System (static) policies — read the baseline, manage your own custom pattern rules:

MethodPathPurpose
GET/api/v1/static-policiesList policies
POST/api/v1/static-policiesCreate a custom pattern policy
GET/api/v1/static-policies/{id}Get one policy
PUT/api/v1/static-policies/{id}Update a non-system policy
DELETE/api/v1/static-policies/{id}Delete a non-system policy
PATCH/api/v1/static-policies/{id}Toggle enabled
POST/api/v1/static-policies/testTest a regex pattern against inputs
GET/api/v1/static-policies/effectiveEffective policies with overrides applied

See Tenant Policy API and System Policy API for the full wire reference. The settable-vs-read-only split is exactly as listed in the field reference above.

Example 1: a custom PII policy

Create a tenant policy that redacts sensitive fields whenever a request mentions them. This is a content policy in the dynamic-compliance category that fires a redact action.

curl -X POST http://localhost:8080/api/v1/dynamic-policies \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-H "X-User-ID: [email protected]" \
-d '{
"name": "Redact customer PII",
"description": "Mask SSN, salary, and medical record fields in responses",
"type": "content",
"category": "dynamic-compliance",
"priority": 900,
"enabled": true,
"conditions": [
{ "field": "query", "operator": "contains_any", "value": ["ssn", "salary", "medical_record"] }
],
"actions": [
{ "type": "redact", "config": { "fields": ["ssn", "salary", "medical_record"] } }
]
}'

Response (201 Created):

{
"policy": {
"id": "6f1c2e8a-9b3d-4f7a-8c21-2d4e6a8b0c11",
"name": "Redact customer PII",
"description": "Mask SSN, salary, and medical record fields in responses",
"type": "content",
"category": "dynamic-compliance",
"tier": "tenant",
"priority": 900,
"enabled": true,
"version": 1,
"conditions": [
{ "field": "query", "operator": "contains_any", "value": ["ssn", "salary", "medical_record"] }
],
"actions": [
{ "type": "redact", "config": { "fields": ["ssn", "salary", "medical_record"] } }
],
"created_at": "2026-06-12T10:00:00Z",
"updated_at": "2026-06-12T10:00:00Z"
}
}

List it back, filtering by category:

curl "http://localhost:8080/api/v1/dynamic-policies?category=dynamic-compliance" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)"

Test it against a sample query before relying on it:

curl -X POST http://localhost:8080/api/v1/dynamic-policies/6f1c2e8a-9b3d-4f7a-8c21-2d4e6a8b0c11/test \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-d '{ "query": "Show me the salary for employee 42" }'
{
"matched": true,
"blocked": false,
"actions": [
{ "type": "redact", "config": { "fields": ["ssn", "salary", "medical_record"] } }
],
"explanation": "Policy 'Redact customer PII' matched: all 1 conditions evaluated to true",
"eval_time_ms": 0.21
}

To make the rule stricter later, update it (only the fields you send change):

curl -X PUT http://localhost:8080/api/v1/dynamic-policies/6f1c2e8a-9b3d-4f7a-8c21-2d4e6a8b0c11 \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-H "X-User-ID: [email protected]" \
-d '{ "priority": 950 }'

And remove it when it is no longer needed:

curl -X DELETE http://localhost:8080/api/v1/dynamic-policies/6f1c2e8a-9b3d-4f7a-8c21-2d4e6a8b0c11 \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-H "X-User-ID: [email protected]"

A successful delete returns 204 No Content.

Example 2: a risk-scored block policy

Block any request whose computed risk score exceeds a threshold. This is a risk policy that reads the risk_score request attribute in a condition and fires a block action.

curl -X POST http://localhost:8080/api/v1/dynamic-policies \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-H "X-User-ID: [email protected]" \
-d '{
"name": "Block high-risk queries",
"description": "Reject requests whose risk score exceeds the safety threshold",
"type": "risk",
"category": "dynamic-risk",
"priority": 1000,
"enabled": true,
"conditions": [
{ "field": "risk_score", "operator": "greater_than", "value": 0.8 }
],
"actions": [
{ "type": "block", "config": { "reason": "Query risk score exceeds safety threshold" } }
]
}'

The policy matches when the request's risk_score is above 0.8 and blocks it. You can combine the risk condition with others — for example, only block high-risk requests from a specific role by adding { "field": "user.role", "operator": "equals", "value": "contractor" } to the conditions array (remember: all conditions must match).

Validation and errors

Validation failures return 400 with a VALIDATION_ERROR code and per-field details:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "name", "message": "Name must be between 3 and 100 characters" },
{ "field": "actions[0]", "message": "invalid action type: deny" }
]
}
}

Common rules to keep in mind:

  • name is required (3–100 characters); description is capped at 500 characters.
  • type must be one of the values in the field reference.
  • At least one condition and one action are required; priority must be 01000.
  • Each action type must be in the canonical action vocabulary.
  • Attempting to create a system-tier policy returns 403 (System policies cannot be created via API).

Editions and limits

  • System-tier policies are immutable on every edition — you override them (Enterprise) rather than edit them.
  • Organization-tier policies require an Evaluation or Enterprise license.
  • Tenant-tier policies are available on every edition; Community and Evaluation have a per-tenant policy-count limit, while paid editions are unlimited. Exceeding a limit returns a tier error with an upgrade link.

Compare what each edition unlocks in Community vs Evaluation vs Enterprise.