CirvixProducts / Policy Engine

Rules that run before the action, not after.

A policy is a JSON rule set, not a prompt and not a suggestion. It resolves deterministically, returns one verdict, and produces the evidence for why that verdict was reached. The engine is the enforcement core of AI agent security policy at runtime.

JSONrule format, not a DSL to learn
4verdicts, no ambiguous states
1.2mstarget evaluation latency
denydefault when no rule matches
Anatomy

What a rule
actually is.

Match on the agent, the org, and the action. Return a verdict. Everything else is optional.

policies / deny-dotenv.jsonJSON
{
  "name": "deny-dotenv-read",
  "effect": "forbid",
  "actions": ["fs.read"],
  "resources": ["**/.env", "**/.env.*"],
  "reason": "secrets are brokered, not read",
  "remediation": "Request the value as a handle: secrets.get(\"STRIPE_KEY\")"
}

// Glob matching is literal. A pattern never
// escapes the segment it was written for.
Verdicts

Four outcomes.
No fifth.

Every evaluation ends in exactly one of these. There is no partial pass and no implicit continue.

VerdictWhat happensRecorded
allowThe action proceeds with the tenant scope it was granted.Decision block written
denyThe action does not run. The caller receives the reason, not the payload.Decision block written
holdExecution pauses for a human decision. The request is preserved; the action is not started.Decision + resolution written
audit_onlyThe rule records what it observed and does not authorize anything. A separate rule must still allow the action.Observation written

audit_only never authorizes. If the only matching rule is audit_only, no rule has allowed the action, and the engine denies it. This is enforced in the evaluator, not left to policy authors.

Sequence

Three safe actions
that are not safe together.

Most engines judge one call at a time. Some failures only exist in the sequence, and judging calls individually cannot see them at all.

A

Private data was read

A credential, a .env, a customer record. Recorded with the call that did it and when.

B

Untrusted content was ingested

A fetched page, a tool result, an MCP response — anything from outside the trust boundary. Set either by injected instructions found in the result, or by provenance alone when nothing obvious was found.

C

An outbound action is proposed

A request, a write, a deploy. This leg is the call being judged, which is why the sequence can be refused before it completes rather than reported after.

Each one alone is ordinary work. An engine that refuses any of them refuses normal development. Together they are the shape of an exfiltration: something outside the boundary has had the opportunity to steer an agent that is holding secrets and is now talking outward.

cirvix why req_8a91SH
  LETHAL TRIFECTA  all three conditions met in this session

    1. sensitive data     Read secret-shaped material from ./.env
       2026-09-03T10:00:00.000Z
    2. untrusted content  A tool result contained 2 injected instructions
                          addressed to the model.
       2026-09-03T10:01:00.000Z
    3. outbound action    Sends data to evil.example
       2026-09-03T10:02:00.000Z

  Cirvix refuses on capability and opportunity. It does not claim the
  sensitive bytes are in this request — that needs data-flow analysis
  it deliberately does not do.

What this does not claim. Cirvix does not assert that the bytes read in step 1 are inside the request in step 3. Establishing that requires data-flow analysis, and every approximation of it that fits in a synchronous hot path is guesswork presented as proof. The refusal is on capability and opportunity, both of which are established, and the explanation says so rather than overstating.

Strictness follows blast radius. A completed trifecta denies in production and holds for a human everywhere else. The combination is common and benign while a developer is exploring, and a tool that refuses that outright gets uninstalled before it ever protects anything.

Consequence vs. Credential

Controlling the side effect,
not just the tool call.

A valid agent with a valid credential calling a legitimate MCP tool can still attempt an unauthorized real-world consequence. Cirvix evaluates the effective side effect at machine speed (<1.2ms design target) before releasing execution.

Consequence DimensionWhat the Agent AttemptsEvaluator BoundaryDefault Verdict
External State MutationWriting to public wikis, forums, external webhooks (e.g. unauthorized coordination channels)Evaluates destination against mission scope. Reading is allowed; public writing requires explicit grant.deny
Sub-Agent InheritanceSpawning worker sub-agents with escalated tool sets or broader filesystem accessMonotonic delegation bounds: child agents can never inherit wider authority than parent.deny
Cross-Resource BoundaryValid database client querying another tenant's schema or 169.254.169.254Structural glob and tenant scoping; literal segment matching prevents traversal.deny
Irreversible ConsequenceDeleting cloud infrastructure, dropping tables, sending external emailsHigh-impact side effects trigger approval hold, preserving exact state for human release.hold

Machine speed beats attack speed. While enterprise attacks assisted by AI agents compress attack timelines from weeks into under 10 hours, human security consoles arrive too late. Cirvix policy evaluation is designed to run inline inside a <1.2ms budget per decision (design target; measured runs with hardware context on benchmarks), terminating unauthorized side effects before the packet or write leaves the host.

Packs

Rule sets that carry
their own provenance.

A pack is one .policy file. The manifest rides on comment lines the parser already skips, so a pack cannot disagree with itself about what it contains.

PackPostureRulesFor
baselinebalanced24Local and CI. Nothing done a hundred times a day is interrupted.
filesystem-guardstrict20Keeps writes and deletes inside the workspace root.
network-guardstrict12Refuses cloud metadata; sanitises what comes back from outside.
zero-exfiltrationstrict24Credentials are brokered as handles, never read.

The hash covers the rules, not the manifest. Bumping a version or fixing a description must not invalidate a review somebody already did; editing a single deny must. A fork records both the parent id and the parent rule hash — the id alone is a claim, the hash is checkable, including after the parent has moved on.

Resolution

Deterministic
by construction.

Given the same request and the same rule set, the engine returns the same verdict — on any machine, in any SDK.

01

Explicit deny wins

A matching deny is terminal. No later rule can lift it, and rule order cannot be used to smuggle an allow past it.

02

No match means deny

The absence of a rule is not permission. An unmatched action is denied and recorded as unmatched.

03

Approvals bind to content

An approval is bound to the hash of what was approved. Editing the request un-approves it.

04

One engine, two runtimes

The Node and Python evaluators are held to a shared conformance fixture, so an SDK and the gateway cannot disagree about a verdict.

Watch a rule flip a verdict

The sandbox runs the same evaluator the gateway runs.

Open the sandbox
Govern what ships

Bring every agent
under control.

Set durable policy, preserve a verifiable record, and give teams a safer way to put intelligent systems to work.

Copied to clipboard