BETA · LIVE NETWORK

Cinchor

Independent, tamper-evident proof of what an autonomous agent did.

As soon as an AI agent can spend money or take an action it can't take back, somebody is accountable for that decision — and "trust our internal logs" stops being good enough the moment an outsider has to rely on the record. Cinchor is the accountability layer: it enforces what an agent is allowed to do in real time, and attests what it did to an independent chain in a form that can't be edited after the fact and that anyone can verify.

What it is (and isn't)

Cinchor is a thin layer you wrap around an agent's risky actions. Two jobs:

It is not another logging vendor. The point is precisely that it is not your system or ours — an in-house audit trail can always be quietly rewritten ("we reviewed our own logs and found nothing wrong"). A record on an independent chain can't.

Core concepts

TermWhat it means
CapabilityA policy granted to an agent — e.g. "may spend up to 1000, for the next hour, to these counterparties." Issued once, enforced on every action.
EnforceA real-time check of one action against the capability. Returns allowed: true/false with a reason (e.g. over_budget).
AttestCommit a decision's context fingerprint (a hash of what happened) + the verdict to the chain. The full record lives off-chain; only the fingerprint is committed.
VerifyRecompute the fingerprint from a record and check it against the on-chain commit. Match = intact. Mismatch = the record was altered.

Finality — included vs settled

Cinchor records commit to a chain that runs two cadences: throughput blocks every 3 seconds carry the transactions, and every 9 minutes a BFT security block anchors the range behind it with a quorum certificate. So the finality of a record is a binary you check, not a confirmation depth you pick.

StateWhat it means
IncludedThe record's tx is in a throughput block (~3s after submit). Reorging an included block requires ≥1/3 of validator stake to equivocate — detectable, attributable, and slashed. This is the state the enforce path reads.
SettledThe block's anchoring security block has a quorum certificate — BFT-final, irreversible. Worst case one security interval after inclusion.

What a fresh read means at execution time: enforce evaluates against the latest included state. A revocation that committed 3 seconds ago refuses the next action — safety-critical state is never held back for settlement. Evidence grades at settlement: a record you hand to an auditor or counterparty carries its chain position, and whether that position is final is machine-checkable.

Both fields are first-class on the API, on operations (GET /v1/operations/{id}) and on the verify response:

{
  "status": "committed",
  "txHash": "txn_eaecf9bb…",
  "blockNumber": 4129,     // the throughput block carrying the tx
  "settled": true          // its anchoring security block is certified
}

settled is computed at read time against the chain's security frontier — poll the operation and watch it flip. If two parties disagree about whether a revocation was final, that reduces to checking one bit against the chain, not an argument about caches.

The walkthrough

The interactive playground runs the whole lifecycle against the live network in about two minutes. Here's what each step proves:

  1. Issue a capability — give the agent a 1000 budget for an hour.
  2. Allowed action (500)allowed:true. Under budget, the agent proceeds.
  3. Disallowed action (5000)allowed:false, over_budget. The policy refuses it in real time.
  4. Attest the decision → its fingerprint is committed on-chain.
  5. Verify → the recomputed fingerprint matches the chain. The record is intact.
  6. Tamper — submit a different version of events (wired 999999 to an attacker) → ok:false. The faked record produces a different fingerprint that doesn't match the chain. Caught.

Step 6 is the whole thesis in one call: there is no version of the record anyone — including Cinchor — can rewrite without the check failing.

Quickstart — two tiers

Tier 1: verify without trusting us (no key, ~15 lines). This checks a real on-chain record from your own terminal, then proves tampering is caught. If you only run one thing, run this.

// verify.mjs — verify a real AI-agent decision on Cinchor. No signup, no key. (node >= 18)
const record = {
  agent: "support-copilot", decision: "approve_refund", order_id: "A-4471",
  amount_usd: 240, policy: "auto-approve refunds <= 250 USD; above requires a human",
  authorized_by: "policy://refunds/v3", result: "approved",
};
const verify = (context) =>
  fetch("https://api.cinchor.com/proof/verify", {
    method: "POST", headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ context }),
  }).then((r) => r.json());

console.log("as recorded:", await verify(record));                          // ok: true
console.log("tampered:   ", await verify({ ...record, amount_usd: 2400 })); // ok: false

node verify.mjs → the recorded context returns ok: true; the tampered one returns ok: false with a different recomputed hash. Nothing in that loop requires trusting our server to be honest.

Tier 2: give an agent a budget and watch the refusal (beta key). The second identical spend crosses the cap and comes back { allowed: false, reason: "over_budget" } — enforcement, not flagging. Keys: beta@cinchor.com.

// quickstart.mjs — give an agent a budget, watch it get refused, prove what happened.
const KEY = process.env.CINCHOR_API_KEY;              // get one: beta@cinchor.com
const api = (path, body) =>
  fetch("https://api.cinchor.com" + path, {
    method: body ? "POST" : "GET",
    headers: { "X-API-Key": KEY, "Content-Type": "application/json" },
    body: body && JSON.stringify(body),
  }).then((r) => r.json());
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

