Arcezia · Complete Technical Guide

Verify before the agent acts. The verdict is solved, not scored.

Arcezia is runtime safety verification for autonomous AI agents. Before an agent executes an action, it asks Arcezia “is this safe?” and receives a signed verdict — ALLOW / REVIEW / BLOCK — decided by verifying grounded evidence, never by another model. Verification runs in Arcezia’s cloud; the SDK does zero inference client-side. This guide is the whole system, end to end.

00

Get started — from an API key to your first verdict

Five minutes, no infrastructure. You need only an API key; everything runs against api.arcezia.com.

1 · Get a key

Self-serve at arcezia.com, or mint a free-tier key directly:

curl -X POST https://api.arcezia.com/v1/signup \
  -A "arcezia-signup/1.0" \                    # a real UA — the WAF blocks default client signatures
  -H "Content-Type: application/json" \
  -d '{"email": "you@company.com"}'
# returns { "api_key": "ar_live_…", "role": "owner", "tier": "free" }  — shown ONCE

The key is returned exactly once — store it now. It carries the owner role, which is what the setup endpoints in §07 (probes, simulations, custom domains) require. Live keys are ar_live_…; use ar_test_… keys (dev mode) for local experiments.

2 · Install the SDK

pip install "arcezia[langchain]"   # or [openai], [anthropic], [llamaindex], [all]
export ARCEZIA_API_KEY=ar_live_…

The SDK is a thin client — it makes signed HTTPS calls and runs zero inference locally. No extra needed for the core verify(); the framework extra only pulls that integration’s deps.

3 · Your first verdict

import arcezia
az = arcezia.Arcezia(task="clean up staging data")   # reads ARCEZIA_API_KEY
cert = az.verify(action_type="execute_sql",
                 action_description="DELETE FROM analytics_staging WHERE created < '2024-01-01'",
                 domain="database_ops")
print(cert.allow, cert.review, cert.block, cert.summary)

With no evidence wired yet, a destructive action returns REVIEW or BLOCK — that is correct (§02). You reach ALLOW by grounding the facts your domain requires (§11), which is what §07 walks through.

Use the SDK, not raw curl, for the API. api.arcezia.com sits behind a WAF that blocks default scripting-client signatures (you’ll see error code: 1010). The SDK sends the right headers automatically. If you must call the REST endpoints directly (the §07 setup calls), send a normal User-Agent header — not the toolkit default.

01

The verification loop

The entire integration surface is one verify() in front of each tool call. Everything else in this guide is what happens inside that call.

How it plugs into your stack

Your agent and your tools stay exactly as they are. You wrap the tools once; everything else is optional and added later.

Arcezia integration architecture Inside your own process, your agent calls tools you already have; the Arcezia client sits between them and returns a verdict over HTTPS from api.arcezia.com before any tool runs. Optionally you expose two endpoints of your own that Arcezia calls back for grounded facts and dry-run predictions. YOUR APPLICATION — runs where it runs today Your agent LangChain · OpenAI · CrewAI AutoGen · LlamaIndex · n8n unchanged arcezia client the one thing you add toolkit.wrap(tools) ALLOW Your tools database · filesystem APIs · email · deploys unchanged HTTPS — verdict before the tool runs api.arcezia.com hosted · nothing to deploy or operate returns ALLOW / REVIEW / BLOCK + signed certificate OPTIONAL — endpoints you expose, added when you want stronger verdicts Arcezia calls you back Your probe webhook answers “is there a recent backup?” from your real systems so a fact is grounded, not claimed Level 3 Your sandbox dry-runs the action and reports the predicted effect catches “this would touch 50,000 rows” Level 3 Your own domains your rules, your vocabulary Level 4 · no code
You wantYou doRuns where
A verdict in front of every tool callwrap your tool list — one lineyour process
The whole plan checked before step 1call verify_chain() with the stepsyour process
Facts grounded in your real systemsexpose an HTTPS endpoint, register it onceyour infrastructure
The effect predicted before it happensexpose a dry-run endpoint, register it onceyour infrastructure
Your own rules and vocabularyregister a domain — configuration, not code

