Version: 0.1 (draft for public comment) Status: Experimental Editor: HAL — Human Accountability Layer (halayer.com) License: Specification text CC BY 4.0 · schemas and reference code Apache 2.0 — free to implement, no royalties, no permission required Canonical URL: https://actionreceipt.com/spec/v0.1
An ActionReceipt is a signed, verifiable, tamper-evident record that an AI agent performed a specific action under a scoped mandate granted by a named, accountable human (the principal).
Money has receipts. Code has commits. AI actions have nothing. As agents move from drafting content to taking actions — sending, scheduling, ordering, quoting, committing — every party involved needs an answer to one question: who stands behind this action, and were they entitled to authorize it?
ActionReceipt is the answer format. It is deliberately minimal: one JSON object, one signature, one verification URL.
A receipt is a JSON object with the following top-level fields:
| Field | Type | Req. | Description |
|---|---|---|---|
spec |
string | ✓ | Spec identifier and version, e.g. "actionreceipt/0.1" |
id |
string | ✓ | Globally unique receipt ID (ULID recommended) |
issued_at |
string | ✓ | RFC 3339 timestamp of issuance |
issuer |
object | ✓ | Who issued and signed this receipt (see 3.1) |
principal |
object | ✓ | The accountable human or legal entity (see 3.2) |
agent |
object | ✓ | The AI system that performed the action (see 3.3) |
mandate |
object | ✓ | The authority under which the action was taken (see 3.4) |
action |
object | ✓ | What was done (see 3.5) |
evidence |
object | Hashes of inputs/outputs (see 3.6) | |
review |
object | ✱ | Human review of the action, when the mandate requires it (see 3.7) |
chain |
object | Link to the previous receipt (see 3.8) | |
verify_url |
string | ✓ | URL where this receipt's current status can be checked |
status |
string | ✓ | Status at issuance: valid | revoked | disputed | settled. Current status MUST be taken from verify_url (see §5) |
✱ review is REQUIRED whenever the governing mandate's review_policy is not none; a receipt missing a required review is invalid regardless of signature.
issuer{
"name": "HAL",
"domain": "halayer.com",
"keys": "https://halayer.com/.well-known/actionreceipt-jwks.json"
}
keys MUST point to a JWKS (RFC 7517) document containing the issuer's public signing keys. Key discovery via https://{domain}/.well-known/actionreceipt-jwks.json is the default convention.
principal{
"name": "Jane Doe",
"role": "Managing Director",
"org": "Example GmbH",
"identity_assurance": "verified",
"principal_id": "hal:principal:01J8ZK…"
}
identity_assurance is one of self_asserted | email_verified | verified (issuer performed identity verification). Counterparties decide how much assurance they require.
agent{
"agent_id": "hal:agent:01J8ZQ…",
"software": "acme-assistant/2.4",
"model": "claude-sonnet-4-6",
"operator": "Example GmbH"
}
model and software are informative, not load-bearing: accountability attaches to the principal and mandate, never to the model.
mandate{
"mandate_id": "hal:mandate:01J8ZR…",
"granted_at": "2026-06-01T09:00:00Z",
"expires_at": "2026-12-01T09:00:00Z",
"scope": ["email.send", "calendar.schedule", "quote.issue"],
"review_policy": "none",
"constraints": {
"quote.issue": { "max_value": 5000, "currency": "EUR" },
"email.send": { "domains_excluded": ["press.*"] }
},
"revocable": true
}
Scopes use dot-notation verbs. Constraints are scope-keyed objects; unknown constraint keys MUST be preserved by intermediaries. A receipt whose action falls outside its mandate's scope/constraints is invalid regardless of signature.
review_policy is one of none | flagged | full, and is set by the principal in the mandate: full means every action under this mandate requires human review before release; flagged means actions or sections matching the mandate's flagging rules wait for a named reviewer (allowed once reviewed); none means no review gate. Unreviewed means unreleased: an implementation MUST NOT issue a receipt for an action whose required review has not occurred.
action{
"type": "quote.issue",
"performed_at": "2026-07-02T14:22:31Z",
"channel": "email",
"counterparty": { "name_hash": "sha256:9f2c…", "domain": "customer.example" },
"summary": "Issued quote Q-2026-0417 for EUR 4,200"
}
summary SHOULD be a single human-readable sentence containing no sensitive content. Counterparty identity MAY be hashed for privacy; the domain is kept clear so recipients can confirm the receipt refers to them.
evidence{
"input_hash": "sha256:aa41…",
"output_hash": "sha256:b7ce…",
"hash_alg": "sha256"
}
Hashes allow either party to later prove that a document they hold is the exact one referenced by the receipt, without the receipt ever containing the document.
review{
"reviewed_by": {
"name": "Dr. Amara Osei",
"principal_id": "hal:principal:01J8ZT…"
},
"reviewed_at": "2026-07-02T09:40:12Z",
"items": ["dosage", "contraindications"],
"decision": "approved"
}
Present when the mandate's review_policy required human review. reviewed_by names the accountable reviewer — a person, not a system. items lists what was reviewed (sections, fields, or the literal ["*"] for full review). decision is approved; rejected actions are never released and therefore never produce a receipt. The review is part of the signed payload: it cannot be added, altered, or removed after issuance.
chain{
"seq": 4183,
"prev_receipt_id": "01J8ZS…",
"prev_receipt_hash": "sha256:c3d9…"
}
Receipts from one agent form a hash chain with a monotonically increasing seq. A missing or broken link is detectable, which makes selective deletion of inconvenient receipts evident; seq additionally makes truncation of the most recent receipts detectable by any party holding a later receipt.
A receipt is transported as a JWS (RFC 7515), compact serialization, with the JSON receipt as payload.
ES256. Issuers MAY additionally offer EdDSA.kid matching a key in the issuer's published JWKS.A verifier (any counterparty) performs five checks:
issuer.keys; verify the JWS.verify_url; confirm current status (a signed receipt may since have been revoked or disputed). The status field inside the payload records status at issuance only and MUST NOT be treated as current.action.type is within mandate.scope and satisfies mandate.constraints, and that action.performed_at falls inside the mandate's validity window.review_policy is not none, confirm the receipt carries a review object naming an accountable reviewer.identity_assurance meet the verifier's own bar.A receipt passing checks 1–4 is authentic and authorized. Check 5 is a policy decision left to the verifier.
Issuers MUST keep signing keys published in their JWKS for at least the retention life of the receipts signed with them; rotated keys remain published (for verification) but are no longer used for issuance.
verify_url MUST also serve an HTML representation so a human clicking the link sees a plain-language certificate: who acted, for whom, under what authority, current status.
valid → revoked — the issuer or principal withdraws the receipt (e.g. mandate was compromised).
valid → disputed — either party contests the action. The receipt chain becomes the evidentiary record.
disputed → settled — resolution recorded; a settlement note (free text plus optional signed settlement object) is attached at verify_url.
Settlement semantics beyond this lifecycle are out of scope for v0.1 and will be defined in a companion spec (ActionSettlement).
x_; verifiers MUST ignore unknown x_ fields.actionreceipt/0.2); verifiers MUST reject major versions they do not support.{
"spec": "actionreceipt/0.1",
"id": "01J9AB3XK7Q2M4N5P6R7S8T9V0",
"issued_at": "2026-07-02T14:22:32Z",
"issuer": {
"name": "HAL",
"domain": "halayer.com",
"keys": "https://halayer.com/.well-known/actionreceipt-jwks.json"
},
"principal": {
"name": "Jane Doe",
"role": "Managing Director",
"org": "Example GmbH",
"identity_assurance": "verified",
"principal_id": "hal:principal:01J8ZK4F2G"
},
"agent": {
"agent_id": "hal:agent:01J8ZQ9H3J",
"software": "acme-assistant/2.4",
"model": "claude-sonnet-4-6",
"operator": "Example GmbH"
},
"mandate": {
"mandate_id": "hal:mandate:01J8ZR5K7L",
"granted_at": "2026-06-01T09:00:00Z",
"expires_at": "2026-12-01T09:00:00Z",
"scope": ["email.send", "calendar.schedule", "quote.issue"],
"review_policy": "none",
"constraints": {
"quote.issue": { "max_value": 5000, "currency": "EUR" }
},
"revocable": true
},
"action": {
"type": "quote.issue",
"performed_at": "2026-07-02T14:22:31Z",
"channel": "email",
"counterparty": {
"name_hash": "sha256:9f2c8a41d6e3b7c5f0a2d9e8b1c4f7a6d3e0b9c8a7f4e1d2c5b8a9f6e3d0c7b4",
"domain": "customer.example"
},
"summary": "Issued quote Q-2026-0417 for EUR 4,200"
},
"evidence": {
"input_hash": "sha256:aa4138c2e9f7d6b5a4c3e2d1f0b9a8c7e6d5f4a3b2c1d0e9f8a7b6c5d4e3f2a1",
"output_hash": "sha256:b7ce29d4f1a8e6c3b0d7f4a1e8c5b2d9f6a3c0e7b4d1f8a5c2e9b6d3f0a7c4e1",
"hash_alg": "sha256"
},
"chain": {
"seq": 4183,
"prev_receipt_id": "01J9AA8WJ6P1L3M4N5Q6R7S8T9",
"prev_receipt_hash": "sha256:c3d94f2a1b8e7c6d5f4a3b2e1d0c9f8a7b6e5d4c3f2a1b0e9d8c7f6a5b4e3d2"
},
"verify_url": "https://executionproof.com/r/01J9AB3XK7Q2M4N5P6R7S8T9V0",
"status": "valid"
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://actionreceipt.com/spec/v0.1/schema.json",
"type": "object",
"required": ["spec", "id", "issued_at", "issuer", "principal", "agent", "mandate", "action", "verify_url", "status"],
"properties": {
"spec": { "const": "actionreceipt/0.1" },
"id": { "type": "string", "minLength": 10 },
"issued_at": { "type": "string", "format": "date-time" },
"issuer": {
"type": "object",
"required": ["name", "domain", "keys"],
"properties": {
"name": { "type": "string" },
"domain": { "type": "string" },
"keys": { "type": "string", "format": "uri" }
}
},
"principal": {
"type": "object",
"required": ["name", "identity_assurance", "principal_id"],
"properties": {
"name": { "type": "string" },
"role": { "type": "string" },
"org": { "type": "string" },
"identity_assurance": { "enum": ["self_asserted", "email_verified", "verified"] },
"principal_id": { "type": "string" }
}
},
"agent": {
"type": "object",
"required": ["agent_id"],
"properties": {
"agent_id": { "type": "string" },
"software": { "type": "string" },
"model": { "type": "string" },
"operator": { "type": "string" }
}
},
"mandate": {
"type": "object",
"required": ["mandate_id", "granted_at", "scope"],
"properties": {
"mandate_id": { "type": "string" },
"granted_at": { "type": "string", "format": "date-time" },
"expires_at": { "type": "string", "format": "date-time" },
"scope": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
"review_policy": { "enum": ["none", "flagged", "full"] },
"constraints": { "type": "object" },
"revocable": { "type": "boolean" }
}
},
"action": {
"type": "object",
"required": ["type", "performed_at"],
"properties": {
"type": { "type": "string" },
"performed_at": { "type": "string", "format": "date-time" },
"channel": { "type": "string" },
"counterparty": { "type": "object" },
"summary": { "type": "string", "maxLength": 280 }
}
},
"evidence": {
"type": "object",
"properties": {
"input_hash": { "type": "string" },
"output_hash": { "type": "string" },
"hash_alg": { "type": "string" }
}
},
"review": {
"type": "object",
"required": ["reviewed_by", "reviewed_at", "items", "decision"],
"properties": {
"reviewed_by": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"principal_id": { "type": "string" }
}
},
"reviewed_at": { "type": "string", "format": "date-time" },
"items": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
"decision": { "const": "approved" }
}
},
"chain": {
"type": "object",
"properties": {
"seq": { "type": "integer", "minimum": 0 },
"prev_receipt_id": { "type": "string" },
"prev_receipt_hash": { "type": "string" }
}
},
"verify_url": { "type": "string", "format": "uri" },
"status": { "enum": ["valid", "revoked", "disputed", "settled"] }
},
"patternProperties": { "^x_": {} },
"additionalProperties": false
}
Feedback and implementations welcome. This is a v0.1 draft published for public comment; nothing here is final.
Canonical URL: actionreceipt.com/spec/v0.1 · schema.json · GitHub · Edited by HAL, Sentidant AG