Product
One tool call, end to end.
Give AI agents access to your infrastructure without giving them unlimited power. This is what happens between the agent deciding to act and anything actually happening.
The path
Agent → Cirvix → policy → risk → approval → execution
Parse & normalize
Whatever spoke it — MCP over stdio, MCP over HTTP, the local control socket, or an SDK wrapper — becomes one envelope. After this point nothing downstream knows which agent framework made the call.
Stops: A rule written once governs every agent that will ever connect.
Detect secrets
The arguments are scanned for credential material: AWS keys, GitHub and OpenAI tokens, private keys, database URLs with passwords. Findings never carry the value — only a masked shape and a fingerprint.
Stops: A key the model pasted into a request body, before it reaches the wire.
Classify risk
A deterministic classifier — not a model — scores the call LOW, MEDIUM, HIGH, or CRITICAL. Identical inputs give identical scores a year later, which is what makes replay meaningful.
Stops: Rules can say risk >= HIGH instead of enumerating every dangerous tool that will ever exist.
Evaluate policy
An ordered rule set. Deny always wins; an approval outranks an allow; a sanitizer outranks an allow; anything unmatched is denied. The same evaluator runs in local dev, CI, and production.
Stops: The call the agent was persuaded to make by a page it read.
Check approvals
A held call waits for a named human. The agent is told which one, and given the approval id — so it can say so and move on to other work rather than hanging.
Stops: A production deploy or a database write happening because nobody was asked.
Sanitize & record
Secret handles are substituted onto the wire and swapped back on the way home. Instructions embedded in fetched content are stripped before the model reads them. Then the decision is appended to a hash-chained log.
Stops: A credential entering a context window, a transcript, and a trace.
Decisions
Five outcomes, not two
Forwarded unchanged.
Forwarded, but not as written — credential material stripped from the arguments, embedded instructions stripped from the result.
Suspended for a named human. It may still happen.
Refused, with a reason and a remediation the agent can act on — so it re-plans instead of retrying.
Recorded, not enforced. The honest shadow deployment: every record says enforced: false so nobody mistakes it for a protected run.
Policy
Rules you can read out loud
deny: tool = filesystem.read path = **/.aws/** deny: network.destination = 169.254.169.254 deny: tool = network.request secrets >= 1 require_approval: tool = shell.exec risk >= HIGH sanitize: tool = network.request targets = result allow: tool = git.statusDeny always wins
A permit cannot override a forbid, regardless of order or specificity. That is what makes a rule set safe to extend: adding a permissive rule can never silently punch a hole through an existing prohibition.
Unmatched means denied
A call no rule permits is refused. Fail-open is how a control plane becomes decorative the first time a rule file fails to parse.
The policy ships its own tests
cirvix policy test runs the cases declared in the file. A rule set nobody dares change ossifies until it is bypassed rather than updated.
In practice
An agent reads a page. The page tells it to read your credentials.
╔════════════════════════════════════════════════════════════╗║ CIRVIX SECURITY INTERCEPT ║╠════════════════════════════════════════════════════════════╣║ Agent: claude-code ║║ Tool: filesystem.read ║║ Target: ~/.aws/credentials ║║ Risk: CRITICAL ║║ Decision: BLOCKED ║║ Policy: deny-credential-directories ║║ Latency: 1.7ms ║╚════════════════════════════════════════════════════════════╝Then the same agent, under the same policy, runs git status, reads ./src/app.ts, runs the test suite, and creates a branch — uninterrupted.
That contrast is the product. Cirvix does not disable agents. It makes the dangerous half controllable, and leaves the rest alone.
Run it yourself. Nothing in the demo is scripted — every decision, risk level, policy name, and latency figure is computed live against your own rule set, so the number you see is your machine’s, not ours.
npx @cirvix/agent-control demo
Overhead
The decision path is not where your latency goes
These are design targets measured on a developer machine, not a published SLA and not a comparison against other products. The harness prints the platform line alongside every figure, because a latency number with no machine attached is not a measurement.
Reproduce it: node benchmarks/decision.mjs