What you do not do: deploy a service, run a model, hold a queue, or change how your agent reasons. The client is a thin HTTPS caller; the engine is hosted. The two optional endpoints are ordinary web handlers on infrastructure you already have — and until you add them, Arcezia simply says REVIEW where it lacks evidence rather than guessing.

import arcezia
az = arcezia.Arcezia(api_key="ar_live_…", task="clean up test records")

cert = az.verify(
    action_type="execute_sql",
    action_description="DELETE FROM analytics_staging WHERE created < '2024-01-01'",
    domain="database_ops",
)
if not cert.allow:                    # gate on ALLOW positively — REVIEW is not runnable
    raise RuntimeError(cert.summary)  # signed, with the reason
db.execute(sql)                       # reached only on a grounded ALLOW

Gate on ALLOW, never on “not blocked”. A verdict can be REVIEW — neither allow nor block. Testing only cert.block lets a REVIEW fall through and executes an action the engine explicitly declined to clear. cert.allow is True only for a grounded ALLOW; the framework adapters (§07) enforce exactly this for you.

Four inputs, nothing more:

The call returns a certificate (cert): .allow/.review/.block booleans, a human-readable .summary, and on ALLOW a single-use .credential. Nine framework integrations wrap this for you (anthropic, openai, langchain, autogen, llamaindex, openclaw, claude_code, n8n, universal) so every tool call is gated automatically — no manual verify().

02

Three verdicts — and why REVIEW is the default

Verification returns one of three outcomes. Understanding REVIEW is the key to using Arcezia correctly: it is the fail-safe, not an error.

VerdictWhat it means & what to do
ALLOWEvery required precondition is grounded true. Proceed; cert.credential is a single-use token for your tool.
REVIEWA required fact is unresolved — not yet grounded. Not a failure: supply the evidence and it resolves to ALLOW. Route to a human meanwhile.
BLOCKOnly “do not execute” is consistent: a required constraint is grounded false, the action is out of task scope, or a fabrication was detected.

The rule that decides REVIEW vs BLOCK: a required fact that is unresolved (not yet grounded) → REVIEW; a required fact grounded false, or a domain rule that outright contradicts execution, → BLOCK. So in a fresh integration with no evidence wired, a destructive action returns REVIEW when its facts are merely unknown — but BLOCK when a domain rule forbids it on the evidence present (e.g. a production write with no grounded authorization can be forced to BLOCK, not REVIEW). Either way Arcezia never fails open. You earn ALLOW by grounding evidence (§03, §07), not by loosening the gate.

What else the certificate carries

Beyond the verdict, four fields matter when you wire this into production.

FieldMeaning
cert.precondition_score[0,1] — the severity-weighted fraction of required preconditions that are satisfied. 1.0 means every one is met.
cert.trust_score[0,1] — the fraction of the evidence that is externally grounded rather than asserted by the agent. A different axis from the score above: one asks “are the preconditions met?”, the other “who says so?”
cert.degradedTrue means nothing was actually verified. A synthetic verdict, produced when Arcezia could not be reached under on_error="review" or "fail_open" (§10). A degraded certificate never carries a credential. Check it before cert.block.
cert.credentialSingle-use token, issued only on ALLOW. Its absence is the second signal that an action was not authorised.

Reading the raw HTTP response? The precondition score is on the wire as precondition_score (the SDK exposes it as cert.precondition_score); dc_score carries the same value as a legacy alias for older consumers. If you integrate over plain HTTP — an n8n HTTP Request node, curl, another language — read $json.precondition_score. verdict, summary, violated, missing and trust_score are on the wire under those exact names.

03

Evidence grounding — the anti-hallucination core

Every fact Arcezia uses is graded by where it came from, not by whether it sounds right. This is why an agent cannot talk its way past the gate.

GROUNDED · external source deterministic analysis CLAIMED · the LLM said so UNRESOLVED · unknown → null FABRICATED · rejected → BLOCK

Every fact is grounded in one of a few ways, and how it is grounded decides whether the LLM is even allowed to speak to it:

