Skip to main content

Quickstart

This walks through governing a simple agent workflow from scratch. By the end, you’ll have a chain running with policy evaluation, a denied action raising an exception, and a receipt you can verify offline. The whole thing takes about 10 minutes if you have Python 3.10+ ready.

1. Install and configure

pip install proofrail
Get your API key from the ProofRail dashboard and save it to a .env file:
# .env
PROOFRAIL_API_KEY=prail_your_key_here

2. Write a minimal governed workflow

Create a file called first_chain.py:
import asyncio
import os
from dotenv import load_dotenv

import proofrail

load_dotenv()
proofrail.init(api_key=os.environ["PROOFRAIL_API_KEY"])


async def main():
    async with proofrail.Chain("first-workflow") as chain:
        # A safe action — should resolve via the local fast-path
        decision = await chain.record_agent_action(
            agent_name="research-agent",
            action_type="tool_call",
            action_name="search_web",
            payload={"query": "vendor pricing for office chairs"},
        )
        print(f"Search action: {decision.policy_decision} (via {decision.decision_source})")

        # A small purchase — should be allowed
        decision = await chain.record_agent_action(
            agent_name="purchase-agent",
            action_type="tool_call",
            action_name="place_order",
            payload={"amount_usd": 150.00, "vendor": "office-supplies.com"},
        )
        print(f"Small purchase: {decision.policy_decision} (via {decision.decision_source})")


asyncio.run(main())
Run it:
python first_chain.py
You should see two allow decisions, the first via local_fast_path and the second via backend_evaluation (because it contains financial data, which bypasses the fast-path).

3. Trigger an approval gate

Now bump that purchase amount up past the default approval threshold:
decision = await chain.record_agent_action(
    agent_name="purchase-agent",
    action_type="tool_call",
    action_name="place_order",
    payload={"amount_usd": 7500.00, "vendor": "office-supplies.com"},
)
Run the script again. This time, the call will block — the policy engine has decided this transaction needs human approval. You’ll see logs like:
Waiting for approval on chain abc-123... (timeout=24h)
Check your email — the approver address you configured (or your account email by default) just received a message with the chain context and an approve/deny link. Click “Approve” in the email. Your terminal output should resume:
Large purchase: allow (via human_approval)
If you click “Deny” instead, the script raises ActionDeniedError with the approver’s notes attached.

4. View the chain in your dashboard

Open app.proofrail.dev and navigate to Chains. Your first-workflow chain should be at the top of the list with three events recorded:
  • search_web (allow, local fast-path)
  • place_order $150 (allow, backend)
  • place_order $7,500 (require_approval → human_approval allow)
Click into the chain to see the full event timeline, the cumulative metrics, and the receipt that was generated when the chain completed.

5. Verify a receipt offline

Receipts are HMAC-signed and hash-chained across your organization. You can verify any receipt without a network call. From the dashboard, find your chain’s receipt and copy its receipt ID. Then:
import proofrail

proofrail.init(api_key=os.environ["PROOFRAIL_API_KEY"])

# Verify a specific receipt
result = await proofrail.client.verify_receipt("rcp_abc123...")
print(f"Valid: {result.valid}")
print(f"Receipt number: {result.receipt_number}")
valid=True means the receipt’s data matches its signature. Tampering with the receipt content would flip this to False.

You just shipped governance

In under 10 minutes you went from zero to:
  • A real agent workflow under chain-level policy
  • One action resolved locally for speed (fast-path)
  • One action sent to the backend for authoritative evaluation
  • One action gated for human approval, resumed cleanly after the approver clicked through
  • A tamper-evident audit receipt verifiable without network access
That’s the whole core surface. Everything beyond this — framework adapters, custom policies, kill switch, cost tracking — is configuration on top of this same pattern.

Where to go next

Chain-level governance

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

LangGraph adapter

Wrap a compiled LangGraph graph with one line.

MCP adapter

Govern MCP server tool calls.

Configuration

Tune thresholds, fail modes, approvers, and more.
Trouble running this? The most common issues are forgetting dotenv (env var not loaded), running Python 3.9 or earlier (3.10+ required), or hitting Supabase free-tier latency on the first chain start (give it a few seconds). If your approval email never arrives, check your spam folder and verify your approver address in the dashboard.