CirvixDocs / API Reference

A small surface, deliberately.

Decisions are made locally by the engine, never over the network. What this API does is record them, read them back, and export the chain. Anything that could weaken a boundary is not an endpoint.

0network hops to enforce
Bearerorg-scoped credential
denyresponse when unauthenticated
JSONrequest and response

Authentication

Every request carries a bearer credential that resolves to an agent and an org. The org_id in a request body is checked against the credential — it is not trusted as an assertion. A mismatch is denied and recorded.

Console keys and SCIM tokens are separate credential surfaces. A SCIM token cannot be used as a console key; that separation is enforced by test.

Where the decision happens

Not here. This is the part of the API most likely to be misread, so it is worth being blunt about: the control plane does not authorize actions over HTTP. There is no endpoint you call to ask permission.

Decisions are made locally, in-process, by the engine — the SDK wrapper, the gateway, or the runtime, whichever is in front of your agent. That is deliberate. An authorization hop over the network would put a remote dependency on the path of every tool call an agent makes, and a control plane that is unreachable would then have to either fail open or stop your agents. Evaluating locally means a network partition costs you telemetry, not enforcement.

the actual enforcement pathJS
import { guard } from "@cirvix_ai/agent-control";

// Evaluated in-process, against the policy this workspace has loaded.
// No network call is made to reach a verdict.
const readFile = guard.wrap(fs.readFile, { tool: "fs.read" });

await readFile("./.env");   // throws: deny-dotenv-read

What reaches this API afterwards is the record of a decision that has already been made and enforced.

Reporting decisions

POST /v1/decisions — ingest decisions the engine already made. This is telemetry, metering and the audit trail; it is not an authorization call, and the verdict is a field you send, not one you receive.

POST /v1/decisionsREQUEST
{
  "decisions": [{
    "verdict":  "deny",
    "tool":     "fs.read",
    "resource": "./.env",
    "rule":     "deny-dotenv-read",
    "reason":   "secrets are brokered, not read",
    "agent":    "pr-triage",
    "runId":    "run_4c07e2"
  }]
}

Send one decision as a bare object, or up to 500 in a decisions array — more than that is refused with 413 before anything is stored, so a rejected batch never leaves you guessing which half landed. The org_id is taken from your credential and never from the body.

A tenant past its daily allowance with no credits gets 402, and nothing in that batch is recorded. Note what this does not do: it cannot un-enforce anything. The action was already permitted or blocked locally at the moment it happened. A 402 here means you lose the record, not the protection.

Endpoints

MethodPathPurpose
POST/v1/decisionsRecord decisions the engine already made. Up to 500 per call.
GET/v1/decisionsList recorded decisions for the calling org.
GET/v1/decisions/:decisionIdRead a single decision, including rule, reason and risk.
POST/v1/runsOpen a run — the unit a group of decisions belongs to.
GET/v1/runs/:runIdRead a run and the decisions recorded under it.
POST/v1/runs/:runId/replayRe-evaluate a past run against current rules. Never re-executes.
GET/v1/auditExport the chain for the calling org, as linked JSON records.
GET/v1/audit/verifyRecompute the chain and report the first block where linkage breaks.
GET/v1/policyThe active rule set and its load state.
GET/v1/policy/versionsEvery published version, newest first.

Verdicts

ValueMeaning
allowProceed, with the scope granted. Nothing wider.
denyDo not proceed. The reason is returned; the payload is not.
holdPause for a human decision. The request is preserved intact.
audit_onlyAn observation was recorded. This does not authorize the action.

Errors

StatusConditionBehaviour
400Malformed request body.Nothing evaluated, nothing recorded.
401Missing or invalid credential.Denied. Recorded as an unauthenticated attempt.
403Credential does not match the requested org_id.Denied and recorded — this is a boundary event.
409Rule set failed to load; previous set still active.Denied. The load failure is recorded separately.
503Policy engine or audit store unreachable.Denied. There is no pass-through mode.
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