const cap = await api("/v1/capabilities", { maxSpend: 100, ttlSeconds: 3600 });
while ((await api(`/v1/capabilities/${cap.capabilityId}`)).Status !== 1) await sleep(3000);
console.log(await api(`/v1/capabilities/${cap.capabilityId}/actions`, { amount: 60 })); // allowed
await sleep(15000);
console.log(await api(`/v1/capabilities/${cap.capabilityId}/actions`, { amount: 60 })); // over_budget

Both snippets are exercised against production before every docs update. The full lifecycle (attest → verify → tamper → revoke) is below in the SDK section and in sdk-js/examples/full-flow.ts.

SDK — drive it from code

The playground is one way in, not the only one. @cinchor/sdk talks straight to the chain — nothing you do is locked to our UI. It drives the entire lifecycle (mint → enforce → attest → verify), and the hosted gateway and the SDK are simply two paths to the same network. Published for TypeScript, Python, and Go.

npm i @cinchor/sdk @omne/sdk
import { CinchorClient, Verdict, EnforcementCode } from '@cinchor/sdk';
import { Wallet } from '@omne/sdk';

const cinchor = await CinchorClient.connect({
  network:  { name: 'ignis', chainId: 3, rpcUrl: 'https://…' },   // read-only RPC is enough to verify
  contract: { name: 'cinchor_permissions', address: 'om1z…' },
});

const principal = Wallet.fromMnemonic(PRINCIPAL).getAccount(0);
const agent     = Wallet.fromMnemonic(AGENT).getAccount(0);

// 1. principal grants the agent a scoped policy
const { capabilityId } = await cinchor.mintCapability({
  principal, agent: agent.address, maxSpend: 1000n, ttlSeconds: 3600,
});

// 2. enforce actions — allowed under budget, refused over it
const ok = await cinchor.enforce({ capability: capabilityId, agent, amount: 500n });   // ok.allowed === true
const no = await cinchor.enforce({ capability: capabilityId, agent, amount: 5000n });  // no.code === EnforcementCode.OverBudget

// 3. attest the decision on-chain
const decision = { action: 'wire', amount: 500, to: 'acme' };
const { attestationId } = await cinchor.attest({
  capability: capabilityId, agent, context: decision, verdict: Verdict.InPolicy,
});

// 4. verify it YOURSELF — the SDK recomputes the fingerprint locally and reads
//    the on-chain commit directly; Cinchor's gateway is never in the loop.
const real     = await cinchor.verifyAttestation(decision, attestationId);                 // real.ok === true
const tampered = await cinchor.verifyAttestation({ ...decision, amount: 999999 }, attestationId); // tampered.ok === false

That's the project's actual end-to-end example (sdk-js/examples/full-flow.ts), which doubles as a live smoke test against a running node.

Verify it yourself — with zero trust in us

In the playground, the verify call is convenient — but we recompute the fingerprint for you. The stronger claim, the one that matters, is that you recompute it and check it against the chain with no Cinchor in the loop. That's exactly what verifyAttestation() above does: it canonicalizes your copy of the decision, hashes it locally, and compares against the on-chain commit it reads directly from Omne.

The fingerprint canonicalization is byte-identical across TypeScript, Python, and Go — an attestation written by one verifies under another. (The hosted gateway additionally salts the fingerprint so a tenant can crypto-shred its own audit context later; the SDK path uses the raw context, which is what makes it independently recomputable.) Want a read-only RPC to point it at? Ask — that's all the verify path needs.

Dashboard

Everything you do in the playground shows up at app.cinchor.com (your API key) — capabilities, enforced actions, and the audit trail of attestations with their on-chain commits.

Architecture (the short version)

FAQ

Is this a real blockchain, or a demo database?

A real, running network. Every attestation in the playground is a live on-chain commit; the verify step reads the actual chain. This is a closed beta on Omne's test network — real chain, test value (no real money moves).

Why does it need a blockchain at all?

Independence + immutability. The value is that the record isn't yours or ours — neither party can rewrite it. A shared, append-only chain is the mechanism that makes that true; the tamper step shows it failing the instant a record is altered.

What can the agent actually be stopped from doing?

Today: budget caps, time-to-live, and counterparty allowlists, enforced per action. The model generalizes to any policy you can express over an action's parameters.

Who holds the keys / the money?

You hold the principal (non-custodial). Agent keys are gateway-managed for convenience on the hosted path, or self-held on the SDK path. Cinchor never custodies your funds.

What's demo vs production-ready here?

The enforce/attest/verify core is real and working end-to-end. This is a beta: it runs on a test network, the validator set is small, and hardening (scale, audits, SLAs) is ahead of us. It's meant to let you use the thing, not to run production traffic yet.

My request hung or errored — what happened?

The beta runs on a small mesh; under load a request can occasionally time out. Wait a moment and retry the step — the chain state is unaffected.


Questions are welcome async — we answer fast. When you're ready, try it ↗.