Arcus Docs

Introduction

Core concepts

The nouns Arcus uses, and what each one actually is in the system — tenant, agent, key, dispatch, policy, guardrail, transfer log and audit event.

One account is one tenant#

Arcus has no workspace entity. Your account is the tenant: your Clerk user id is your tenant id, and API keys, policies, guardrail rules, transfer logs, baselines and your audit chain all hang directly off it. Billing is account-level too.

This matters in three places you will actually notice:

  • Isolation is per account. Rate-limit counters, quarantine state and audit chains are namespaced by tenant, so billing-agent in your account and billing-agent in someone else's are two unrelated agents that cannot affect each other's limits.
  • Your audit chain is yours alone. A global chain would interleave other accounts' writes into your proof, so verifying your own history would depend on rows you are not allowed to read. Each tenant gets an independent chain starting at sequence 1.
  • There is no seat model. If you need to share access, share the workspace login; if you need to attribute keys to individuals, use the owner email field on each key.

Agent#

An agent id is a string you choose — intake-agent, billing-worker, support-triage. Arcus does not maintain a registry of agents; an agent exists the moment a dispatch declares it.

An agent id is meaningful only together with your tenant. It appears in three roles:

  • the from field on a dispatch (who is sending),
  • the senderAgentId on a policy or guardrail rule (who a rule applies to),
  • the subject of rate limiting, quarantine and statistical baselines.

`from` is caller-supplied

Anything the caller sends can be claimed. That is precisely why identity binding exists: bind a key to an agent id and the claim becomes a check. Rate limiting also keys on the bound agent when there is one, so a spoofed from cannot be used to escape a quarantine. See Authentication & keys.

API key#

The credential your agent presents. Format:

text
ark_live_<48 hex characters>

Arcus stores the SHA-256 hash and a 15-character display prefix — never the key. The raw value is shown once at creation. Consequences worth internalising:

  • Support cannot recover a lost key. Revoke and reissue.
  • A database compromise does not yield usable keys.
  • Keys are matched by hash, so lookup is a single indexed read on the hot path.

A key can carry an agent binding (agentId) and an owner email. Revocation is immediate: the row keeps its history but the key stops authenticating.

Dispatch#

One governed request. Your agent sends it; Arcus decides on it; the worker delivers it.

json
{
  "target": "https://api.example.com/webhook/triage",
  "from": "intake-agent",
  "to": "triage-service",
  "message": "Human-readable instruction or content",
  "data": { "any": "structured fields" }
}

target and message are required. from, to and data are optional — though from is what every policy, guardrail and rate limit reasons about, so omitting it means falling back to whatever the key's binding says. Full field reference: Dispatch API.

A dispatch is not a proxy call. Arcus does not stream your target's response back. It accepts responsibility for delivery, returns 202, and delivers asynchronously with retries.

Policy#

A rule about routes: may this sender reach this endpoint at all?

Matched on (senderAgentId, targetEndpoint) with * as the only wildcard. When several policies match, the most specific one wins — an exact sender beats a wildcard, a literal target beats a wildcard, and longer literals beat shorter ones. When nothing matches, the answer is deny.

Three actions: ALLOW, BLOCK, REQUIRE_APPROVAL. Details: Policy engine.

Parameter guardrail#

A rule about content: is this specific instruction safe to carry out?

Policy answers whether an agent may talk to an endpoint. A guardrail answers whether the message it is sending should go — a transfer of £50,000 from an agent that has only ever sent £100, a DROP TABLE in a command field, a confirm: true on a deletion.

Guardrails match on a dotted path into the payload (data.amount, data.items[*].qty) and every match is collected, because two rules tripping on different fields are two separate facts a reviewer needs. Each can block, hold_for_approval or flag_only. Details: Parameter guardrails.

Baseline#

Learned statistics for one numeric field, per agent: a rolling window of the last 50 values, plus the mean and standard deviation derived from it.

The point is catching what no rule was written for. Nobody thought to cap the amount, and policy has no opinion, but the shape of the traffic changed — and that is worth a human look. A baseline needs 5 observations before it will judge anything, and flags at 5× the rolling mean or 4 standard deviations out.

Baselines live in PostgreSQL rather than Redis on purpose: a rate-limit counter lost to a flush costs one window of enforcement, but a lost baseline silently resets every agent to "no established normal" and the check goes quiet exactly when it is least obvious that it had.

Transfer log#

The mutable operational record of one dispatch. Status, source agent, target URL, payload size, attempts, HTTP status, error, which policy matched, whether DLP or a guardrail fired, and the decision reason.

It changes as a delivery progresses — that is the point of it. Statuses:

StatusMeaning
PENDINGAccepted and queued, not yet delivered.
SUCCESSThe target returned 2xx.
FAILEDDelivery failed after retries, or the queue was unavailable.
BLOCKED_BY_POLICYNo policy allowed the route, or one explicitly blocked it.
BLOCKED_BY_DLPThe payload contained credential-shaped data.
BLOCKED_BY_PARAMETERA guardrail set to block matched a value in the payload.
PENDING_APPROVALHeld for a human decision; the payload is retained until then.
REJECTEDAn approver refused a held message.
THREAT_DETECTEDThe sending agent was rate-limited or quarantined.

Audit event#

The immutable evidentiary record. One row per governance-relevant event, written once and never updated, chained by hash to the previous event in your tenant's chain.

A delivery outcome does not edit the dispatch event — it appends a new event. That is what makes the chain worth having: any modification or deletion breaks the sequence, and the break is provable on demand. Details: Audit chain.

Transfer log vs audit event#

The distinction is the one thing worth being clear about, because both look like "the log":

Transfer logAudit event
PurposeOperations — what is happening nowEvidence — what happened, provably
MutableYes, by designNever
StructureA row per dispatchA hash-chained sequence per tenant
DeletableYesDeletion is detectable
Read byThe Logs view, dashboards, retriesCompliance export, chain verification

Tier and capability#

Your tier is free, pro or max. It sets numeric limits (active keys, enabled guardrail rules) and grants capabilities — named permissions like audit.verify, policy.custom, dlp.configure or reports.

Capabilities gate control and visibility, never enforcement. Every plan, including Free, gets the full five-gate pipeline on every request. What Pro and Max add is the ability to configure it more finely and see further into it. See Pricing & plans.

Quarantine#

A temporary block on one agent, held in Redis with a live TTL.

Arcus imposes one automatically when an agent exceeds 60 dispatches in 60 seconds (300-second quarantine), and a platform operator can impose one deliberately from the abuse queue. Both write the same Redis keys, so there is exactly one enforcement path and the two mechanisms cannot disagree about who is blocked. You can see your own quarantines, and their remaining TTL, under Anomaly Detection. Details: Threat detection.