DCS LABS · R+2 · OPEN PROVENANCE STANDARD

An open standard for
cryptographically signed
AI agent action receipts.

R+2 specifies how an AI agent's actions are signed, hash-chained, and made independently verifiable — without trusting the issuing vendor. The standard is free, open under MIT, and designed for adoption by governments, enterprises, and any AI vendor that needs to make its agents auditable.

Draft v0.1 Status: Published 2026-05-19. First production receipt emitted 2026-05-20 (Base mainnet). Submitted to Anthropic Standards Program, MeitY (India), and ISRO for review.
NEW · v0.1 · MAY 20, 2026
R+3 · Tamper-Evident Audit Export
Aggregate R+2 receipts into Merkle-rooted, signed, on-chain-anchored audit bundles. The compliance layer regulators need.
Read R+3 spec
NEW · v0.1 · MAY 20, 2026
R+4 · Federated Zero-Knowledge Verification
Prove compliance over R+3 bundles without revealing the receipts. Multi-issuer, privacy-preserving. ~200-byte proofs, < 10 ms to verify. The federation layer.
Read R+4 spec
Version
v0.1 · 2026-05-19
Licence
MIT · free to adopt
Reference impl
@trdnetwork/mcp-server
Editor
DCS AI Technologies

§1 At a glance #

An AI agent performs an action. The action is wrapped in a receipt. The receipt is signed with ed25519, links to the agent's previous receipt by content hash, and is published either inline or to IPFS. Any consumer — a regulator, a downstream system, a citizen filing an RTI request — can independently verify three things:

  1. Identity: the action was performed by the agent identified by this public key.
  2. Integrity: the action data hasn't been altered since it was signed.
  3. Sequence: this action is part of an unbroken chain of actions from this agent, with no gaps and no replacement.

That's it. The rest of this document specifies exactly how to produce, transport, and verify such a receipt — with no ambiguity, so that two independent implementations will interoperate.

Why this standard exists AI agents are about to do real economic work — sign contracts, hold budgets, negotiate with other agents, present audit trails to regulators. Today, no shared open standard defines what an agent's "action receipt" looks like. R+2 is our answer. It's deliberately minimal: small enough for a junior engineer to implement in two days, complete enough for a regulator to use as evidence.

§2 Scope & non-goals #

In scope

Explicitly out of scope

§3 Terminology & conformance #

The keywords MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, and RECOMMENDED in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Defined terms

TermDefinition
AgentAn autonomous software process identified by a stable ed25519 public key, capable of producing R+2 receipts.
IssuerThe party operating an Agent. Often a company or a person. Not the same as the Agent itself.
ReceiptA signed JSON object conforming to the schema in §4, recording a single Action.
ActionAn event performed by an Agent that the Issuer chooses to record. Any tool call, API call, computation, or business event qualifies.
VerifierAny party — including regulators, consumers, or other agents — who independently checks a Receipt's validity.
CIDContent Identifier. A hash-derived identifier for a piece of data. R+2 uses SHA-256 hex by default; IPFS CIDs MAY be used when receipts are pinned.
ChainThe ordered sequence of Receipts from a single Agent, linked by prev_receipt_cid.

§4 The Action Receipt schema #

A conforming Action Receipt is a JSON object with exactly the following top-level fields. Implementations MUST NOT add unknown top-level fields; extensions go inside the extensions object (§11).

FieldTypeDescriptionRequired
spec_versionstringThe R+2 version this receipt conforms to. MUST be the string "r2/v0.1" for this revision.MUST
agent_pubkeystringThe agent's ed25519 public key, base64url-encoded (RFC 4648 §5), no padding. Exactly 43 characters.MUST
agent_idstringA short human-readable identifier for the agent. SHOULD be unique within the Issuer's namespace.MUST
action_idstringA UUIDv4 (RFC 9562) identifying this specific Action. Globally unique.MUST
action_typestringA short, slash-namespaced action category (e.g. "memory/write", "payment/settle", "tool/call").MUST
action_dataobjectThe substantive payload of the action. Schema is application-defined. MUST be a JSON object.MUST
occurred_atstringRFC 3339 timestamp with timezone offset. Resolution to milliseconds RECOMMENDED.MUST
prev_receipt_cidstring | nullThe CID of the immediately preceding receipt from this agent. null for the first receipt only.MUST
noncestring16 bytes of random data, base64url-encoded, no padding. Prevents signature reuse across identical action bodies.MUST
extensionsobjectImplementation-defined fields. MUST be a JSON object. MAY be empty ({}).MUST
signaturestringed25519 signature of the canonical JSON of the receipt with signature field excluded. Base64url-encoded, no padding. Exactly 86 characters.MUST

Example (unsigned form)

