# How Do You Integrate AgenticRail's Sequence Enforcement API?

> Markdown mirror for AI agents, generated 2026-08-12 from the live page.
> Canonical: https://agenticrail.nz/docs/
> Site context: https://agenticrail.nz/llms.txt

Developer Documentation

# Zero to first gate call

*in under 10 minutes.*

One endpoint. One header. POST before each step — the gate returns **ALLOW** or **DENY**. Your agent only proceeds on ALLOW. Every ALLOW writes a cryptographic receipt — a signed, chained record of what ran, when, in what order, written before the action executed. The same gate answers the engineering question and the compliance question.

 Wrapper live — https://api.agenticrail.nz/v1/evaluate

How it works

## Three steps. No magic.

Every gate call follows the same path. Your agent sends a request. The gate enforces sequence. You get a receipt or a halt.

01

Send request

POST to `/v1/evaluate` with your agent's current step, a unique nonce, and a timestamp. Auth via the `Authorization: Bearer` header.

02

Gate enforces sequence

The gate validates step order, checks the nonce for replay, verifies `function` and `action_type` against the policy for this step, and confirms the sequence is not sealed. All checks must pass.

03

Receive receipt or halt

On pass: a cryptographic receipt with decision `ALLOW` — Ed25519-signed, chained, written to R2 as a tamper-evident record. That receipt is your compliance record: structural proof of what ran and in what order, timestamped by AgenticRail. On failure: a `DENY` with a reason code. Your agent only proceeds on ALLOW.

Authentication

## One header. Every request.

All requests to the wrapper require the `Authorization: Bearer` header. The demo key is public and rate-limited — use it to test without signing up.

Demo key — public, free to use

DEMO-AGENTICRAIL-PUBLIC-2026

Add to every request: `Authorization: Bearer DEMO-AGENTICRAIL-PUBLIC-2026`

 The wrapper expects the `Authorization` header; the gate uses `x-slp8-key`.

 For production use, contact [hello@agenticrail.nz](mailto:hello@agenticrail.nz) for a private key with no rate limits.

Service Architecture

## Wrapper, Gate, and Report

AgenticRail deploys three public services:

01

Wrapper (front door)

**Endpoint:** `https://api.agenticrail.nz/v1/evaluate`

 **Auth:** `Authorization: Bearer <key>`

 Adds API key management, rate limiting, D1 logging, and demo key bypass. All client requests should use this endpoint.

02

Gate (enforcement)

Pure sequence enforcement layer — validates step order, nonce, function/action_type policy, and sequence seal. Called internally by the wrapper via service binding. Not publicly accessible — all client traffic enters through the wrapper.

03

Report (compliance)

**Endpoint:** `https://report.agenticrail.nz/report`

 **Auth:** `x-slp8-key: <key>`

 Generates HTML/JSON compliance reports for any sequence. Read-only; no state mutation.

Demo key `DEMO-AGENTICRAIL-PUBLIC-2026` works with all three services. Wrapper prefixes demo sequence IDs with `demo-` and isolates receipts.

Request format

## Fields, one by one.