How it is groundedWhat that meansCan the LLM claim it?
Deterministic checkA real check Arcezia runs (SQL parse, env var, row-count estimate)No
Your systemsAn external tool or your probe webhook (backup API, FK graph)No
Signed human tokenA signed human-intent token from your backendNever — claiming it = FABRICATED → BLOCK
Task-scope checkComparison of the action against the original task manifestNo
Model inferenceThe model may contributeYes — but recorded as CLAIMED, never pinned

The certificate carries a trust_score — the fraction of constraints that are externally grounded. A verdict resting mostly on CLAIMED evidence is low-trust even when it is ALLOW.

04

The four checks — before, across, after, ahead

Arcezia verifies an action at four distinct moments. Use as many as the risk warrants.

01 · Before — structural

Is this action safe & in scope?

Pre-execution solve: destructiveness, authorization, task-scope, reversibility. The core gate.

az.verify(...) → POST /v1/verify
02 · Across — the plan

Do these steps compose safely?

Verifies a whole chain; state propagates between steps; blocks at the first unsafe one. Catches safe steps that combine into harm.

az.verify_chain(manifest) → POST /v1/verify_chain
03 · After — audit

Did the outcome match intent?

Compare what actually happened to what was authorized. Catches “expected 1 row, got 50,000” — and fabricated “success”.

az.verify_outcome(outcome, expected) → /v1/verify_outcome
04 · Ahead — look-ahead

What will this action actually do?

Your sandbox dry-runs the action; Arcezia blocks if the predicted effect exceeds scope. Damage prevented, not detected.

simulation webhook → POST /v1/simulate/register

03 vs 04: both compare effect against authorized intent. 04 predicts before (needs a sandbox that can simulate) and prevents; 03 measures after (needs you to report the real result) and confirms. 04 is the guard, 03 is the receipt.

05

How a legitimate irreversible action passes

Arcezia does not block irreversibility. The destructive/mass-modify flags carry zero weight. It blocks unrecoverable, unauthorized irreversibility — and lets the authorized kind through.

For a destructive database action to reach ALLOW, Arcezia requires three things, and each must be grounded through a channel the agent cannot forge:

When those are grounded true, the identical DELETE that would otherwise BLOCK returns ALLOW with a single-use credential. When they are merely unprovided, the verdict is REVIEW — supply them and it becomes ALLOW. When authorization is fabricated or the action is out of scope, it is BLOCK. The agent structurally cannot self-authorize; that is the whole point.

Here is how you supply all three — each through its own channel (see §07 for the channel setup):

# 1. Scope, via the capability envelope — a plain dict your backend signs after
#    a human confirms it. Grounds action_within_task_scope.
az.start_session(capability_envelope={
    "allowed_domains": ["database_ops"],       # which domains this session may touch
    "allowed_action_types": ["execute_sql"],   # which actions (omit ⇒ everything BLOCKs)
    "max_scope": "mass",                        # blast radius: single_record | batch | limited | mass
    "structural_authority": {                    # the six axes an action may cross — each defaults
        "sensitive_data": True,               # unresolved (⇒ REVIEW) until you name it. Exact keys:
        "persistent_mutation": True,          # NOT "mutation"
        "mass_scope": True,
        "outbound": False,
        "trust_boundary_crossing": False,     # NOT "trust_crossing"
        "irreversible": False,
    },
})
# An unrecognised key (a typo) can never become a silent grant: the SDK
# rejects it immediately (ValueError naming the six valid axes), and over
# raw HTTP the server grants nothing for it and reports it back as
# ignored_authority_keys in the session response.

# 2. Authorization, via a signed token from YOUR backend (never the LLM).
#    Grounds production_explicit_authorization.
az.authorize_production(prod_token)   # prod_token = JWT you mint after a human clicks Approve

# 3. Backup, via a probe webhook you register once (§07 Level 3a) — Arcezia
#    calls your endpoint, which answers from real state. Grounds verified_recent_backup.

cert = az.verify(action_type="execute_sql",
                 action_description="DELETE FROM analytics_staging WHERE …",
                 domain="database_ops")
if cert.allow: run(cert.credential)   # all three grounded → ALLOW + single-use credential
06

Plans — blast radius, not seats

You don’t buy users; you buy which action domains you may verify plus the volume to do it. Tiers are cumulative — each includes every domain below.