{
  "spec_version":     "r2/v0.1",
  "agent_pubkey":    "u4yK_lH8Z6vJ3qZ5tNwQpRz_aBcDeFgH1iJ2kL3mN4o",
  "agent_id":        "0001",
  "action_id":       "3f8a7c12-8b91-4e2c-9b3a-5f7d8e1a2c4b",
  "action_type":     "memory/write",
  "action_data": {
    "memory_id":   "mem_a83f12cd",
    "content_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "embedding_model": "text-embedding-3-large",
    "embedding_dim": 1536
  },
  "occurred_at":     "2026-05-19T15:42:08.123Z",
  "prev_receipt_cid": "sha256:bafy2bzaceabc...",
  "nonce":           "k3J9p2qR7sT5vXyA",
  "extensions": {}
}
Note on action_data We deliberately do not standardize action_data contents at this layer. The whole point of R+2 is to be a substrate that any sector can build on. Healthcare receipts will contain PHI references; finance receipts will contain settlement details; AI inference receipts will contain prompt hashes. Sectoral profiles MAY constrain action_data via JSON Schema linked from a registered extension namespace.

§5 Cryptographic primitives #

Signature algorithm — Ed25519

R+2 uses Ed25519 as specified in RFC 8032 §5.1. Implementations MUST use pure Ed25519 (not Ed25519ph or Ed25519ctx). Signature size: 64 bytes (86 chars base64url, no padding). Public key size: 32 bytes (43 chars base64url, no padding).

Hash algorithm — SHA-256

R+2 uses SHA-256 (FIPS 180-4) for receipt content hashes and the chain pointer. SHA-256 hashes appear as hex strings prefixed with "sha256:" in fields where they're stored as JSON values. When transported as IPFS CIDs, they use multibase-encoded CIDv1 with the SHA-256 multihash code.

Encoding — Base64url, no padding

All cryptographic byte strings in R+2 use base64url encoding as defined in RFC 4648 §5, without padding. Two-character base64 padding (==) MUST be omitted. The character set is [A-Za-z0-9_-].

Why these choices

Implementer note Use a vetted library. We RECOMMEND libsodium (C / Rust / Python / Node), @noble/ed25519 (TypeScript), or the standard library's crypto/ed25519 package (Go 1.13+). Do not implement Ed25519 yourself.

§6 Canonical JSON (RFC 8785) #

Signing JSON is harder than it looks. Two JSON serializations of the same logical object may differ in whitespace, key order, number representation, or Unicode escaping — but produce different hashes, and therefore different signatures. To eliminate this ambiguity, R+2 mandates RFC 8785 — JSON Canonicalization Scheme (JCS).

JCS in 6 rules

  1. Object keys are sorted lexicographically (Unicode code-point order).
  2. No insignificant whitespace.
  3. Numbers are serialized using ECMAScript's Number.prototype.toString() algorithm.
  4. Strings use minimum-length escaping (only quote, backslash, and control chars are escaped).
  5. Arrays preserve their original order.
  6. The output is UTF-8.

Implementations MUST use a library that follows RFC 8785 strictly. We RECOMMEND canonicalize (npm), jcs (Go), or the W3C reference TypeScript implementation. Do not roll your own.

§7 Signing flow #

  1. Construct the receipt JSON object with all required fields except signature.
  2. Compute the canonical JSON form (RFC 8785) of the receipt, treating the signature field as if it didn't exist.
  3. Sign the canonical bytes with the agent's Ed25519 private key.
  4. Base64url-encode (no padding) the resulting 64-byte signature.
  5. Insert the encoded signature into the receipt as the signature field.
  6. Serialize the receipt for transport in any preferred encoding. The transport form does not need to be canonical JSON; only the signed bytes do.

Reference signing snippet (TypeScript)

import { ed25519 } from '@noble/curves/ed25519';
import canonicalize from 'canonicalize';
import { Buffer } from 'buffer';

function signReceipt(receipt, privateKey) {
  const { signature, ...unsigned } = receipt;
  const canonical = canonicalize(unsigned);
  const sig = ed25519.sign(new TextEncoder().encode(canonical), privateKey);
  const sigB64 = Buffer.from(sig).toString('base64url');
  return { ...unsigned, signature: sigB64 };
}

§8 Verification flow #

A Verifier receives a Receipt and the agent's expected public key from an identity layer (DNS, on-chain SBT, etc.). The Verifier MUST perform the following checks in order. Any failure means the Receipt is invalid and SHOULD be rejected.

  1. Schema: All required fields from §4 are present, with correct types and value ranges.
  2. Spec version: spec_version equals "r2/v0.1" (or a version the Verifier supports per §11).
  3. Public key match: The agent_pubkey in the receipt equals the public key the Verifier obtained from the identity layer for this agent_id.
  4. Signature: Decode signature from base64url; remove the signature field from the receipt; canonicalize the result per §6; verify the Ed25519 signature over the canonical bytes using the public key from step 3.
  5. Chain: If prev_receipt_cid is not null, the Verifier SHOULD fetch the previous receipt by CID and verify it recursively. The Verifier MAY rely on a previously-verified receipt cached locally.
  6. Timestamp sanity: occurred_at SHOULD be within a reasonable window. Outside ±24h from the verification time, the Verifier MAY flag the receipt for further inspection but MUST NOT reject solely on this basis.

