Skip to content

documentation

The guard contract.

Your guardrails compile into machine-checkable policy, decisions are logged per call, and the same evidence feeds your compliance reports. This page is the whole contract.

01

Tokens

Guard tokens are created in the console by an owner or admin. Two kinds exist: gsk_ service tokens, for a runtime your agents call through, and gik_ install tokens, for a data plane that reports decisions. The secret is shown once at creation and stored only as a SHA-256 hash. If you lose it, revoke and mint a new one. Scopes are granted per token and revoking is immediate.

guard:config:read / writeRead or push compiled rulesets (the push contract).
guard:decisions:read / writeRead or report decisions (the reporting contract).
02

Push a ruleset

Compile a guardrail and store it with the control plane. The call is idempotent on config_id: re-pushing an unchanged ruleset acks {"stored": false}, so there is no churn. On the hosted platform your guardrail is pushed automatically when a new version is generated.

push a ruleset - shell
curl -X POST $GUARD_URL/v1/guard/configs \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "config_id": "cfg_<guardrail-id>",
    "org_id": "<your-org-id>",
    "ruleset_version": "<compiler version hash>",
    "rules": [ ... ]
  }'
03

Decisions in and out

Data planes report decisions in batches, at least once. The store is idempotent on the decision id, and raw payloads never travel, only a state_digest. Your org can pull the same log from GET /v1/guard/decisions and the aggregated view from GET /v1/guard/activity.

report decisions - shell
curl -X POST $GUARD_URL/v1/guard/decisions \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "batch_id": "sync-2026-09-23T08:00",
    "org_id": "<your-org-id>",
    "decisions": [{
      "id": "gdec_...",
      "surface": "mcp_tool_call",
      "mode": "enforce",
      "decision": "block",
      "state_digest": "<sha256 of the exact state>",
      "ref": { "tool": "..." }
    }]
  }'
04

Connect your runtime

Call evaluate immediately before a tool executes. It is the gate, not an audit. One call per decision point: the relay loads your compiled ruleset, makes a single batched judge call, and answers in milliseconds.

guard_check.py
import httpx

GUARD = "https://arx.orithos.com"
TOKEN = "gik_..."  # install token with guard:evaluate

def guard_check(tool: str, args: dict) -> str:
    resp = httpx.post(
        f"{GUARD}/v1/guard/evaluate",
        headers={"Authorization": f"Bearer {TOKEN}"},
        json={"surface": "mcp_tool_call", "tool": tool, "args": args},
        timeout=10,
    )
    if resp.status_code != 200:
        return "fail_closed"          # 429/503 -> YOUR fail mode decides
    return resp.json()["decision"]     # allow | escalate | block

def execute_tool(tool: str, args: dict):
    decision = guard_check(tool, args)
    if decision == "block":
        raise PermissionError(f"Blocked by Arx Guard: {tool}")
    if decision == "escalate":
        queue_for_review(tool, args)   # never silently proceed
        return
    return run(tool, args)

Rules of the road

A non-200 answer means the relay could not evaluate, so apply your own fail mode, closed for destructive tools and open for read-only ones. block means refuse the call and return an error to the agent, never retry the same call. escalate means surface it to a human or a review queue. Each evaluation is one decision and one metered unit: evaluate once, act on the verdict.

05

Usage and metering

Decisions are counted per org per calendar month (UTC). Each relay evaluation counts once, decisions reported over the reporting contract count once each, and retries or duplicate batches never double-count. Read the current period and trailing months at GET $GUARD_URL/v1/guard/usage, which requires guard:decisions:read, split by relay versus reported and by outcome.

Your plan's monthly allowance is enforced at the relay: once the current month reaches it, evaluations answer 429 until the month rolls over, unless your plan grants overage. Then calls keep flowing and the excess settles from the same counters against your spend cap. The usage response carries limit, remaining and overage_allowed, so you always know where you stand.

06

Evaluate

The relay judges your traffic: send one decision point, get one verdict. It loads your compiled ruleset, makes a single batched judge call with our key, no judge account needed, or yours on BYOK, applies your routing table, logs the decision, and answers. Requires an install token (gik_) carrying guard:evaluate.

evaluate - shell
curl -X POST $GUARD_URL/v1/guard/evaluate \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "surface": "mcp_tool_call",
    "tool": "send_email",
    "args": { "to": "customer@example.com" },
    "agent": "billing-bot"
  }'
# -> 200 {"decision": "block", "decision_id": "gdec_...",
#         "ruleset_version": "...", "detail": {"blocks": [...]}}

Contract: 200 is a decision, allow, escalate or block. 429 is over the token's rate limit or the spend cap. 503 means the relay cannot evaluate, nothing pushed yet, no key configured, license expired, so your own fail mode applies. A judge failure is not a 503: your per-rule fail_mode decides, closed means block, and the decision is logged with the reason. Raw state is never stored, only its SHA-256 digest.

07

Where the endpoint lives

The managed endpoint is https://arx.orithos.com, use it as $GUARD_URL in the examples above. Only the token-authenticated contract routes are reachable there. Platform administration stays internal. Self-hosting instead? The same service and the same tokens work against your own control plane. The managed MCP path, tool calls enforced in your agent traffic, runs through the Orithos MCP gateway. See MCP Registry.

08

Compliance and audit

Every decision carries its ruleset version and the attribution of what fired, blocked rules and gate class. The aggregated activity view is embedded in compliance report exports as enforcement_evidence, and the decision log is retained per your org's retention window.

org scopingTokens are org-scoped: a token can only ever read or write its own org's data.
revocationImmediate, and recorded with who revoked it and when.
syncThe decision log syncs to your org store at least once. Consumers page with a cursor until caught up.