All requests are `Content-Type: application/json` via POST. Fields are validated in order — a missing required field halts at gate step 1.

 | Field | Type | Description |
 | schema_version | string | Always `"1.0"` |
 | sequence_id | string | Unique per sequence — e.g. a UUID or session ID. Groups steps together. |
 | step | string | Your step name — must match `function`. Must be a valid step in your configured sequence, called in the defined order. e.g. `"verify_identity"`, `"assess_risk"`, `"execute_transfer"`. |
 | function | string | Canonical function name — must equal `step`. e.g. `"verify_identity"`, `"assess_risk"`. Used for policy lookup. |
 | action_type | string | Canonical action type for this step. Must be in the allowed set for the function. e.g. `"CHECK_STATE"`, `"RECORD_RESULT"`, `"WAIT_FOR_SIGNAL"`. |
 | model_id | string | Your agent identifier — e.g. `"my-agent-v2"`. When using the demo key, the wrapper transforms this to `"client:demo"` before passing to the gate. |
 | nonce | string | Unique string per request (any format). Used for replay protection — never reuse. |
 | action | string | Descriptive action label for this step. e.g. `"verify identity"`, `"assess risk"`. |
 | ts_ms | number | Unix timestamp in milliseconds. Required — use `Date.now()` or equivalent. Must be within ±300 seconds of current time when received by the gate. |
 | inputs | object | Optional. Any context you want to log alongside the step. |
 | attestation | object | Optional. Evidence object signed into the receipt at this step — e.g. `{"aml_check": "passed", "approved_by": "risk-committee-id"}`. The full object is signed into the receipt and stored in R2 alongside it, so any later alteration is detectable. Use it to embed proof of deliverables, external check results, or human approvals directly in the audit trail. Can contain hashes, IDs, and long strings — excluded from poison hardening. |
 | step_order | string[] | Required on every call. Array of all step names in execution order — e.g. `["verify_identity", "assess_risk", "execute_transfer"]`. The gate reads it from each payload to resolve the step's position. The gate does not store it between calls. |

**Timestamp freshness:** The gate enforces a ±300 second window around the current time. If your request arrives more than 5 minutes early or late, it will be rejected with reason `STALE_TIMESTAMP`. Always generate `ts_ms` fresh using `Date.now()` or equivalent.

Quickstart

## Copy. Paste. Run.

This example works against the live wrapper right now. Each snippet generates a fresh timestamp, a unique nonce, and a unique sequence ID on every run, so it returns **ALLOW** the moment you paste it.

 curl — bash / mac / linux

```
# Paste the whole block. Fresh timestamp, unique nonce + sequence id - runs every time.
TS=$(( $(date +%s) * 1000 ))
NONCE=$(openssl rand -hex 8)
SEQ="my-seq-$(date +%s)"

curl -X POST https://api.agenticrail.nz/v1/evaluate \
 -H 'Content-Type: application/json' \
 -H 'Authorization: Bearer DEMO-AGENTICRAIL-PUBLIC-2026' \
 -d "{
 \"schema_version\": \"1.0\",
 \"model_id\": \"my-agent\",
 \"sequence_id\": \"$SEQ\",
 \"step\": \"verify_identity\",
 \"function\": \"verify_identity\",
 \"action_type\": \"CHECK_STATE\",
 \"action\": \"verify identity\",
 \"nonce\": \"$NONCE\",
 \"ts_ms\": $TS,
 \"inputs\": {},
 \"step_order\": [\"verify_identity\", \"assess_risk\", \"execute_transfer\", \"audit_ledger\"]
 }"
```

 powershell — windows

```
# Paste the whole block into PowerShell
$ts = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
$nonce = -join ((1..16) | ForEach-Object { '0123456789abcdef'[(Get-Random -Maximum 16)] })
$seq = "my-seq-$ts"
$body = '{"schema_version":"1.0","model_id":"my-agent","sequence_id":"' + $seq + '","step":"verify_identity","function":"verify_identity","action_type":"CHECK_STATE","action":"verify identity","nonce":"' + $nonce + '","ts_ms":' + $ts + ',"inputs":{},"step_order":["verify_identity","assess_risk","execute_transfer","audit_ledger"]}'
$headers = @{ "Content-Type" = "application/json"; "Authorization" = "Bearer DEMO-AGENTICRAIL-PUBLIC-2026" }
(Invoke-WebRequest -UseBasicParsing -Uri https://api.agenticrail.nz/v1/evaluate -Method POST -Headers $headers -Body $body).Content
```

`ts_ms` is a required field — the current Unix time in milliseconds, within 300 seconds of server time. The snippets generate it for you. Note: `date +%s%3N` is GNU-only; the cross-platform form `$(( $(date +%s) * 1000 ))` works on macOS and Linux.

 javascript