Reference verification snippet (TypeScript)

function verifyReceipt(receipt, expectedPubkey) {
  const { signature, ...unsigned } = receipt;
  if (unsigned.agent_pubkey !== expectedPubkey) return false;
  if (unsigned.spec_version !== 'r2/v0.1') return false;

  const canonical = canonicalize(unsigned);
  const sigBytes = Buffer.from(signature, 'base64url');
  const pubBytes = Buffer.from(expectedPubkey, 'base64url');
  const msg = new TextEncoder().encode(canonical);
  return ed25519.verify(sigBytes, msg, pubBytes);
}
Independent verifiability Note that nothing in this flow requires contacting the original issuer. The Verifier needs only the receipt itself and the agent's public key from the identity layer. This is the whole point: regulators, courts, citizens, and downstream systems can verify without trusting the vendor.

§9 The receipt hash-chain #

Each Receipt's prev_receipt_cid field MUST contain the SHA-256 hash (or IPFS CIDv1 with SHA-256 multihash) of the canonical JSON form of the agent's immediately preceding signed Receipt.

This produces a strict total order over an agent's Receipts and makes any tampering immediately detectable. Specifically:

The first Receipt from an agent MUST have prev_receipt_cid: null. A Verifier MAY choose to record the first receipt's CID separately as a tamper-evidence anchor.

§10 Optional IPFS/Filecoin pinning #

R+2 receipts MAY be pinned to IPFS (and durably backed by Filecoin) to guarantee permanence beyond the issuer's infrastructure. Pinning is OPTIONAL; the standard does not require it.

When pinned:

Why pinning matters for governments A government auditor verifying an AI decision five years after the fact cannot rely on the original vendor still existing. Pinning to Filecoin gives a 10-year (and increasingly, 100-year) durability guarantee independent of the vendor's solvency. This is one of the reasons R+2 includes pinning as a first-class option.

§11 Versioning & extensions #

Spec version

The spec_version field uses the format "r<major>/v<minor.patch>". The current version is "r2/v0.1". Major versions (r2 → r3) MAY introduce breaking changes; minor versions MUST remain backward-compatible.

Extensions

Implementations MAY add fields inside the extensions object. Extension fields MUST use a namespaced key of the form "<org>.<feature>" to avoid collisions. Examples:

Verifiers MUST ignore unrecognized extension fields. Verifiers that understand a specific extension MAY apply additional validation rules to it.

Sectoral profiles

A sectoral profile is a public document specifying:

Profiles are registered at https://dcslabs.ai/standard/profiles/<profile-name>. The first profiles in active drafting: r2-health-v1 (healthcare), r2-gov-v1 (Indian government RTI-compliance), and r2-finance-v1 (cross-border payment provenance).

§12 Worked example #

A complete R+2 signed receipt for a memory-write action, followed by a verification you can run yourself.

The signed receipt

