Skip to main content

Quickstart

This walks through the shortest real path through Arclasp: create an API key, record one governed agent action, approve it from the dashboard, and get back a signed receipt. No policy setup required — a fresh organization’s default threshold handles it. The whole thing takes a few minutes, using only the low-level arclasp.Chain / record_agent_action() API — no framework adapter required.

1. Sign up and create an API key

Sign up at proofrail.dev and open your organization’s dashboard. Create an API key from Settings → API Keys. Keys are prefixed with prail_ and shown once at creation — store yours in a secrets manager or .env file.

2. Install the SDK

3. Initialize the SDK against the hosted backend

The SDK’s backend_url defaults to http://localhost:8000 for local development. To reach hosted Arclasp, pass it explicitly:
If you skip backend_url, the SDK will try to talk to localhost:8000 and fail — this is the single most common setup mistake. See Troubleshooting.

4. Record a governed action

Open a chain and record one action with a payload that deterministically crosses the default approval threshold. A fresh organization’s default policy requires human approval when a single action’s top-level payload amount (amount_usd, amount, or value) exceeds $5,000. No custom policy setup is needed for this — the default applies as soon as your organization exists.
Run it:

5. Approve it from the dashboard

Once record_agent_action() sends the event, the backend flags it as requiring approval ($6,000 > $5,000), and the call blocks — it polls GET /v1/chains/{id}/approval-status roughly every 5 seconds while the chain shows as pending_approval. Leave the terminal running. Open the Arclasp dashboard, find the pending approval, and approve it. The default local wait timeout is 24 hours, configurable with default_approval_timeout_hours — see Configuration.

6. Watch the SDK resume automatically

As soon as you approve from the dashboard, the next poll picks up the decision and record_agent_action() returns with policy_decision="allow" and decision_source="human_approval". Your script continues from where it was blocked — no restart needed. If you deny the action instead, the call raises arclasp.ActionDeniedError. If nobody resolves it within the timeout window, it raises ChainTimeoutError. See Exceptions for the full picture — this page keeps it to the two outcomes you’ll hit most.

7. Completion and receipt

When the async with Chain(...) block exits, the SDK marks the chain complete on the backend, which generates a signed receipt. That’s why chain.receipt() is called after the async with block in the example above — the receipt doesn’t exist until the chain has completed. Two distinct pieces of evidence come out of this flow, and it’s worth keeping them separate:
  • Approval certificate — evidence of the human approval decision itself (who decided, when, and any notes).
  • Chain Record / receipt — evidence for the completed governed chain as a whole, generated once the chain closes.

8. View the Chain Record

Open the chain’s detail page in the dashboard (https://app.proofrail.dev/dashboard/chains/{chain_id}) to see the full event timeline, the approval decision, and the receipt.

9. Public verification (optional)

From the authenticated dashboard, an admin can issue a public verification link for a chain or receipt. That public page exposes only public-safe verification status — no internal token values or private governance data. This is an optional step once you have your first governed action working; it isn’t required to complete this quickstart.

Where to go next

Chain-level governance

The concept that makes Arclasp different from per-call governance tools.

Human approval

The full approval flow: timeouts, fallback approvers, and denial handling.

MCP adapter

Govern MCP server tool calls.

Configuration

Tune thresholds, timeouts, and more.
Trouble running this? The most common issue is forgetting backend_url="https://api.proofrail.dev" — without it the SDK tries localhost:8000 and every call fails to connect. Also check Python 3.10+ is installed, and that the amount in your payload is a top-level key (amount_usd, amount, or value) — a nested payload like {"financial": {"amount_usd": 6000}} will not trigger the threshold.