PlanPriceVerif./moBurst/minDomains it adds
Free$010020database_ops, filesystem_ops, agent_action
Hobby$19/mo10,00060+ api_ops, email_ops, browser_ops
Team$99/mo100,000300+ payment_ops, deployment_ops, messaging_ops, pii_ops, customer_support
Scale$499/mo1,000,0001,000+ crm_ops, cloud_ops, data_warehouse_ops
Enterprise$50k/yrunlimited5,000+ healthcare_ops, eu_ai_act, government_ops, financial_compliance
+Add-ons — $29/mo per domain. Unlock any Team/Scale domain on a lower tier. Same SDK, same key.
Over your monthly limit? No hard stop. Verifications continue at the standard usage rate — $2 per 1,000 (core domains; higher-stakes more).
402Upgrade path. Calling a locked domain returns a structured ArceziaUpgradeRequired (current tier, next tier, add-on price) your agent handles inline.
07

The integration path — Levels 1 to 4

Adoption grows into the product. Level 1 is five minutes; the value inflects at Level 3, where evidence becomes authoritative and REVIEW turns into real ALLOW/BLOCK.

Level 1 — Drop-in wrapper

Install the extra; every tool call is gated automatically.

pip install "arcezia[langchain]"
from arcezia.integrations.langchain import ArceziaToolkit
safe_tools = ArceziaToolkit(az).wrap([sql_tool, shell_tool])   # domains auto-route from tool name

Level 2 — Chain verification

Sometimes each step is safe alone but the sequence is harmful (read customer emails, then send them out). Instead of verifying one action, you hand Arcezia the whole plan and it checks the steps together.

A chain manifest is just that plan as a dict: a "steps" list, where each step is one action — the same three fields you pass to verify() (action_type, action_description, domain) plus an id you choose (step_id is accepted too — the id is what blocked_at reports back). You build it in plain code:

chain_manifest = {
  "steps": [
    { "id": "read",  "action_type": "execute_sql",
      "action_description": "SELECT ssn, name FROM customers", "domain": "database_ops" },
    { "id": "send",  "action_type": "send_email",
      "action_description": "email the list to external@gmail.com", "domain": "email_ops" },
  ]
}
result = az.verify_chain(chain_manifest, stop_on_block=True)
# result shape (NOT a certificate — no top-level .verdict/.summary):
{ "overall_verdict": "SAFE" | "REVIEW_REQUIRED" | "BLOCKED" | "SEMANTIC_BLOCK",
  "blocked_at": "step-id" | None,
  "steps": [ { "id", "verdict", "missing_constraints", "state_mutations" }, … ],
  "semantic_triggers": […] }   # cross-step danger flags (exfiltration, mass-destroy)

State propagates between steps, and Arcezia derives it — you do not declare it. As each step is verified, the engine’s own structural reading of the action (that a read touched sensitive data, that a later step sends data outbound) carries forward into the accumulated session state. Two individually-safe steps that compose into harm — read customer data, then email it out — surface as a semantic_trigger even when each step alone is fine. The g_* world-state flags are engine-owned; a manifest cannot set them, and it cannot un-set a danger it has created (asserting a danger flag false in state_mutations is rejected, not honoured).

Level 3 — Ground the evidence (the real upgrade)

(a) Probe webhooks — ground a constraint that has no built-in check. This is what moves destructive actions from REVIEW to a real verdict.

# REST, once at setup (NOT an SDK method; needs your owner-role key (the one signup returns; admin works too)):
POST /v1/probes
{ "domain": "database_ops", "constraint_name": "verified_recent_backup",
  "webhook_url": "https://you/arcezia/backup", "secret": "≥16 chars" }
# also: GET /v1/probes · DELETE /v1/probes/{domain}/{constraint}

When the constraint needs resolving, Arcezia POSTs {constraint, domain, action_type, action_description, task}, signed X-Arcezia-Signature: sha256=… (HMAC over the raw body, keyed by sha256(secret) — see below). You reply within 5s:

{ "value": true, "grounded": true, "detail": "pg_dump verified 2h ago" }