```
// One gate call — adapt into your agent loop
const res = await fetch('https://api.agenticrail.nz/v1/evaluate', {
 method: 'POST',
 headers: {
 'Content-Type': 'application/json',
 'Authorization': 'Bearer DEMO-AGENTICRAIL-PUBLIC-2026',
 },
 body: JSON.stringify({
 schema_version: '1.0',
 model_id: 'my-agent',
 sequence_id: 'my-seq-' + Date.now(),
 step: 'verify_identity',
 function: 'verify_identity',
 action_type: 'CHECK_STATE',
 action: 'verify identity',
 nonce: crypto.randomUUID().replace(/-/g, '').slice(0, 16),
 ts_ms: Date.now(),
 inputs: {},
 step_order: ['verify_identity', 'assess_risk', 'execute_transfer', 'audit_ledger'],
 }),
});

const gate = await res.json();

if (gate.decision === 'ALLOW') {
 // Proceed with your step
} else {
 // Halt — do not proceed
 console.error('DENY:', gate.reasons);
}
```

**No SDK is required.** The gate is a plain HTTPS JSON call, exactly as above, so any language that can POST can use it. These packages wrap that call for convenience and ship the integrations below.

 SDKs — Python and JavaScript

```
# Python — ships LangGraph and CrewAI integrations
pip install agenticrail

# JavaScript / TypeScript — dual ESM + CJS, works with LangGraph.js, Mastra, Genkit
npm install @agenticrail/core
```

Both are MIT-licensed and open source. Evaluate against the live gate with the public demo key above — no account, no signup. `step_order` is sent on every call; the gate reads it from each payload and does not store it.

Response reference

## ALLOW or DENY. Nothing in between.

The wrapper returns a flattened response with all decision details at the top level. There is no `pack` wrapper — the `decision`, `reasons`, and `executed` fields are directly in the response object. The nested `receipt` object carries the receipt metadata for that decision — `key_id`, `signature_alg`, `payload_hash`, and `version`.

✓ ALLOW — step accepted

```
{
 "decision": "ALLOW",
 "executed": true,
 "pack_id": "80fe6e6887ca024d2325260f83224c86c3d2157b10ef60cc73ee8fded4661552",
 "reasons": [],
 "sequence_id": "demo-test-seq-001",
 "step": "verify_identity",
 "function": "verify_identity",
 "action_type": "CHECK_STATE",
 "model_id": "client:demo",
 "result": {
 "status": "submitted",
 "data": {
 "state": null
 }
 },
 "receipt": {
 "pack_id": "80fe6e6887ca024d2325260f83224c86c3d2157b10ef60cc73ee8fded4661552",
 "key_id": "k2_2026-06-07_ed25519",
 "signature": null,
 "signature_alg": "Ed25519",
 "payload_hash": "201031e1bce583b179f7b9b8b9c794de2cd8514da84adae974232ed3f2ff0774",
 "prev_receipt_id": null,
 "ts_ms": 1780732058107,
 "version": "slp8_receipt_v2",
 "attestation": null
 },
 "log": {
 "ok": true,
 "error": null
 }
}
```

✗ DENY — sequence violation

```
{
 "decision": "DENY",
 "executed": false,
 "pack_id": "1493ba42f5e0ffb81227e700eda1e03e762058fd9da4080f320c432b6fa23c2f",
 "reasons": ["SEQUENCE_VIOLATION"],
 "sequence_id": "demo-replay-test-seq",
 "step": "execute_transfer",
 "function": "execute_transfer",
 "action_type": "CHECK_STATE",
 "model_id": "client:demo",
 "result": {
 "status": "skipped",
 "message": "No execution triggered"
 },
 "receipt": {
 "pack_id": "1493ba42f5e0ffb81227e700eda1e03e762058fd9da4080f320c432b6fa23c2f",
 "key_id": "k2_2026-06-07_ed25519",
 "signature": null,
 "signature_alg": "Ed25519",
 "payload_hash": "9f2c1a77b4e83d0516a8c4f9e2b7d3061c5a8e94f0b2d6713a9e4c8051f7b2d4",
 "prev_receipt_id": "80fe6e6887ca024d2325260f83224c86c3d2157b10ef60cc73ee8fded4661552",
 "ts_ms": 1780732061488,
 "version": "slp8_receipt_v2",
 "attestation": null
 },
 "log": {
 "ok": true,
 "error": null
 }
}
```

