<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.35 (Ruby 3.2.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-dembowski-agentledger-proof-of-behavior-00" category="info" submissionType="independent" version="3">
  <!-- xml2rfc v2v3 conversion 3.33.0 -->
  <front>
    <title abbrev="AgentLedger PoB">Proof-of-Behavior Protocol for Autonomous AI Agents</title>
    <seriesInfo name="Internet-Draft" value="draft-dembowski-agentledger-proof-of-behavior-00"/>
    <author fullname="Jakub Dembowski">
      <organization/>
      <address>
        <email>dembowski@proton.me</email>
      </address>
    </author>
    <date year="2026" month="April" day="20"/>
    <area>Applications</area>
    <keyword>AI agents</keyword>
    <keyword>audit trail</keyword>
    <keyword>cryptographic receipts</keyword>
    <keyword>policy enforcement</keyword>
    <abstract>
      <?line 21?>

<t>Autonomous AI agents execute actions — file writes, API calls, shell commands — on behalf of human principals. No standard mechanism exists for a third party to verify that an agent acted within its declared behavioral rules, that policy enforcement occurred before execution (not after), or that the action log has not been tampered with after the fact.</t>
      <t>This document defines the Proof-of-Behavior (PoB) protocol: a minimal, language-agnostic standard for tamper-evident audit trails and pre-execution policy enforcement in AI agent systems. The protocol specifies a signed receipt format, a hash-chain linking scheme, a policy gate contract, and a cross-agent reference mechanism.</t>
    </abstract>
  </front>
  <middle>
    <?line 27?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>AI agent frameworks (LangChain, AutoGen, CrewAI, and others) expose lifecycle hooks that allow external code to observe agent actions. These hooks are sufficient for logging but do not provide cryptographic guarantees. A log written by the agent process being audited is not independently verifiable: the same software that produced the actions also produces the evidence.</t>
      <t>The Proof-of-Behavior protocol addresses three distinct problems:</t>
      <ol spacing="normal" type="1"><li>
          <t><strong>Tamper evidence</strong>: Once an action is recorded, neither the agent nor its operator can modify or delete the record without detection.</t>
        </li>
        <li>
          <t><strong>Pre-execution enforcement</strong>: Policy decisions must be recorded before the action executes. A DENIED record proves the agent was blocked; the absence of such a record proves the policy was not consulted.</t>
        </li>
        <li>
          <t><strong>Cross-agent attribution</strong>: In multi-agent systems, an orchestrator should be able to verify that a downstream agent completed a specific action under a specific policy, without trusting the downstream agent's in-process state.</t>
        </li>
      </ol>
      <section anchor="requirements-language">
        <name>Requirements Language</name>
        <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/>.</t>
      </section>
    </section>
    <section anchor="terminology">
      <name>Terminology</name>
      <dl>
        <dt>Receipt:</dt>
        <dd>
          <t>A signed JSON object recording a single agent action. Immutable once finalized.</t>
        </dd>
        <dt>Chain:</dt>
        <dd>
          <t>An ordered, append-only sequence of receipts, each cryptographically linked to its predecessor.</t>
        </dd>
        <dt>Policy Gate:</dt>
        <dd>
          <t>A pre-execution evaluation step that produces either an ALLOW or DENY verdict before any action is forwarded to the agent.</t>
        </dd>
        <dt>DENIED Receipt:</dt>
        <dd>
          <t>A receipt with status "denied", written to the chain before the action is attempted. Proves the policy gate ran and rejected the action.</t>
        </dd>
        <dt>agent_id:</dt>
        <dd>
          <t>The raw bytes of the agent's Ed25519 public key, encoded as lowercase hexadecimal. Serves as both identity and verification key.</t>
        </dd>
        <dt>principal_id:</dt>
        <dd>
          <t>An opaque string identifying the human or organizational principal that authorized this agent's keypair. Format is binding-specific.</t>
        </dd>
        <dt>policy_hash:</dt>
        <dd>
          <t>SHA-256 hash of the policy configuration, embedded in the signed receipt payload. Ensures policy cannot be substituted without breaking signatures.</t>
        </dd>
        <dt>prev_hash:</dt>
        <dd>
          <t>SHA-256 hash of the preceding receipt's canonical form (signature field excluded). Null for the first receipt in a chain (genesis receipt).</t>
        </dd>
      </dl>
    </section>
    <section anchor="protocol-overview">
      <name>Protocol Overview</name>
      <t>The protocol operates in four phases for each agent action:</t>
      <artwork><![CDATA[
 ┌─────────────────────────────────────────────────────────┐
 │  1. POLICY EVALUATION (pre-execution)                   │
 │     PolicyGate.evaluate(action) → ALLOW | DENY          │
 │     If DENY: write DENIED receipt → raise error         │
 │     If ALLOW: continue to phase 2                       │
 ├─────────────────────────────────────────────────────────┤
 │  2. RECEIPT CREATION (pre-execution)                    │
 │     Build receipt with status=PENDING                   │
 │     prev_hash = SHA-256(previous receipt, no sig)       │
 │     policy_hash = SHA-256(policy config)                │
 ├─────────────────────────────────────────────────────────┤
 │  3. ACTION EXECUTION                                    │
 │     Forward action to agent/tool                        │
 │     Capture result or error                             │
 ├─────────────────────────────────────────────────────────┤
 │  4. RECEIPT FINALIZATION (post-execution)               │
 │     Set status = COMPLETED | FAILED                     │
 │     result_hash = SHA-256(result)                       │
 │     Sign receipt with Ed25519 private key               │
 │     Append to JSONL storage                             │
 └─────────────────────────────────────────────────────────┘
]]></artwork>
      <t>The critical property of phase 1: the DENIED receipt is written to persistent storage and signed before the error is raised. The agent process cannot proceed to phase 3 without passing phase 1, and cannot suppress the phase 1 record.</t>
    </section>
    <section anchor="receipt-format">
      <name>Receipt Format</name>
      <t>A receipt is a JSON object <xref target="RFC8259"/> with the following top-level fields.</t>
      <section anchor="required-fields">
        <name>Required Fields</name>
        <dl>
          <dt>receipt_id (string):</dt>
          <dd>
            <t>A UUIDv4 string uniquely identifying this receipt.</t>
          </dd>
          <dt>chain_id (string):</dt>
          <dd>
            <t>Equal to agent_id. Identifies the chain this receipt belongs to.</t>
          </dd>
          <dt>agent_id (string):</dt>
          <dd>
            <t>Lowercase hex encoding of the agent's Ed25519 raw public key (64 hex characters, 32 bytes).</t>
          </dd>
          <dt>principal_id (string):</dt>
          <dd>
            <t>Opaque identifier for the authorizing principal. Format is defined by the binding in use.</t>
          </dd>
          <dt>timestamp (string):</dt>
          <dd>
            <t>ISO 8601 UTC timestamp of receipt creation (e.g., "2026-04-20T10:00:00.000000+00:00").</t>
          </dd>
          <dt>prev_hash (string or null):</dt>
          <dd>
            <t>SHA-256 hex digest of the canonical form of the preceding receipt (signature excluded). MUST be null for the first receipt in a chain.</t>
          </dd>
          <dt>schema_version (string):</dt>
          <dd>
            <t>Protocol version. This document defines version "0.1".</t>
          </dd>
          <dt>action (object):</dt>
          <dd>
            <t>Describes the agent action. See <xref target="action-object"/>.</t>
          </dd>
          <dt>signature (string):</dt>
          <dd>
            <t>Ed25519 signature over the canonical form of the receipt (signature field excluded), encoded as lowercase hex (128 hex characters, 64 bytes).</t>
          </dd>
        </dl>
      </section>
      <section anchor="action-object">
        <name>Action Object</name>
        <dl>
          <dt>type (string):</dt>
          <dd>
            <t>One of: "tool_call", "llm_invoke", "decision", "cross_agent".</t>
          </dd>
          <dt>framework (string):</dt>
          <dd>
            <t>The agent framework in use. RECOMMENDED values: "langchain", "autogen", "crewai", "custom".</t>
          </dd>
          <dt>tool_name (string or null):</dt>
          <dd>
            <t>Name of the tool invoked. REQUIRED when type is "tool_call".</t>
          </dd>
          <dt>status (string):</dt>
          <dd>
            <t>One of: "pending", "completed", "failed", "denied".</t>
          </dd>
          <dt>payload_hash (string or null):</dt>
          <dd>
            <t>SHA-256 hex digest of the canonical JSON encoding of the action input. MAY be null.</t>
          </dd>
          <dt>result_hash (string or null):</dt>
          <dd>
            <t>SHA-256 hex digest of the canonical JSON encoding of the action result. MUST be null when status is "pending" or "denied".</t>
          </dd>
          <dt>error (string or null):</dt>
          <dd>
            <t>Human-readable error message. SHOULD be set when status is "failed" or "denied".</t>
          </dd>
          <dt>policy_hash (string or null):</dt>
          <dd>
            <t>SHA-256 hex digest of the policy configuration active at the time of evaluation. MUST be set when a policy gate is in use. Embedded in the signed payload.</t>
          </dd>
        </dl>
      </section>
      <section anchor="example-receipt">
        <name>Example Receipt</name>
        <sourcecode type="json"><![CDATA[
{
  "action": {
    "error": null,
    "framework": "langchain",
    "payload_hash": "e3b0c44298fc1c149afbf4c8996fb924...",
    "policy_hash": "3fa7188e44ea5c896b2a5d1068de1246...",
    "result_hash": "9f86d081884c7d659a2feaa0c55ad015...",
    "status": "completed",
    "tool_name": "web_search",
    "type": "tool_call"
  },
  "agent_id": "6c24573e8a4f2b9c...",
  "chain_id": "6c24573e8a4f2b9c...",
  "cross_agent_ref": null,
  "prev_hash": "a3f4b2c1d0e9...",
  "principal_id": "agent@example.com",
  "receipt_id": "550e8400-e29b-41d4-a716-446655440000",
  "schema_version": "0.1",
  "signature": "4a5b6c7d...",
  "timestamp": "2026-04-20T10:00:00.000000+00:00"
}
]]></sourcecode>
      </section>
    </section>
    <section anchor="canonicalization">
      <name>Canonicalization</name>
      <t>The canonical form of a receipt is used for both signing and hash computation. It MUST be produced as follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>Serialize the receipt as JSON.</t>
        </li>
        <li>
          <t>Exclude the "signature" field entirely.</t>
        </li>
        <li>
          <t>Sort all object keys lexicographically at every nesting level (recursive).</t>
        </li>
        <li>
          <t>Emit with no insignificant whitespace (separators "," and ":").</t>
        </li>
        <li>
          <t>Encode as UTF-8 bytes.</t>
        </li>
      </ol>
      <t>This is equivalent to JCS (JSON Canonicalization Scheme) with recursive key sorting.</t>
      <t>Implementations MUST use this canonical form consistently. Any deviation produces a different byte sequence and an invalid signature.</t>
    </section>
    <section anchor="hash-chain">
      <name>Hash Chain</name>
      <t>Each receipt's prev_hash links it to its predecessor:</t>
      <artwork><![CDATA[
prev_hash[n] = SHA-256( canonical_form( receipt[n-1] ) )
]]></artwork>
      <t>where canonical_form excludes the signature field.</t>
      <t>The genesis receipt (first in chain) MUST have prev_hash = null.</t>
      <t>Verification of the chain proceeds from genesis to tip:</t>
      <ol spacing="normal" type="1"><li>
          <t>Assert receipt[0].prev_hash == null.</t>
        </li>
        <li>
          <t>For i = 1..N: assert receipt[i].prev_hash == SHA-256(canonical_form(receipt[i-1])).</t>
        </li>
        <li>
          <t>For each receipt: verify Ed25519 signature over canonical_form(receipt[i]).</t>
        </li>
      </ol>
      <t>A verifier that observes a valid chain at time T can store the (receipt_id, hash) pair and later detect any rewrite of the chain history, even if the verifier has no access to the signing key.</t>
    </section>
    <section anchor="signing">
      <name>Signing</name>
      <t>Each receipt MUST be signed using Ed25519 <xref target="RFC8032"/> as follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>Produce the canonical form of the receipt (signature field excluded).</t>
        </li>
        <li>
          <t>Sign the UTF-8 bytes using the agent's Ed25519 private key.</t>
        </li>
        <li>
          <t>Encode the 64-byte signature as lowercase hexadecimal.</t>
        </li>
        <li>
          <t>Set receipt.signature to this value.</t>
        </li>
      </ol>
      <t>The verifying party uses the agent_id field (which encodes the Ed25519 public key) to verify each signature independently.</t>
      <t>Agent identity MUST be established before any receipt is written. The Ed25519 keypair MUST be generated fresh for each agent instance unless a persistence mechanism is in use (see <xref target="key-persistence"/>).</t>
    </section>
    <section anchor="policy-gate">
      <name>Policy Gate</name>
      <t>The policy gate is an external component that evaluates each action before execution. It operates as follows:</t>
      <artwork><![CDATA[
result = policy.evaluate(action_type, tool_name, payload)

if result.verdict == DENY:
    write_denied_receipt(action_type, tool_name, result.reason, policy_hash)
    raise PolicyViolationError
else:
    # proceed to execution
]]></artwork>
      <t>The DENIED receipt MUST be written to persistent storage before PolicyViolationError is raised. Implementations MUST NOT proceed to execution if the DENIED receipt write fails.</t>
      <t>The policy_hash field in every receipt (ALLOW and DENY) MUST contain the SHA-256 hash of the policy configuration. This ensures that an auditor can verify not only that the policy ran, but that the specific policy configuration active at the time matches any externally stored policy definition.</t>
      <t>The external observer pattern is RECOMMENDED: the policy gate and receipt chain SHOULD be constructed outside the agent process and injected via callback registration. This places the enforcement logic in a different trust domain from the agent being audited.</t>
    </section>
    <section anchor="cross-agent-references">
      <name>Cross-Agent References</name>
      <t>When agents collaborate, handoffs SHOULD be recorded as cross-agent receipts. A cross-agent receipt references a specific receipt in another agent's chain.</t>
      <section anchor="cross-agent-reference-object">
        <name>Cross-Agent Reference Object</name>
        <sourcecode type="json"><![CDATA[
{
  "target_agent_id": "273170e7...",
  "ref_receipt_id": "550e8400-...",
  "status": "pending"
}
]]></sourcecode>
        <dl>
          <dt>target_agent_id:</dt>
          <dd>
            <t>The agent_id (Ed25519 public key hex) of the referenced agent.</t>
          </dd>
          <dt>ref_receipt_id:</dt>
          <dd>
            <t>The receipt_id of the specific receipt being referenced.</t>
          </dd>
          <dt>status:</dt>
          <dd>
            <t>One of: "pending", "confirmed".</t>
          </dd>
        </dl>
      </section>
      <section anchor="resolution">
        <name>Resolution</name>
        <t>To resolve a cross-agent reference, the verifying agent:</t>
        <ol spacing="normal" type="1"><li>
            <t>Locates the referenced agent's chain (by target_agent_id).</t>
          </li>
          <li>
            <t>Finds the receipt with the matching receipt_id.</t>
          </li>
          <li>
            <t>Verifies the Ed25519 signature on that receipt using target_agent_id as the public key.</t>
          </li>
          <li>
            <t>Confirms the receipt status is "completed".</t>
          </li>
        </ol>
        <t>Signature verification in step 3 is REQUIRED. A cross-agent reference that resolves without signature verification provides no tamper-evidence guarantee for the referenced chain.</t>
      </section>
    </section>
    <section anchor="checkpoint-hashes">
      <name>Checkpoint Hashes</name>
      <t>For long-running chains, implementations MAY write periodic checkpoint records to enable efficient partial verification.</t>
      <t>A checkpoint record is NOT a receipt. It MUST include:</t>
      <ul spacing="normal">
        <li>
          <t>"checkpoint": true</t>
        </li>
        <li>
          <t>"at_receipt_id": receipt_id of the last receipt in the batch</t>
        </li>
        <li>
          <t>"receipt_count": number of receipts covered</t>
        </li>
        <li>
          <t>"cumulative_hash": SHA-256 of the concatenated canonical forms of all receipts from genesis through at_receipt_id</t>
        </li>
        <li>
          <t>"signature": Ed25519 signature over the checkpoint record (signature field excluded)</t>
        </li>
      </ul>
      <t>Partial verification from a checkpoint proceeds by:</t>
      <ol spacing="normal" type="1"><li>
          <t>Verifying the checkpoint's cumulative_hash against the covered receipts.</t>
        </li>
        <li>
          <t>Verifying the chain tail (receipts after the checkpoint) independently.</t>
        </li>
      </ol>
    </section>
    <section anchor="storage">
      <name>Storage</name>
      <t>Implementations SHOULD store receipts in newline-delimited JSON (JSONL) format: one JSON object per line, UTF-8 encoded, LF line endings.</t>
      <t>Checkpoint records are interleaved with receipts in the same file. A parser MUST distinguish receipts from checkpoints by the presence of "checkpoint": true.</t>
      <t>Storage MUST be append-only during normal operation. Implementations SHOULD use OS-level file locking or equivalent to prevent concurrent writes.</t>
    </section>
    <section anchor="key-persistence">
      <name>Key Persistence</name>
      <t>Agent keypairs SHOULD be persisted across restarts to maintain a continuous chain. Implementations SHOULD:</t>
      <ol spacing="normal" type="1"><li>
          <t>Store the Ed25519 private key in a file with permissions 0400 (owner read-only).</t>
        </li>
        <li>
          <t>Store the public identity (agent_id, principal_id, binding_signature) separately with permissions 0600.</t>
        </li>
        <li>
          <t>Verify that the loaded keypair matches the chain's agent_id before resuming.</t>
        </li>
      </ol>
      <t>A chain whose agent_id does not match the loaded keypair MUST NOT be extended.</t>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <section anchor="chain-rewrite">
        <name>Chain Rewrite</name>
        <t>An attacker with write access to the JSONL file can rewrite the entire chain history with freshly computed hashes and re-signed receipts, provided they control the signing key. Mitigations:</t>
        <ul spacing="normal">
          <li>
            <t>External checkpointing: publish SHA-256(checkpoint) to an append-only external log at session boundaries. Any rewrite diverges from the published value.</t>
          </li>
          <li>
            <t>Bilateral co-signing: a separate signing service (in a different trust domain from the agent) co-signs each receipt. A rewrite requires compromising both keys.</t>
          </li>
          <li>
            <t>On-chain anchoring: commit checkpoint hashes to a public blockchain.</t>
          </li>
        </ul>
      </section>
      <section anchor="key-compromise">
        <name>Key Compromise</name>
        <t>A compromised private key allows an attacker to forge receipts that appear valid. Mitigations include key revocation registries and hardware security modules for key storage. These are out of scope for this document.</t>
      </section>
      <section anchor="same-trust-domain">
        <name>Same Trust Domain</name>
        <t>The in-memory verify() operation uses the same keypair that signed the receipts. This proves internal consistency but does not protect against an attacker who has already replaced the in-memory chain state. Verifiers MUST use verify_from_disk() with the expected public key, not in-process verify().</t>
      </section>
      <section anchor="policy-bypass">
        <name>Policy Bypass</name>
        <t>The policy gate can be bypassed if the agent constructs a ReceiptChain instance without a policy, or calls finalize_last() directly without a preceding append(). Implementations SHOULD restrict access to the ReceiptChain constructor and enforce that policy is set at chain construction time.</t>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
    <section anchor="references">
      <name>References</name>
      <section anchor="normative-references">
        <name>Normative References</name>
      </section>
      <section anchor="informative-references">
        <name>Informative References</name>
      </section>
    </section>
  </middle>
  <back>
    <references anchor="sec-normative-references">
      <name>Normative References</name>
      <reference anchor="RFC8259" target="https://www.rfc-editor.org/info/rfc8259" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml">
        <front>
          <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
          <author fullname="T. Bray" initials="T." role="editor" surname="Bray"/>
          <date month="December" year="2017"/>
          <abstract>
            <t>JavaScript Object Notation (JSON) is a lightweight, text-based, language-independent data interchange format. It was derived from the ECMAScript Programming Language Standard. JSON defines a small set of formatting rules for the portable representation of structured data.</t>
            <t>This document removes inconsistencies with other specifications of JSON, repairs specification errors, and offers experience-based interoperability guidance.</t>
          </abstract>
        </front>
        <seriesInfo name="STD" value="90"/>
        <seriesInfo name="RFC" value="8259"/>
        <seriesInfo name="DOI" value="10.17487/RFC8259"/>
      </reference>
      <reference anchor="RFC8032" target="https://www.rfc-editor.org/info/rfc8032" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8032.xml">
        <front>
          <title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title>
          <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
          <author fullname="I. Liusvaara" initials="I." surname="Liusvaara"/>
          <date month="January" year="2017"/>
          <abstract>
            <t>This document describes elliptic curve signature scheme Edwards-curve Digital Signature Algorithm (EdDSA). The algorithm is instantiated with recommended parameters for the edwards25519 and edwards448 curves. An example implementation and test vectors are provided.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="8032"/>
        <seriesInfo name="DOI" value="10.17487/RFC8032"/>
      </reference>
      <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author fullname="S. Bradner" initials="S." surname="Bradner"/>
          <date month="March" year="1997"/>
          <abstract>
            <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </reference>
      <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author fullname="B. Leiba" initials="B." surname="Leiba"/>
          <date month="May" year="2017"/>
          <abstract>
            <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </reference>
    </references>
    <?line 368?>

<section anchor="receipt-schema-summary">
      <name>Receipt Schema Summary</name>
      <t>The following table summarizes all receipt fields.</t>
      <table>
        <thead>
          <tr>
            <th align="left">Field</th>
            <th align="left">Type</th>
            <th align="left">Required</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">receipt_id</td>
            <td align="left">string (UUID)</td>
            <td align="left">REQUIRED</td>
            <td align="left">Unique receipt identifier</td>
          </tr>
          <tr>
            <td align="left">chain_id</td>
            <td align="left">string (hex)</td>
            <td align="left">REQUIRED</td>
            <td align="left">Equal to agent_id</td>
          </tr>
          <tr>
            <td align="left">agent_id</td>
            <td align="left">string (hex)</td>
            <td align="left">REQUIRED</td>
            <td align="left">Ed25519 public key, 64 hex chars</td>
          </tr>
          <tr>
            <td align="left">principal_id</td>
            <td align="left">string</td>
            <td align="left">REQUIRED</td>
            <td align="left">Authorizing principal identifier</td>
          </tr>
          <tr>
            <td align="left">timestamp</td>
            <td align="left">string (ISO 8601)</td>
            <td align="left">REQUIRED</td>
            <td align="left">UTC creation time</td>
          </tr>
          <tr>
            <td align="left">prev_hash</td>
            <td align="left">string (hex) or null</td>
            <td align="left">REQUIRED</td>
            <td align="left">SHA-256 of previous receipt</td>
          </tr>
          <tr>
            <td align="left">schema_version</td>
            <td align="left">string</td>
            <td align="left">REQUIRED</td>
            <td align="left">Protocol version ("0.1")</td>
          </tr>
          <tr>
            <td align="left">action.type</td>
            <td align="left">string (enum)</td>
            <td align="left">REQUIRED</td>
            <td align="left">Action type</td>
          </tr>
          <tr>
            <td align="left">action.framework</td>
            <td align="left">string</td>
            <td align="left">REQUIRED</td>
            <td align="left">Agent framework</td>
          </tr>
          <tr>
            <td align="left">action.tool_name</td>
            <td align="left">string or null</td>
            <td align="left">CONDITIONAL</td>
            <td align="left">Required for tool_call</td>
          </tr>
          <tr>
            <td align="left">action.status</td>
            <td align="left">string (enum)</td>
            <td align="left">REQUIRED</td>
            <td align="left">pending/completed/failed/denied</td>
          </tr>
          <tr>
            <td align="left">action.payload_hash</td>
            <td align="left">string (hex) or null</td>
            <td align="left">OPTIONAL</td>
            <td align="left">SHA-256 of input</td>
          </tr>
          <tr>
            <td align="left">action.result_hash</td>
            <td align="left">string (hex) or null</td>
            <td align="left">OPTIONAL</td>
            <td align="left">SHA-256 of output</td>
          </tr>
          <tr>
            <td align="left">action.error</td>
            <td align="left">string or null</td>
            <td align="left">OPTIONAL</td>
            <td align="left">Error description</td>
          </tr>
          <tr>
            <td align="left">action.policy_hash</td>
            <td align="left">string (hex) or null</td>
            <td align="left">RECOMMENDED</td>
            <td align="left">SHA-256 of policy config</td>
          </tr>
          <tr>
            <td align="left">signature</td>
            <td align="left">string (hex)</td>
            <td align="left">REQUIRED</td>
            <td align="left">Ed25519 signature, 128 hex chars</td>
          </tr>
        </tbody>
      </table>
    </section>
    <section anchor="reference-implementation">
      <name>Reference Implementation</name>
      <t>A reference implementation in Python (MIT licensed) is available at:
https://github.com/dembovvski/agentledger</t>
      <t>The implementation covers: AgentIdentityImpl (Ed25519), ReceiptChainImpl
(JSONL storage, checkpoint hashes), DenylistPolicy/AllowlistPolicy/
CompositePolicy, integrations for LangChain/AutoGen/CrewAI, CLI verifier.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA9VcT3MbR3a/41N0qMMSDgGBEEiRTLlqYYqysUuJjEh547hc
rMFMA5jlYAY7PUOKK8m1lUNOOaRSPuSQYz6ZP0l+773unh4AlOXaSm2tSt4F
MN2vu1+/P7/3Z9Tr9TpVWmX6RO1clkUx6+HvV3oR3aVFqfBLVcRFpmb4Mq6r
Ii+WRW3UeKLGc51XZqcTTaelvsNs/uFcJ3ONecVXO52kiPNoCcJJGc2qXqKX
0+Le3Ka9iEZmPLK3cmtO7Zq9waATR5WeF+XDiUrzWdEx9XSZGpMWefWw0vRj
olca/5NXnU66Kk9UVdamGg4Gx4NhJyp1dKLGq1WWgg4mmc6tfrgvyuREfY+N
8+pmT0V1klaYGaXZnorLh1VVzMtotUhjVepYpysatCpA5UFpbKOM9RIzf+h0
orpaFOVJR6ke/lNqVmeZnPR30W09VS/cSfmpXmIFMMH9+NsVMTXvL3Wnkxfl
Enu800TszcvTo+HB8QnmPFG/u7p4bX8bPBvKb2fJ8OBg/7jT6fV6Kpoa7D0G
B9r3IsdT+p2O60orjCAWqJ//8pOapZlW92VaaZxsfDlRcZRl+GgWOstUXCyX
UZ7I0CJXdCHZTBUztajxQK3KNI/TVZSZvnpdKFNhcFQmaqnjRZSnZok1U4Ol
SVYiVS1SPFxFZfWgqkLd6TKd4dMiqhSI8S5pczpR9ynG5irF1ETHGe4vUU4a
okyVdUb75Zmb16GKOK5LmYIftT04zqx28wJLzCpddvcU9sQUqoXjicqKuVpE
RtGwqda5qqLlSpd2RzKTx88wod/pXC9S7LCIa1430bM014YHbCrOLjSgq1ZW
fU7Aj2Wap8sIopZF+bzG+aEGeWEqiJtnJXFONtHTd2nCLGqk1IBx4Gipe80Z
tzAErHRioMyDqfQSF3aNXbrdKLPScTpLsflImXSe48RW4mkHEEgoB3Fm0cPN
glyW5rdpPlcmXmAJemiXnUNPITc5C+Ieby+CKhXGiI6D7AwMzWPdSElfxHeZ
JkkGDXiiJpheJDXfCYTZbX1WQqOgtbdG7Z6DZae0lT02Ql9rfDgt9f14IosW
uITSdHH3q8Jo7Hem44cYwr4oiltjhS7LinuMwKXmEUl7okkui6nR5Z1uBJK0
hfll3HQIpDL1bJbGKW8MlwTRmRNHpjUEoWAJAnfpytYsCW66jPJKa9Acs8SR
/lUQtumDyCKvi8mxNgZiSFT5znEpqchmYO6yB1GkNJqSxSYCBmxSpphV97RP
0RLmJwg0wo5TZKZwT0RqRcRizaK9TYi9wERJUmJ7PK/UWiXQcxgDXgkbWZqT
Tme/r7744pqF11P+4osTdUG3TxovSoczQdZgjHWyp3Kd0s0FjIBBZENQgExU
4UuMqcsiIduBb4nOdKV5vFBhVS3oFvA7r4DTDGkrly09CRSENnUp8gtzkxrm
zhL+A9z3e3PWJDAX1qLyRb44ez05e+H2QFdveSqnuIdVmWZFfKuTf5KfIWXE
BxhTU8ewLVumWp26txYJamXqDGKAAz2jA50GehVVVZlO+Wh0nAl4hLHWszqt
J90A06C05CmImQasyuhsiuRnwyxDlO9zjNXR0h4EPmFFHCe9tlYjdvyoIZFl
+LscYM9fCTtlkmc63Trp3xjIdc/JPSxgRXL45Il6o/9UpyXflFHn1laKhMKN
K/LjRu28ent1vbMn/69eX/DnN2f//Hby5uwFfb76Znx+7j+4EVffXLw9f9F8
amaeXrx6dfb6hUzGr2rtp1fj73bE1uxcXF5PLl6Pz3fI0lYtn8AaWBB/U+h8
CVPNrCO/ZmJcGOl0rr46vVT7I/X+/T/Auw/3948/frRfjvafjz5+BB9gFq91
CZdRwGQ8dDpvxDyfdABsnMkmhADz9UeIvZUmth14nM+ztkHrq8lyWVd86QXJ
IVxXlKV/ZuFiw8qUSVoScoA46YosTq/IYXEMbsRJb4OMdAQ5bhk7WNgH9hVk
eQpWY3AAOoYbLkqsZLXua9y1nKTty/RdlNWM2CAPetWyZQA0Yiog0rjQiz+Q
NYAWfkcSnKRx5RQ2yh8CU4OfYBYT2ZDXT2zFKnCLr84HsvcniQSg2oEdS3WC
u3d22xISz7hpJbAolFMvV6S5ZFPX1JtdZkn2MCevS7fXMtTYG+/xJk1oVyT2
ZXQPbwHLQxfgDwEFsnhQreopaJN64Fpy8mwsdPB3uowj8mP6XUS2Dvijr67I
3xkaMIXfVAwzUoA02pA4F4HNRA+78bDP7oikZBVBIsCikiROCMwenKYLWsT1
FOUcHv/PTAwe1xOy1oZBNMmgKJE7FFZdRWnZVy8ZihBDp/CAoN5zloZ2xdy8
IZBCm4KW94YHhwxaHJcsw2FHZ+m8Lnkb4M8SWpiIIrL7bOOfVfSQFRFu7gzW
Fz7PU4lygYmw3wDeaVU75EqWDhFQJAgJ1CA3mMic03ef3iGtylprl8fxsVCR
ky4xFFO7niJ0VsN263dxVmP/XYBwhB0CGQmjpqWp/DFwuMiK6C74qo24XXrW
FfPiI7sL3Pldqu/FxHqXLw5Yk5XGGjXAAHauBdyz6of2Be7/xx9/7Kiff/qP
n3/6y9/P3/+kLf+bUsAulxfnk9Pv1Nm34/O3YzLwardlnbpq8w/mWgL4I8aN
bFvfGjK9K9zpqp///b+s1fogRms7icmMn55IjBaADL5TIoIwAOqsyxK38BgJ
XuiEYXma1+yQ+O7UcMsRAgL/87e+jV/193/tmYH14KrPJpfX6vTN2efeXJtp
X9Vplmwz/19eAgBMXn/9SwS8pqsvnaLTHgCia693QLsF2YfuVgKNOQtJhBZs
4xh/19cGRDs+5cs6+5ez07f86TP+tJj2Upy787yQc7ZJT6sC9utzCJxGK7as
MNdAz+Sy2pr1CQJ/n1wfNcrycgIIO/lXpzCFqR7XmBbTrnTlwNGXChj58vzs
Glbqg3o5npzjwy9yXbi9Luvy61Zd3dgBXGJbWz0QKtM7wlcUKHyCwJjBLQkM
YehzHKcoITqfc+8//a2v8lf9/W92y+zYEX5UDCvg4eHagfcAQsQv7EsiYc3d
ADEEkBdTgCEqji4ttwgvWvQUwGDRIIIb5KoSyTy1kxwWS/FXQeayj2ceT60i
Q1GM258EXnaaqVcrSkYIgpIBNv4RZGMxvcWPnc44PFLUCpvev7c5V0RgLEiM
pArKFDGaLVa9TN/pTLCXaQWoiXrJP3Y6ljzwMeAaY+KuBBRv305e3I0cTq7z
FKgZIVIbMDfIDOQZsq0TOvtTTaDZmjc8RTgnJFIbWwjSC2nhSrIin+NxEUQU
LbLnYXggcQPt6JEYg4KQJs5Qu4cjnoaVKfcH6dhTz4YSpnTXoobWqhcSO6Tu
AKVHsC4g4It308MwQDKuicuc2aiAAGptKHlQpUttKH3aWnBydaGODgf76u31
qWqGNLEsVENLwLOr+/M+gv3hYHjYG4x6w8H1/uBkQH/7A/7zj/xlpxuie7ca
+Y8ckLzbgvvgUZLOsahj7BrAfywUCJF/gPk534EoJP8c7I9dcso2urkj9aUT
BozxEYB9SKq6LcHt5u4M+vs7JEzibndFh5jUC5veCHNgLvNwpTX0TL71ZA6n
OJrjtWTdilvzFAF0+QnGbWHXWqD0eEysdveHRxtiDMn2Ygx1H8txL6zFeNI+
CaTuYdU+wkVOmZITtUM45IayIpRAyrLlTZrfFbeavrnEI33mfPkNM43Y6/Pe
LaKNFW2eW8EPU1WKIg9tsDhVGVgIaAmoVoHJspq+j1L+VMOSL2lJ3igVsLaK
8mt6YLnN0EqOkdDCknBT9wvyEsQICFBwbrpmgQpbGUReGD/yZlyikb7MojST
Tzb7Quomgflfp3Fs+zcsnU3c5Ku6goKNv3P61SfT3mCV/49Fhf6aWjM3Ld+I
n45NtHLAEfG023b1DWVgerBqCWf8ZCAMn4EEQSEl9UmpDEC59cUs79fWCuOT
X8eHbVkYPj3VXKQcR0aZhjf5v4YhfovtmlNqvPSfbU/ouEQO6/DZu4jEy0ED
zlb80RR5531HQTv4LnZO1Huu1+4wv/CVTrcnP3ml22mrljwNZZMG6GfTQTwa
DY+PZvF+vD86jmbT2Sg+Oj4+nE2Ph6N+v++nNoylmc9m0fP9oyM9GunoABMO
p8PoINkfHB4len84OgxmBqJJM49nR4fJ4AiTR/Hz5PDgOBrOdBQN4oODKBns
HwQz5bZpUqB18shbAnp6r6c3RkdlvPCPoeI7LcuG3z/uMRMtxKDHh/FwdPD8
mT6KRrPh9Dh2a+84ePPpQY09vCn1LLiIHe9ziUD0bDaaDuP9ZKCP/eQQd/Ag
IvNbLfffx3llWAPZaNDBwUAfjQaDnh4eT3uj/WTUwzUc9kajw8ODg9GIPL/M
a7tTmktOUR45/0O/jqKD6SHuwe/LAw96+ov4ovNRgDvQ7KmzIzaRatH8hi+M
QpQLxZBiMmd4aWdcGgCIZg2ma68rq2mTyiubrxtGxqJgW9i70mXK9YKWy8Uo
sm19qredibfl5wErnC8G1isBfftUyboqSq7GOhAOOAm/rN+lcauQAOMA6F0+
KGAQriIJEkegGNfg/p2Gfx6R+qc2CMwLmAA+K2WwqQq3oE6HVRSTX9OriGtg
MHF7O1LIOSEcd0CpXi4G4zhvr1/2jsT7u3o//hLeh2ki50sh4+mV2mWbvn41
6orr413Zjt8n42WDQ+MQoDohSSSAJb0pwnxcmMD3tYulIqCEXWCeGudUsrxL
ZTVfGYlgcmdcZ694703Bhgvy5Nqw/TRpQJUESt+QLHD1p9M5o5Ruk4VuwC3V
c8CFaktFx2Z9/djv8x+CgL45yg0dZddR/z7v7f+guqorIg7jXuq1sQ67GW/Q
A2Bnq9VrWW21KyAYToCNTFf4uojudCs7Z/36t2Gdw3lsDqJsVAoFKIulX4WK
PulKlGFsDOJnf5zBD/1gAbfCkAMXlWLJ/X7/9QmkqzUrXZvluLbGND8cPOt2
WX1eugS8fXbiariPQOfHKP5A+HZsKz7adsfYbgiSKREZYQo5anLS11yOpwSA
aPpuY0f32LR0FdVuWO6yiNpnEi7Lc1UOwJPT2i12Q+ZBjepWd3DyqTzye5Lu
HMAFzhvYypszZ1KeghxfyQ9tIW4QhOCBmhMKjkcS+A+eDRH4rxu7S9Grvyrm
YAHgPBWND8yK3cfWKl6TvOKLtmaJhh6OeqLYfr1Hy3tkEylF53IKzRRmH2SZ
QwSrRSI6HHFzo1ZtwhiOYnc52C5sKXgrgZSM2Cw+doOGApbQZu1WCwvJHYcy
vvTo7opcJKiZRZNTEslZT0lJWsltwZYMPRnSWipeYfdASYv1mhW8RBWReazz
jOQqarJbYaNSAzLJfVAQi3V6wdCPH10tralr2ypaG6pGedh3tFwVOfuSBbs4
KRUZu0EJC9Zb2dhL+4pcS2DJiNr89Zd23fX60w3Btj3lsd2eA8fdTieduRjE
1dFhjLgIxYiPNfZG4oAbew2PUrWEEHcYqrQG0LbLxKR4Jcz6Ni0ytr5nBLY7
OjNaVnwS5gU9A5o85lqW0l35p1OVlp/blg5TlVtdMzWDbNuSM1ZrGxIbR1GU
6YfCIJZetCnNLbTxhkSKg2Q2iffWeVEFL7JRzecWuG0SR9vqtW+3pI4y201l
NZRyqdze4dsiLb0ywuVRY5t/sNbh88vB3DKqqOuIlddJPjWSkONIHBXOL6W2
54EY5XXEeqESclrRT3RHQZLjZKOfQnopbDaP/UoT5BKEqsqa2yyKujKptant
nDRRSHPbjQGExa2x0yi+Bd15yv1TDXdXWeR76ILGy6yYg0ecfmsAGTdBqaRY
0q4YUzSLt7r9xJRIk5eYxzeuedJ0On/gGFhae2MofzQtyBiQ182TYjYzwYl9
DxsMRbsZU3p3qIFty+9Ns6YJu7rCtGJeSA+O9VwuyfjkkX3bpNlauF1F5VxX
N2HAOHz+bP/5QD/34RK2cvNIjObHNGGsS5C4sGlthVb+jPPRm76LfGi38e/2
AInvF2pvyHfmNJl/O3WDbXLHDUWfEns8EwblKpeSd+Fygymy2oZ+BRnZIiN1
295nu9cAKHbr/FhwzXkRs/vYdkJ3mWqXkutt9gmYeZlSa3iIfnzBhLU9SF1T
hYIAjIDsNbgQoNNcLIyjZ5FRe3GSYdZ2f1OMcE6FSe0NBVmsJrEBJl75JVvt
TaltM3sm5kVSmZu64WTZ7pW5b3ylymynbZuBGb22GrpByLcE+/x9cBtOpcgU
LHR8uypS7IIiNbICL7n1OJ/3yjpnDMzDzZ5K1z3X+DvribB0WsCxY6gnJwaC
AbXOJUXou5sJByLWbx2HA4WN+cQ2co4+89DkEtKccTDkrkdJHzdxh1/U0PRj
VLX1e1OTsqhd0+CSD0kaTXfD46Jmsnm9nMIwBQ2KsJJ31MrIO6iXdcavWbjk
kXOnLhYpctKNnDFjG/Nz0x1lKzzhdmC4KIt6DuAWnofWDNNBnypqbHD18aCi
07nccjmynyik5GPY6YOo/rfeHrTXJLVv8wbmgCSqsmxhFjaOgwzBOi1GKIA7
Phg0wZsTzVLdjRiAIjfBZ5tJEevMJNL0dLFSru+zNNe9RGfpkpvkORXDCZnz
rn194QS2RbcKvdSUTvP2bCxmK0J76vwl/67E/hpuh93Qk6i0Db2Zju7c6yHh
rnwfPr1hQyYEWgQII8ogzfLzGmHNmhA13DGuqEmlbddru6k5ZMwspHXAN2zU
TWpOzPNLRa6Dz3b/bmUvhTYXV77EDTtAPes2t9/OelGyQhrCc37dJrdI18hF
/h4e9DIIot4/WY+VXMxnY7UQr7hh1MlDppesLNxAxQaKcBOj4Mh1tFFPlZjJ
R85lc5Y+S7GtO4QJyvtQdJkrarY28irAAChD7Rb3iCEV1VCYtzai9zStP/IR
7K5zWHsqTEHvuSr1jdfqrrK5SGoF2Fz8cDBonGcAzileA4dcqOsQttfB35gG
39hwh+KxpSQdx1ZR7xf0fowfmBRaXjZgctvW8SHQVPA51Nci1SvKb9LRTylH
mVhZM4IGebE3kvDB6pRBqgCmwVE+sbimdlpHWnH4SihKcdkiAdmUPm5njIQQ
x/fZg81oa8lva2MDgl67uZde5xO/zA3XD/LmUpFtZJXUK4QlczkP+7AzH717
jcTYE5ECqLXP3gXmjvo18pZ6+viGXgPCtRrNl66mcGJJVKb8akmQKEtglAGG
TBM22PUoRJEkTk99lXKijTMLPXsIet3MCZk/GIVUKaXCPz9A6TqappVx7HOv
vOyxlGYYwzeAySmDOC47UF6fdniR29fIojymBg/aH71rmFahz7IXR1xzysVv
0AQxBhmZU7eMZqH235KWdvO7Xpx38XIHwlCKeeBNJDbG/USlJDtb9+4wDNOD
8Sust7XhYGqFbBGVCb94ZZw6LIuEXlhkcMeZfzHY7pUyGkvAkd4EimGiLQgM
Gi/ksFfkTq75bl7w3UiMnOa9pV6S/AvG3+02dr7J3rEvcirM57SaEMBl44JZ
eUWB/ZskqGzJAcG1vN5mbQS1hnMu1yKEkLuwK5ysjTKymMQwjpFlwWbPIgfy
so8LD8qgBCJnuiEpvIHbvN3tNlGGfreS6Dx820Fej/OvETmeCAttWu6rB2on
20zMkZWBVZvyY6ofB41PTdaAYmFbNhar5rOHLgSI/ItPnGDJMuNfr7khEItD
JFCRuLL23s7xDT9iIrDpx9w0ucOSUnNtg9nald9vIdl3m5dQ4VuzuGwqp0cu
R+LncPdsurRlocn49XjDqLdbg2xenke6VyZt712TssANvHavN68/mOSzrY/o
zVDKuoR9fFxVi9RVvVxG5YPcY9Cjx/GL4YfguAmxetO290Ga9dQHdU1dKh+a
Jr4PtnlpxVz40PmALbT+w9wgOPnguvl2qbmvS5RcE8wH9ZY7/JqgpelxIyq+
t6+hwUmHFomNXj+e2nz51NQtbwMFXXqGKbX68jy1Fp3xtj689cM0jXTNllyn
3TpXrk+bFjtOD8pGXPVr7Uy2raRNI4jX1vvqmdpam9v2g603vKldrt53hcXS
rlaJeLgdaQSWa8ex/WAysJnYtGU9wtW15q1wTd9+5ac2TDi9eP1iIi8chmLL
XsN1YYTEbBLkk0ew2aanPkvyVLp+nkqiPyTXart69KbcK5Htm+KOqpBY2E31
K2nBaK4Rk66mLRwLCEiGP2kruD9akJf/hAw2vXVtMQxT4SKDPm7/HC31o/dU
2IRIWhra0TWfIN3M7lk760MxzeUDdBeC/Wpyjbg21jkcW5dLUHe4YTaVCI87
i6pamZOnT+dwR/WU2mKe8j9PcXdnbtOnwT/PYUFHex1OC5gTEemJjYBonz6x
2t1reSd61tlt9drvbWI/THqh8wcA3Eo899MxGfnge4fQX2GAOy+txyXUMrdO
inXC/0sBT+0/FPDU/TsBp+cTX1jud/4PKAkQkfdEAAA=

-->

</rfc>