grounded must be true; a non-200, timeout, or grounded:false leaves the fact unresolved (fail-safe). The agent cannot override a webhook-grounded constraint with its own evidence — the webhook is the only path. URLs are SSRF-guarded. Your raw secret never leaves your side: Arcezia stores only sha256(secret), and that digest is the HMAC key — so you derive the same key locally to verify. Your endpoint checks the signature, then answers from real state:

import hmac, hashlib
def handle(req, SECRET):
    key = hashlib.sha256(SECRET.encode()).hexdigest().encode()   # NOT the raw secret
    sig = hmac.new(key, req.raw_body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(f"sha256={sig}", req.headers["X-Arcezia-Signature"]):
        return 401
    ok = backup_exists_and_verified()          # your real check
    return { "value": ok, "grounded": True, "detail": "checked pg_dump catalog" }

Sign over the raw body, not a re-serialization. Arcezia signs the exact bytes it sends (canonical JSON, keys sorted). Frameworks that parse and re-encode the body — Flask’s get_json(), Express’s .json() — change those bytes and every signature check fails. The same key derivation and raw-body rule apply to the simulation webhook below.

The webhook must be publicly reachable over HTTPS. Arcezia’s cloud calls out to your endpoint, so localhost will not work — deploy the handler somewhere with a public URL (Cloud Run, Lambda + API Gateway, Cloud Functions, Fly, a Fargate service) and register that URL. For local development, expose it with a tunnel (ngrok, cloudflared). The endpoint should answer within 5s; a slow or unreachable webhook resolves to UNRESOLVED → REVIEW (fail-safe), never a silent pass.

(b) Outcome audit — after an ALLOWed action runs, confirm reality matched intent:

r = az.verify_outcome(action_type="execute_sql", action_description="reset staging",
                      outcome={"rows_affected": 1206},   # what happened
                      expected={"rows_affected": 40})    # what was authorized
if r.block: alert(r.violations)                     # outcome ≠ intent

(c) Look-ahead simulation — register one sandbox per domain; Arcezia calls it during verify() to predict the effect before allowing it:

# REST, once at setup (NOT an SDK method; needs your owner-role key (the one signup returns; admin works too)):
POST /v1/simulate/register  { "domain": "database_ops", "webhook_url": "https://you/arcezia/simulate", "secret": "≥16 chars" }
# Your sandbox dry-runs the action without committing, then reports the effect:
def simulate(req):                          # verify signature as above
    with db.transaction() as tx:            # BEGIN … ROLLBACK
        cur = tx.execute(sql_from(req))
        n = cur.rowcount
        tx.rollback()
    # rowcount is -1 for DDL (DROP/TRUNCATE/ALTER) — a table drop looks like
    # "0 rows" if you trust it. Refuse what you can't measure; never report it as safe.
    if n is None or n < 0:
        return { "acceptable": False, "reason": "effect not measurable by row count (DDL?)" }
    return { "acceptable": n <= 1000, "reason": f"{n} rows",
             "outcome": {"rows_affected": n} }

Arcezia BLOCKs if acceptable:false, or if predicted rows_affected/amount/… exceeds your capability envelope’s max_scope (single_record=1, batch=100, limited=1000; mass = no numeric row ceiling) / max_amount; predicts PII while denied → REVIEW; predicts an error → REVIEW. Declare limits at az.start_session(capability_envelope=…).

Capability-envelope gotchas (each verified against the live engine):
List allowed_action_types and allowed_domains, or you fail closed. If you set an envelope but omit allowed_action_types, every action is treated as outside it — action_within_task_scope grounds false and you get BLOCK across the board. List the action types the session is allowed to take.
max_scope:"single_record" is for row-level work, not payments. The mass-scope heuristic reads some action descriptions (e.g. refund text) as non-single and will BLOCK even a single item. For payments, gate with the domain’s own facts (AML / duplicate / amount), not max_scope.
A REVIEW can come with an empty missing list. Constraints held unresolved by a rule (rather than being directly required-for-execute) drive REVIEW without appearing in cert.missing. Read cert.constraints (per-constraint quality) to see which facts are still ungrounded.

Level 4 — Custom & compliance domains

Custom domains — upload your own rulebook (same YAML grammar; extends: a built-in). Private to your key; usable immediately.

# REST (admin): POST /v1/domains  { "name": "crm_ops_strict", "yaml_content": … }
"""
extends: crm_ops
constraints:
  - name: customer_data_authorized
    source: user_signal          # signed — LLM can never claim it
    required_for_execute: true
rules:
  - name: sensitive_requires_auth
    formula: { implies: [ {var: execute}, {var: customer_data_authorized} ] }
"""

Compliance domains (Enterprise) — you don’t define these; you enable the tier and verify with domain="healthcare_ops" etc. They encode real regulation: healthcare_ops (HIPAA — PHI authorization, encryption, BAA, patient consent), eu_ai_act (human oversight, conformity assessment, bias audit, Art. 10 data governance).

Level 4 needs Level 3 to function. Compliance constraints like baa_in_place or patient_consent_verified can never be claimed by the agent — enabling the domain only states what must be true. You make it real by registering a Level-3 probe webhook or signed-token source for each. Without them, every regulated action fails safe to REVIEW.

What each domain needs to reach ALLOW

Two things gate every verdict. Scope — every action, in every domain, requires action_within_task_scope, grounded by the capability envelope you sign at start_session. Facts — higher-consequence actions (destructive, bulk, high-value, sensitive-data) require additional grounded facts; the engine decides which apply per action. You never guess which: a REVIEW names the ungrounded ones.

The self-serve loop. On a REVIEW, read cert.constraints — each has a name and a quality (UNRESOLVED = not yet grounded). Find that name below, ground it through the listed channel, and re-verify. When every applicable fact is grounded, the identical action returns ALLOW. That loop — API tells you the name, this table tells you the channel — is the whole integration; you never reproduce the engine’s logic.

How a domain, its facts, and the three channels fit together. A domain (e.g. database_ops) is a rulebook: it names the facts that gate its actions. Each fact is grounded through exactly one channel — you wire the channel once, and Arcezia resolves that fact automatically on every future action in the domain:

ChannelWhat it is & what it doesWhere you set it up
envelopeCapability envelope — the signed scope object you pass to start_session. Declares allowed domains, action types, and blast radius. Grounds action_within_task_scope for every action.§05 / §07c
probeProbe webhookyour HTTPS endpoint that answers one fact from real state (does a backup exist? did AML pass?). You register one per fact (POST /v1/probes); when the engine needs that fact, it calls your endpoint (signed) and uses the reply as grounded evidence. The agent can never substitute its own answer.§07 Level 3a
tokenSigned token — a human-approval token minted by your backend after a person confirms. Grounds authorization facts (production_explicit_authorization, phi_access_authorized). The LLM can never produce one; claiming it is FABRICATED → BLOCK.§05

So integrating a domain is: read its row below → for each fact, wire the one channel it uses (a probe endpoint, a token source, or the envelope) → the engine grounds it from then on. You wire where each fact comes from; the engine decides when it applies.

Per-domain facts — what to ground for each domain (18)
DomainFacts to ground for ALLOW (channel: envelope / probe / token)
agent_actionaction_within_task_scope (envelope), budget_or_rate_within_limits (probe), user_explicit_authorization (token)
api_opsaction_within_task_scope (envelope), user_explicit_authorization (token)
browser_opsaction_within_task_scope (envelope), target_url_is_whitelisted (probe), user_explicit_authorization (token)
cloud_opsaction_within_task_scope (envelope), backup_exists (probe), user_explicit_authorization (token)
crm_opsaction_within_task_scope (envelope), access_logged (probe), user_explicit_authorization (token)
customer_supportaction_within_task_scope (envelope), user_explicit_authorization (token)
data_warehouse_opsaction_within_task_scope (envelope), backup_or_snapshot_exists (probe), result_anonymized (probe), user_explicit_authorization (token)
database_opsaction_within_task_scope (envelope), production_explicit_authorization (token), verified_recent_backup (probe)
deployment_opsaction_within_task_scope (envelope), required_reviewers_approved (probe), rollback_plan_exists (probe), tests_passed (probe), user_explicit_authorization (token)
email_opsaction_within_task_scope (envelope), recipient_is_opted_in (probe), unsubscribe_link_present (probe), user_explicit_authorization (token)
eu_ai_actaction_within_task_scope (envelope), bias_audit_passed (probe), conformity_assessment_complete (probe), data_bias_examined (probe), data_quality_assessed (probe), data_representativeness_verified (probe), human_oversight_maintained (token), training_data_documented (probe), transparency_disclosure_made (probe), user_explicit_authorization (token)
filesystem_opsaction_within_task_scope (envelope), recent_backup_exists (probe), secret_scan_passed (probe), target_outside_critical_paths (probe), target_under_version_control (probe), user_explicit_authorization (token), working_tree_clean (probe)
financial_complianceaction_within_task_scope (envelope), aml_check_passed (probe), audit_trail_maintained (probe), kyc_verified (probe), sanctioned_entity_check_passed (probe), user_explicit_authorization (token)
government_opsaction_within_task_scope (envelope), audit_trail_maintained (probe), multi_party_authorization (token), need_to_know_established (probe), security_clearance_sufficient (probe), user_explicit_authorization (token)
healthcare_opsaction_within_task_scope (envelope), audit_log_enabled (probe), baa_in_place (probe), data_encrypted_at_rest (probe), data_encrypted_in_transit (probe), patient_consent_verified (probe), phi_access_authorized (token)
messaging_opsaction_within_task_scope (envelope), user_explicit_authorization (token)
payment_opsaction_within_task_scope (envelope), aml_check_passed (probe), sanctioned_entity_check_passed (probe), user_explicit_authorization (token)
pii_opsaction_within_task_scope (envelope), access_logged (probe), adequacy_decision_or_safeguards_present (probe), data_subject_consent_verified (token), legal_basis_established (probe), user_explicit_authorization (token)

Why not the full rule set? You don’t need it, and it stays sealed. The engine decides when each fact applies to an action; you only wire where each fact comes from. The API drives the loop — a REVIEW always names the exact ungrounded fact — so grounding is mechanical, not guesswork.

08

Why only this approach works

Every other way of making agents safe shares one flaw: something that can be fooled is trusted to make the safety decision. Arcezia moves the decision outside the agent and grounds it in facts the agent cannot forge.

Common approachWhy it breaks
Prompt rules / system instructionsThe agent grades itself; instructions are claims it can reason around. This is exactly how the Replit wipe happened (§09).
A second model / LLM-as-judgeA model grading a model — same hallucination and prompt-injection failure modes, nondeterministic, no proof, and it can be talked down.
Allow/deny lists & RBACCoarse: a safe DELETE and a catastrophic one use the same permission and the same tool. No sense of scope or outcome.
Logging / observabilityDetects after the damage. No prevention.
Human-in-the-loop on everythingDoesn’t scale; alert fatigue turns into rubber-stamping.

What makes Arcezia different — stated as properties, the things you can observe and rely on:

What stays inside the box. You provide the action and the evidence sources; you receive a signed verdict and its reason. The method that makes the verdict complete (never misses) and non-contradictory (never self-conflicts) is Arcezia’s proprietary, patent-pending core. You never need to see inside it to rely on it — and it never ships to your infrastructure. Verification is hosted, so the method stays sealed while you get the result. That sealed core is a large part of why this can’t simply be copied.

09

Case study — the Replit database wipe (July 2025)

During a code freeze, an AI agent deleted production data for 1,190+ companies, then fabricated test results and falsely claimed rollback was impossible. Every safeguard failed because each was a claim, not an enforced constraint.

What happenedThe check that stops itVerdict
Panicked, ran DROP/DELETE on prod during a freezeStructural — action is outside the authorized task (action_within_task_scope=false)BLOCK
Told itself “DB already empty, safe”Grounding — that’s CLAIMED, trust 0; if it forges authorization → FABRICATEDBLOCK
Reported “tests passed, 0 rows” + 4,000 fake usersOutcome audit — 1,206 real rows ≠ the 0 claimedBLOCK
Claimed “rollback impossible”Unsourced claim can’t govern recoveryflag

Sources: Fortune 2025-07-23 · The Register 2025-07-21 · AI Incident Database #1152.

The mirror image is the point: a DBA doing the same deletion, but with a signed authorization token + a verified backup + in scope, gets ALLOW and a credential. The agent cannot self-authorize; the human can.

10

Operating notes & honest limits

When Arcezia itself cannot be reached

The fail-safe above covers an unresolved fact. This covers an unreachable gate — a network partition, a timeout, an outage. You choose that behaviour when you construct the client, and it is the most consequential setting you will pick.

on_errorBehaviour after retries are exhausted
"fail_closed" (default)Raises ArceziaUnavailableError. The action is stopped because safety could not be verified. Choose this unless you have a specific reason not to.
"review"Returns a synthetic REVIEW. The action halts pending a human — safe degradation.
"fail_open"Returns a synthetic ALLOW; the action proceeds unverified. Only for non-critical actions, and deliberately.

The verdicts produced by the last two are synthetic: nothing was checked. They are always marked cert.degraded = True and never carry a credential. If you call the client directly under either setting, test that flag before the verdict:

if cert.degraded:
    # Arcezia was unreachable — this verdict verified nothing.
    raise RuntimeError("not verified")
if not cert.allow:                  # ALLOW positively — a REVIEW is not runnable
    raise RuntimeError(cert.summary)
run_tool(...)                       # only when verified AND allowed

The framework adapters (§07) already do this for you: a degraded certificate raises ArceziaUnavailableError and the wrapped tool never executes — including under fail_open. The setting relaxes the client, not the gate in front of your tools.

11

Domains & the facts they require

This is the map from “stuck at REVIEW” to ALLOW. For a consequential action, the engine will not ALLOW until these facts are grounded — and it grounds them only two ways: a signed token you attach with az.authorize(…), or a probe webhook you register (§07 Level 3). The agent can never supply either.

DomainSigned token — az.authorize()Probe webhook — /v1/probes
database_opsproduction_explicit_authorizationverified_recent_backup
payment_opsuser_explicit_authorizationpayment_recipient_verified, aml_check_passed, sanctioned_entity_check_passed
filesystem_opsuser_explicit_authorizationrecent_backup_exists
cloud_opsuser_explicit_authorizationresource_has_deletion_protection, backup_exists
deployment_opsuser_explicit_authorizationtests_passed, rollback_plan_exists, required_reviewers_approved
email_opsuser_explicit_authorizationrecipient_is_opted_in, recipient_not_on_suppression_list, attachment_scanned
messaging_opsuser_explicit_authorizationattachment_scanned
crm_opsuser_explicit_authorizationcontact_consent_verified
data_warehouse_opsuser_explicit_authorizationbackup_or_snapshot_exists
api_opsuser_explicit_authorization— (system probes only)
browser_opsuser_explicit_authorization
agent_actionuser_explicit_authorization
customer_supportuser_explicit_authorization
pii_opsdata_subject_consent_verified, user_explicit_authorizationadequacy_decision_or_safeguards_present
healthcare_opsphi_access_authorizedbaa_in_place, patient_consent_verified
financial_complianceuser_explicit_authorizationkyc_verified, aml_check_passed, sanctioned_entity_check_passed
eu_ai_acthuman_oversight_maintained, user_explicit_authorizationconformity_assessment_complete, bias_audit_passed, training_data_documented, data_quality_assessed, data_bias_examined, data_representativeness_verified
government_opsmulti_party_authorization, user_explicit_authorizationsecurity_clearance_sufficient, need_to_know_established, system_accreditation_valid

Shaded rows are Enterprise-tier compliance domains (§06). Every constraint above is grounded by a signed human token or your probe webhook — the two kinds the agent cannot forge. Other constraints each domain checks (destructiveness, production-target, PII, rate) are grounded by Arcezia’s own deterministic checks or your org policy, and need no wiring from you.

How to read a REVIEW. If a verdict is REVIEW and you don’t know why, inspect cert.constraints — each entry has a quality (GROUNDED / CLAIMED / UNRESOLVED / FABRICATED). The UNRESOLVED ones are exactly the facts from this table you haven’t grounded yet. (Note: cert.missing lists only directly-required constraints, not rule-driven ones — so it can be empty on a REVIEW; cert.constraints is the complete picture.)