**About the signature.** The inline `receipt` carries the decision metadata and the `payload_hash`. The signature itself is finalized in the durable receipt written to storage — it is not echoed in the synchronous response, so the calling system cannot verify it at the moment of decision, only afterward. That's deliberate: the synchronous path stays lean, and every verification is forced through the one durable, tamper-evident record rather than trusting an ephemeral API response. To verify it, call [report.agenticrail.nz](https://report.agenticrail.nz) — the compliance report includes each receipt's raw `signature` (base64) and its exact `signed_canonical` preimage, so you can run `ed25519_verify(public_key, signed_canonical, signature)` yourself, entirely offline, against the published key at [/spec/receipt-public-keys.json](https://agenticrail.nz/spec/receipt-public-keys.json) — no callback to AgenticRail, no trust in our own verification claim required.

Reason code

Meaning

SEQUENCE_VIOLATION

Step arrived out of order — e.g. `execute_transfer` before `verify_identity` has completed.

REPLAY_NONCE

Nonce has already been used. Generate a fresh nonce per request.

STALE_TIMESTAMP

Timestamp (ts_ms) is outside the allowed ±300 second window from current time. Always generate ts_ms fresh using Date.now() or equivalent.

SEALED_SEQUENCE

This sequence has already been completed. Start a new `sequence_id`.

ACTION_NOT_ALLOWED

`action_type` is not in the allowed set for this function/step.

UNKNOWN_STEP

`step`/`function` is not present in this sequence's own declared `step_order`. An unrecognised name alone does not deny — it falls through to a permissive generic policy so custom `step_order` sequences work. Only a name absent from your declared `step_order` is rejected. *(Corrected 2026-07-05 — supersedes the previously-documented but unreachable `NO_POLICY_MATCH`.)*

FUNCTION_STEP_MISMATCH

`function` and `step` fields do not match.

ARTIFACT_UNBOUND

A witness step's `attestation.witnessed_pack_id` did not match the real prior receipt — missing, wrong, or unverifiable against the durable record.

STEP_ORDER_MISMATCH

The `step_order` sent differs from the one this sequence was opened with. The declared order is locked on the first call, so a later call cannot shorten it to skip a required step. If the process genuinely changed, start a new `sequence_id`.

missing_*

Required field absent — e.g. `missing_function`, `missing_action_type`, `missing_nonce`.

Every code above arrives as an entry in the `reasons` array of a **DENY**, and every DENY is written to a signed receipt. A request can also be refused *before* it reaches enforcement, in which case you get a HALT instead. Those are a different class, and they are listed next.

HALT

## Refused at the door. No receipt.

**HALT is not an enforcement decision.** ALLOW and DENY are decisions: the gate evaluated your step against the sequence and reached a verdict, and either way a signed receipt is written before your action runs. HALT means the request was rejected at the boundary — malformed, oversized, unauthenticated, or matching a prompt-injection pattern — and never reached the enforcement engine at all.

**A HALT produces no receipt.** Nothing was decided, so there is nothing to sign or store. If you are reconciling receipts against calls, HALTed calls will have no corresponding receipt, and that is correct behaviour, not a gap.

A HALT is returned with a non-2xx HTTP status and carries `status` rather than `decision`:

HALT response

```
{
 "status": "HALT",
 "halt_gate_step": 1,
 "reason_code": "SCHEMA_VIOLATION",
 "reason_detail": "REJECT_ROLE_DIRECTIVES"
}
```

`reason_code` is the bucket; `reason_detail`, when present, is the specific trigger.

reason_code

Meaning

UNAUTHORIZED

401. Missing or invalid credentials. `reason_detail` is `MISSING_KEY` or `BAD_KEY`. On the public API this means the `Authorization: Bearer` header.

SCHEMA_VIOLATION

The body failed hardening before parsing. `reason_detail` carries the trigger: `BAD_CONTENT_TYPE` (415), `BODY_TOO_LARGE` (413), `BAD_JSON` (400), `BODY_READ_ERROR` (400), or one of the injection patterns below (403).

 ↳ REJECT_ROLE_DIRECTIVES

The body contains role-directive text of the kind used in prompt-injection attempts.

 ↳ REJECT_BASE64_BLOBS

A base64-shaped string over 40 characters. Payloads are metadata, not carriers. Not applied to `attestation`, which legitimately holds hashes and IDs.

 ↳ REJECT_YAML_FRONT_MATTER

YAML front-matter markers, matched both as real newlines and as the escaped `\n` that appears in JSON-stringified bodies.

 ↳ ATTESTATION_TOO_LARGE

The `attestation` object exceeds its size cap.

 ↳ ATTESTATION_TOO_DEEP

The `attestation` object nests deeper than the allowed depth.

METHOD_NOT_ALLOWED

405. Request was not a POST.

NOT_FOUND

404. Unknown path.

DEMO_LIMIT

413. The demo key has a tighter body-size cap than a production key.

Three rejections happen earlier still, at the public wrapper, and return a plain `error` field rather than a HALT envelope: `invalid_api_key` (401) when a real key prefix is presented with the wrong secret, `invalid_json` (400) when the body will not parse, and `rate_limited` (429) when you exceed your rate limit. Treat all of these the same way you treat a HALT: the call did not reach enforcement, and there is no receipt.

**Sending no key is not one of them.** An unrecognised credential — no header at all, a placeholder, or a key that was never issued — does not fail. The call runs on the public demo lane and the response says so, carrying `lane`, `lane_reason` and `lane_notice`. Only a *recognised* key presented wrongly is refused: a wrong secret returns 401, a revoked key returns 403. The trade is that a demo-lane sequence is prefixed `demo-` and its report can be read by anyone holding the sequence id, so nothing private belongs in `attestation`.

Sequence rules

## The rules the gate enforces.

These aren't soft guidelines. A violation on any one of them returns DENY immediately.

**Steps must run in the configured order.** No skipping. Each step must follow the one before it — for example, `verify_identity` → `assess_risk` → `request_approval` → `execute_transfer`. An out-of-order step returns `SEQUENCE_VIOLATION`.

**Nonces are single-use.** Each request must supply a unique nonce. Reusing any nonce — even from a prior sequence — returns `REPLAY_NONCE`.

**function and action_type must be valid.** `function` must match `step`. `action_type` must be in the allowed set for that function. Invalid combinations return `ACTION_NOT_ALLOWED` or `FUNCTION_STEP_MISMATCH`.

**Sequences seal after completion.** Once `settle` is accepted, the sequence locks. Any further request on that `sequence_id` returns `SEALED_SEQUENCE`. Start a new sequence with a fresh ID.

**Only POST is accepted.** GET, PUT, PATCH and all other methods return `METHOD_NOT_ALLOWED` immediately.

Attestation

## Embed evidence in the receipt.

Each step can carry an `attestation` object — arbitrary evidence that travels with the request and gets **signed into the R2 receipt**. Use it to prove what happened at each step: an AML check passed, a human approved the action, an external system returned a specific result.

The attestation is stored alongside the receipt and appears in every compliance report generated for that sequence. It's not a separate log entry — it's part of the cryptographic chain.

 Python — attestation per step

```
from agenticrail import RailClient
import time

client = RailClient(api_key="DEMO-AGENTICRAIL-PUBLIC-2026")
seq = client.sequence("payment-run-001", [
 "verify_identity", "assess_risk", "request_approval",
 "execute_transfer", "audit_ledger"
])

# Attach evidence at each step — signed into the receipt
seq.next("verify_identity", attestation={
 "kyc_provider": "acme-kyc",
 "result": "pass",
 "checked_at": int(time.time() * 1000),
})

seq.next("assess_risk", attestation={
 "risk_score": 23,
 "threshold": 50,
 "decision": "below_threshold",
})

seq.next("request_approval", attestation={
 "approved_by": "risk-committee-id-7f3a",
 "approval_ref": "APR-2026-00412",
})

seq.next("execute_transfer") # attestation optional — omit if nothing to prove
seq.next("audit_ledger") # seals sequence — all attestations locked in chain
```

 JavaScript — attestation per step

```
import { RailClient } from "@agenticrail/core";

const client = new RailClient({ apiKey: "DEMO-AGENTICRAIL-PUBLIC-2026" });
const seq = client.sequence("payment-run-001", [
 "verify_identity", "assess_risk", "request_approval",
 "execute_transfer", "audit_ledger"
]);

// Attach evidence at each step — signed into the receipt
await seq.next("verify_identity", {
 attestation: { kyc_provider: "acme-kyc", result: "pass", checked_at: Date.now() }
});

await seq.next("assess_risk", {
 attestation: { risk_score: 23, threshold: 50, decision: "below_threshold" }
});

await seq.next("request_approval", {
 attestation: { approved_by: "risk-committee-id-7f3a", approval_ref: "APR-2026-00412" }
});

await seq.next("execute_transfer"); // attestation optional
await seq.next("audit_ledger"); // seals sequence — all attestations locked in chain
```

The `attestation` field accepts any plain JSON object. Values can include strings, numbers, and nested objects. Large binary blobs are not supported — store those in your own system and include a reference ID or hash here instead.

Compliance Reports

## One command. Full provenance report.

The report worker reads every receipt for a sequence, verifies the cryptographic chain, and produces a human-readable compliance report. This is the deliverable your lawyer, auditor, or regulator asks for — proof of what ran, verified independently of what the agent claims.

Not a log export. Chain-verified receipt evidence, generated on demand for any sequence.

01

Request a report

**Endpoint:** `POST https://report.agenticrail.nz/report`

 **Headers:** `Content-Type: application/json`, `x-slp8-key: <key>`

 **Body:** `{ "sequence_id": "your‑sequence", "format": "html"|"json" }`

 Demo key restricts to sequences prefixed `demo‑`. Production key accesses any sequence.

02

Report generation

Worker scans R2 for all receipts matching the sequence ID, verifies each pack ID hash (multi‑generation logic), validates the receipt chain, and composes a deterministic `enforcement_summary` from the resulting counts. **No language model is involved anywhere in report generation** — the same inputs always produce byte-identical text, so the summary reproduces like the rest of the document.

03

Output formats

**HTML:** Full‑page report with cover, sequence summary, enforcement log, chain proof, and the deterministic enforcement summary.

 **JSON:** Structured data containing all verified receipts and verification results.

 Read‑only; no state mutation.

 curl — generate HTML report

```
# Replace SEQUENCE_ID with your sequence (demo‑ prefix for demo key)
curl -X POST https://report.agenticrail.nz/report \
 -H 'Content-Type: application/json' \
 -H 'x-slp8-key: DEMO-AGENTICRAIL-PUBLIC-2026' \
 -d '{
 "sequence_id": "demo‑my‑seq‑001",
 "format": "html"
 }'
```

Reports are deterministic — the same sequence always yields identical output. Verification uses multi‑generation hash checking to handle Gen‑1 and Gen‑2 receipts.

Compliance Evidence

## What the receipt chain proves — and to whom.

Every gate call produces enforcement output (ALLOW/DENY). It also produces a compliance record — a signed, chained, tamper-evident receipt that answers the question regulators and lawyers actually ask: *"Can you prove what the AI did?"*

These are the same facts. Different audience, different frame.

Engineering question

"Did the agent proceed correctly? Was the step blocked? Why?"

Answered by the gate decision: `ALLOW`, `DENY`, reason codes.

Compliance question

"Can you prove what the AI did last Tuesday — not what it reported, what it actually executed?"

Answered by the receipt chain: signed, chained, tamper-evident.

### Receipt field reference — what each field proves

 | Receipt field | What it proves |
 | pack_id | Unique identifier for this enforcement decision — the canonical reference for this chain link. |
 | signature (Ed25519) | Tamper evidence. An Ed25519 signature (base64) over the canonical receipt, verifiable offline against the published public key (/spec/receipt-public-keys.json). If the receipt was altered after writing, verification fails. Legacy receipts before 2026-06-07 use HMAC-SHA256. |
 | prev_receipt_id | `pack_id` of the previous receipt — an identifier reference establishing chain order. On its own, proves something with that identifier came before; see `prev_receipt_hash` below for content-tamper protection. |
 | prev_receipt_hash | SHA-256 of the previous receipt's full canonical JSON, signature included (added 2026-07-08). An in-place edit to any earlier receipt breaks this link even if `prev_receipt_id` references still match — this is what actually invalidates the report on tampering. Null for the chain's first receipt and for any link whose anchor predates this field. |
 | ts_ms | Timestamp to the millisecond — when the gate decision was made. Written at enforcement time, not retrieved or reconstructed later. |
 | payload_hash | SHA-256 of the raw request body — the fingerprint of your payload, not the payload itself. Your agent's input data never enters receipt storage. An auditor can verify the receipt is cryptographically bound to a specific payload without ever seeing that payload's contents. |
 | attestation | Per-step evidence signed into the receipt — AML check results, human approval tokens, risk scores, KYC references. Proves what justified this specific decision. |

Key distinction

Logs are self-reported — the AI agent tells you what it did. Receipts are structural — the gate wrote them before the agent acted, independent of the agent's own reporting. An auditor cannot distinguish a genuine log from a reconstructed one. They can verify a receipt chain cryptographically. That difference is what makes AgenticRail evidence rather than documentation.

Next steps

## Ready to go further?

The demo key is open for testing, and you can [drive the gate in the browser](https://agenticrail.nz/demo/) first — skip a step, replay one, and watch it get refused before you write any code. When you're ready for production — dedicated rate limits, private key, support, and integration help — get in touch.

### Get a production key

No rate limits. Private key. Direct support. Contact us and we'll have you set up within 24 hours. [hello@agenticrail.nz →](mailto:hello@agenticrail.nz)

Wiring this up from code, or pointing an agent at it? The machine-readable API description is published as OpenAPI 3.1 at [agenticrail.nz/openapi.json](https://agenticrail.nz/openapi.json) — every endpoint, the full payload contract, all eight denial codes and the response schemas. It is linked as `service-desc` from [/.well-known/api-catalog](https://agenticrail.nz/.well-known/api-catalog), so a client that follows RFC 9727 discovery will find it without being told. Framework integrations: the Python SDK ships LangGraph and CrewAI adapters, the JavaScript SDK covers LangGraph.js, Mastra and Genkit, and MCP clients can call the gate as a tool at [mcp.agenticrail.nz](https://mcp.agenticrail.nz/).

Working out whether this fits at all, rather than how to call it? The [product overview](https://agenticrail.nz/product/) sets out what AgenticRail is in one page: what it enforces, what a receipt contains, what it is used for — EU AI Act Article 12 record-keeping, provable human oversight and sign-off, segregation of duties — how it sits alongside observability, guardrails and orchestration, and what it does not do.

Blunt questions — whether you can self-host, who holds the signing keys, what certifications we do and don't have, and what a receipt does not prove — are answered on the [FAQ](https://agenticrail.nz/faq/).

Looking for the formal side instead? The [enforcement specification](https://agenticrail.nz/spec/) (versioned, fingerprinted, frozen) and the published briefs — [evidence completeness](https://agenticrail.nz/spec/completeness/), [provable safeguards for automated decisions](https://agenticrail.nz/spec/enforceable-safeguards/), sector gap analyses for [NZ health](https://agenticrail.nz/spec/nz-health/) and [NZ education](https://agenticrail.nz/spec/nzqa-nz-education/) — all live under [/spec/](https://agenticrail.nz/spec/).
