Docs · Policy DSL

Write policy in seconds, not hours.

AEGIS ships six grammar-constrained templates that cover the policy patterns guardrail products actually use. The AI generator produces these templates from a one-paragraph description + your tool inventory; the AJV validator self-tests them on the same shot.

The six templates

Each template compiles to a JSON Schema fragment applied to a tool call's arguments object.

  1. forbid_argument

    An argument MUST be absent or empty. Use for "no shell commands", "no raw SQL".

    { "kind": "forbid_argument", "field": "command" }
  2. require_pattern

    An argument MUST match a regex (allowlist).

    { "kind": "require_pattern", "field": "url",
      "pattern": "^https://api\\.example\\.com/" }
  3. forbid_pattern

    An argument MUST NOT match a regex (denylist).

    { "kind": "forbid_pattern", "field": "sql",
      "pattern": "DROP\\s+TABLE" }
  4. max_length

    String length cap. Use for prompt-injection caps.

    { "kind": "max_length", "field": "note", "max": 4096 }
  5. enum_values

    Argument MUST be one of a fixed set.

    { "kind": "enum_values", "field": "method",
      "allowed": ["GET", "HEAD"] }
  6. require_https

    Argument MUST be an HTTPS URL.

    { "kind": "require_https", "field": "callback" }

Composite policies (AND / OR)

Combine multiple templates against the same call:

{
  "all_of": true,
  "templates": [
    { "kind": "require_https", "field": "url" },
    { "kind": "enum_values", "field": "method", "allowed": ["GET", "HEAD"] },
    { "kind": "max_length", "field": "body", "max": 4096 }
  ]
}

Same-field templates fold into allOf (or anyOf if all_of=false).

DSL combinators (top-level)

Outside the template grammar, AEGIS exposes a small expression DSL for policies that key on classification / anomaly / agent identity:

{
  "when": {
    "all": [
      { "classifier.category": "shell" },
      { "anomaly.score": { ">": 0.7 } },
      { "agent.id": { "in": ["agent-x", "agent-y"] } }
    ]
  },
  "then": { "decision": "block", "reason": "shell + anomalous + risky agent" }
}

Comparators: == != > < >= <= in matches. Combinators: all any not.

AI policy generator

Don't want to write templates by hand? Run the generator with a description + tool inventory + (optional) workflow graph:

POST /api/ai/generate-policy-bundle
{
  "description": "Customer support copilot; never shell, never email outside our domain",
  "tool_inventory": [
    { "name": "shell" }, { "name": "send_email" }, { "name": "search_kb" }
  ],
  "workflow_graph": { /* from the scanner */ }
}

→ Returns: policies[] + DSL rules, each with should_block / should_allow tests AEGIS pre-runs through AJV.

Self-testing

Every generated (or hand-written) policy ships with a tests block:

{
  "id": "no-shell",
  "policy_schema": { ... },
  "tests": {
    "should_block": [
      { "tool": "shell", "arguments": { "command": "rm -rf /" } }
    ],
    "should_allow": [
      { "tool": "search_kb", "arguments": { "q": "refund policy" } }
    ]
  }
}

AEGIS compiles the schema, runs the tests, and rejects the policy if any assertion fails. No bad-actor-shaped policies ever land in production.

Counterfactual explainer

When a policy blocks a call, AEGIS computes the minimum edit that would have passed, re-runs the validator, and surfaces it in the audit:

{
  "decision": "block",
  "policy_name": "https-only",
  "counterfactual": {
    "any_suggestion": true,
    "suggestions": [{
      "description": "Change field \"url\" to a value matching ^https://",
      "proposed_arguments": { "url": "https://example.com/x" },
      "verified": true,
      "fix_kind": "pattern"
    }]
  }
}

Effectiveness scoring

Per-policy precision / recall / F1 over a rolling window. Cockpit surfaces a HEALTHY / TIGHTEN / RETIRE / PROBE signal so operators know which policies are noise vs catching real risk.

Next