{
  "spec_version":     "r2/v0.1",
  "agent_pubkey":    "u4yK_lH8Z6vJ3qZ5tNwQpRz_aBcDeFgH1iJ2kL3mN4o",
  "agent_id":        "0001",
  "action_id":       "3f8a7c12-8b91-4e2c-9b3a-5f7d8e1a2c4b",
  "action_type":     "memory/write",
  "action_data": {
    "memory_id":    "mem_a83f12cd",
    "content_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "embedding_model": "text-embedding-3-large",
    "embedding_dim":  1536
  },
  "occurred_at":     "2026-05-19T15:42:08.123Z",
  "prev_receipt_cid": "sha256:bafy2bzaceabc1234567890abcdef1234567890abcdef1234567890abcdef00",
  "nonce":           "k3J9p2qR7sT5vXyA",
  "extensions":      {},
  "signature":       "sig_base64url_86chars_no_padding_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Verify it with curl + jq + a one-liner

# Fetch the receipt from the DCS reference implementation
$ curl -s https://api.dcslabs.ai/api/receipts/r2_a83f12cd \
    | jq '.receipt' \
    > receipt.json

# Get the expected public key from the on-chain identity layer (Base mainnet)
$ EXPECTED_PK=$(cast call 0xbDd1f5fC349D9a8EfCEb07Edbd491233b2540f5F \
    "agentPubkey(string)" "0001" --rpc-url https://mainnet.base.org)

# Run R+2 verifier (npm install -g @trdnetwork/r2-verify)
$ r2-verify --receipt receipt.json --pubkey $EXPECTED_PK
✓ Schema valid
✓ Spec version r2/v0.1 supported
✓ Pubkey matches Base mainnet record
✓ Signature valid
✓ Chain pointer matches predecessor (sha256:bafy2bzaceabc...)
✓ Timestamp within window

Receipt verified.

§13 Adoption checklist #

If your organization wants to adopt R+2, here's the minimum work required:

For an AI vendor (issuer-side)

  1. Generate an Ed25519 keypair per agent. Keep the private key in a secrets manager.
  2. Publish the public key to a discoverable identity layer (DNS TXT, on-chain registry, DID document).
  3. For every action your agent takes, construct an R+2 receipt and sign it.
  4. Store receipts in a queryable database (Postgres works fine). Index by agent_id, action_id, and occurred_at.
  5. Expose a public read endpoint for receipt retrieval. GET /receipts/<action_id> returning the JSON.
  6. Optionally pin receipts to IPFS for long-term durability.

For a regulator or downstream consumer (verifier-side)

  1. Establish a process for obtaining the agent's expected public key (typically via the identity layer in use).
  2. Run the verification flow from §8 on every receipt before trusting its claims.
  3. For sensitive decisions, also walk the chain back to a known anchor.
  4. Use the reference verifier (@trdnetwork/r2-verify) or implement your own — both are equally conformant.

A reference implementation written in TypeScript ships with the DCS Labs @trdnetwork/mcp-server npm package. It produces and verifies R+2 receipts by default for every MCP tool call. You can study it as a working example.

§14 Governance & change-log #

Editor

The current editor is DCS AI Technologies L.L.C. Contact: [email protected].

Path to multi-stakeholder governance

R+2 v0.1 is a single-editor draft. The intended trajectory:

DCS Labs will not hold a veto over any future version. The spec is MIT-licenced from v0.1 onward and can be forked at any time.

Change-log

VersionDateChanges
r2/v0.12026-05-19Initial public draft. Submitted to Anthropic Standards Program, MeitY, ISRO.

§15 Frequently asked questions #

Why not use existing standards like Verifiable Credentials (W3C VC)?
W3C VC is excellent for credentials — static claims about an identity. R+2 is for actions — dynamic events produced by an agent at runtime. We considered VC and found that the data-model overhead (issuer, holder, subject, proofs) added cost without value for high-volume action streams. R+2 is deliberately lighter. That said, an R+2 receipt MAY be embedded inside a W3C VC as the credentialSubject if a deployment prefers VC's transport semantics.
What if I want to use a different signature algorithm?
R+2 v0.1 mandates Ed25519. A future R+2 v0.2 or R+3 will likely add an algorithm-identifier field for crypto agility. For now, conforming implementations MUST use Ed25519. If you have a specific need (e.g., FIPS-mode ECDSA), open an issue at github.com/DCS-LabsAI/r2-standard — we'll consider it for the next minor version.
Does R+2 require blockchain?
No. R+2 is chain-agnostic. The reference identity layer DCS Labs uses (a soul-bound token on Base mainnet) is one option for publishing agent public keys. DNS TXT records, DID documents, or even a simple HTTPS key endpoint are all equally valid. R+2 doesn't care how a verifier obtains the public key — only that the verifier obtains it from a source they trust.
How does R+2 differ from R+3?
R+2 specifies how an action is signed. R+3 (draft separately) specifies how a collection of R+2 receipts is exported as a tamper-evident audit trail — the format a regulator receives. R+3 builds on R+2; you cannot have R+3 without R+2 first.
Can I use R+2 without the DCS Labs reference implementation?
Yes, that's the whole point of an open standard. The reference implementation exists to make adoption easy, but any implementation that follows §4-§11 is equally conformant. We expect at least three independent implementations to emerge in 2026.
What's the patent / IP situation?
DCS AI Technologies L.L.C holds no patents covering R+2 and has filed none. The standard is published under MIT. Contributors who submit changes to the spec MUST sign a contribution agreement granting an irrevocable royalty-free patent licence. We're not in this to build a patent thicket.
How do I report a bug in the spec?
Email [email protected] or open an issue at github.com/DCS-LabsAI/r2-standard. Cryptographic or security issues SHOULD be reported privately to [email protected]; we'll coordinate disclosure responsibly.

§16 Contact & contribution #

Comments, corrections, and contributions are warmly welcomed.

For policymakers

If you represent a government agency, regulator, or international body and want to evaluate R+2 for adoption: we'll arrange a 30-minute technical briefing and provide a sector-specific adoption guide. Email [email protected] with your context and we'll respond within 48 hours.