Comptra register of record · 0 voided this session Open the console →
the ledger every agent answers to

agents spendreal money.someone has to sign off.

Cap what every agent can spend, on top of any rail. Seal each decision into a tamper-evident register an auditor can verify. Not a bank. Not a rail.

live policy · per-call cap $5,000 · agent_4a9f1c → openai · $4,200 · SEALED scroll ↓
§01
§01the claim

Your agent has a credit card,
and no ledger holds your agent.

Every rail issues a credential. None owns the layer that decides whether a dollar may move, so the charge clears before anyone signs.

§02
§02the question that stalls the deal

“Your agent moves money.
Prove every payment was authorized — and that the record hasn’t changed since.”

That is what an enterprise security review asks the day your AI touches a card. Most teams answer with a log. A log is the wrong artifact — watch.

spend_log.csv · exported from your own databaseheld by you
agent_4a9f1c , openai , $4,200.00 , approved
// a row anyone with write access can change, then re-export. nothing in the file reveals it.

A log you can edit
is not an audit trail.

§03
§03set the policy, seal the record
per-call cap · drag to cut
$5,000openai
{ vendor: "openai", capPerCall: 5000, allow: [openai, anthropic, aws] }
→ openai
CAP
ALLOW
RATE
daily budget$25,000 remaining
// drop-in · 4 lines
import { gate } from 'comptra'
const ok = await gate({ vendor:'openai', maxPerVendor:5000 })
register of record · hash-chained
#agentvendoramountverdictseal
// set a cap, fire a record. then edit a sealed amount and VERIFY — watch the proof break.
§04
§04the chain & the break

Every seal is computed from its record. Forge one, the chain fractures.

// each seal's guilloché is seeded by its own SHA-256. identical input, identical seal.
§05
§05any rail, same seal

We don't move the money.
We decide if it moves.

provenance · agent_4a9f1c · policy v3 · gate@1.2ms · 2026-06-19T14:22:07Z · sealed
agent_4a9f1c → openai · $4,200 · cap $5,000 → ✓ SEALED
// verified-by Stripe Issuing — the seal is rail-independent. same record, same proof, any rail.

Rails issue. Banks hold. Comptra seals.

§06
§06who answers to the ledger

The agents already spending
your company’s money.

// procurement · media · travel · ops · infrastructure — each one a credential with no ledger behind it. hover to hold the register still.

§07
§07verify without trusting us

Don’t trust Comptra. Verify it.

The proof was never ours to forge. Every record is sealed with the same primitives that secure the open web — and your auditor checks them on their own machine, offline.

integrity
SHA-256 hash-chain
Each record commits to the one before it. Change a byte anywhere and every hash downstream stops matching — the verifier names the exact row.
record_hash = sha256(prev_hash ‖ JCS(record))
inclusion
RFC 9162 Merkle
The same append-only tree that lets the world audit TLS certificate logs. Prove a record is included in O(log n), without re-reading the ledger.
Certificate Transparency v2 · domain-separated
anchor
Ed25519 checkpoints
The Merkle root is signed at intervals. To rewrite history an attacker must forge a signature over a root you already hold. They can’t.
sig(tree_size, root_hash) · your retained key
the part most audit-log vendors hide
If Comptra itself is compromised, the proof still holds. Our servers being breached doesn’t let anyone forge a signature you already hold. The verifier runs client-side — run it against a checkpoint you captured last month and catch us. That is the entire point of the design.
// honest boundary, stated plainly: we don’t stop a compromised agent from making a bad-but-allowed payment — that’s a policy problem, not a ledger problem. we don’t move your money, so reconcile against your issuer. open · split-view defense (witnessed checkpoints) is on the roadmap, not yet shipped.
§08
§08the certificate of audit

The export that unblocks the security review.

comptra · certificate of record
serial (chain root)  
records  0   sealed 0   void 0
PASS — ready for security review
counter-signed · comptra register · v0.1
verify it yourself · the root is in the file
# every record's hash = sha256(prevHash | record)
const ok = chain.every((r,i) =>
  r.hash === sha256(chain[i-1].hash + '|' + canonical(r)))
SOC 2 (in progress)SSO / SAMLRBACself-hosted ledger option
§09

Enter your name in the register.

Pre-product. We onboard teams whose agents already move money.

the ledger every agent answers to.