Internet Engineering Task Force P. Piehl Internet-Draft Independent Intended status: Experimental 11 October 2026 Expires: 14 April 2027 Rule Provenance for Autonomous AI Agent Audit Records draft-piehl-agent-rule-provenance-00 Abstract This document describes an experimental profile of the Agent Audit Trail format for AI agents. The profile records the rules an agent operates under: each version of each rule, who set and approved it, and which rules were in force when a decision was made. It keeps a decision separate from any later approval or override, binds it to the exact request, and requires that records of consequential actions go to a recorder independent of the operator and be anchored in a public log. It also sets out what these records can and cannot prove. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 14 April 2027. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Piehl Expires 14 April 2027 [Page 1] Internet-Draft AI Agent Rule Provenance October 2026 Table of Contents 1. Introduction 2. Conventions and Definitions 3. Relationship to the Agent Audit Trail 4. Rule Records 5. Policy Snapshots 6. Decision Records 7. Recording, Delivery and Receipts 8. Independent Recorders 9. External Anchoring 10. Verification 11. Limitations 12. Implementation Status 13. Privacy Considerations 14. Security Considerations 15. IANA Considerations 16. References Appendix A. Examples Appendix B. Open Issues Appendix C. Test Vectors Author's Address 1. Introduction When an AI agent does something that causes harm, the first question is what it did. The second, which usually matters more to the operator, a business partner, a court or a regulator, is whether it was allowed to. That second question can only be answered with facts from the moment of the decision: which rules were in force, who wrote and approved them, whether the agent followed them, and whether a person stepped in. The Agent Audit Trail format [SHARIF] gives agents a tamper-evident log. A decision record in that format can name the policy it relied on (policy_ref), an action can be marked "denied", and a human override can be noted. What the format does not record is the rules themselves. Nothing says when a policy was written or by whom, so a rule added after an incident looks the same as one that was there all along. Nothing records what a rule replaced, or stops two different versions of the same rule from both claiming to be current. Nothing records the full set of rules in force, so an operator can show a reviewer the rules that suit it and leave out the one that applied. The format also has no way to tell "no rule applied" apart from "the rules could not be checked", and it folds evaluation, approval and override into a single record even though all three can happen to one action. Piehl Expires 14 April 2027 [Page 2] Internet-Draft AI Agent Rule Provenance October 2026 There is also the question of who holds the log. [SHARIF] Section 5.2 asks that the recorder be a separate component with its own key, which protects the log from the agent. It does not protect the log from the organization that runs the agent, because that organization still owns the recorder. This document is a profile of [SHARIF] that fills these gaps. It records each version of each rule, ties every decision to the exact request and to a hash of every rule in force, keeps approvals and overrides apart from the original evaluation, and requires that records of consequential actions reach a recorder outside the operator's control, whose log is anchored publicly. Section 11 is frank about what all of this proves and what it does not. The intended status is Experimental. The mechanisms here should be built and tried before any of them is proposed as a standard, and reports from deployments are welcome, in particular on interoperability between implementations, false positives in the timing checks, receipt latency, behavior when a recorder is down, and any recorder equivocation seen in practice. 1.1. Overview The figure below shows the parts and the order in which records flow. A verifier later reads the records, receipts and anchors and reports a named result. +------------+ 1. rule records +--------------------------+ | Operator |-------------------->| Independent recorder(s) | | (rules) | | receipts + append-only | +------------+ | log | +--------------------------+ +------------+ 2. decision record ^ ^ | | Evaluator |-------------------------+ | | 4. tree | (checks | | | heads | rules) | | v +------------+ | +----------------+ | 3. permitted and | | External anchor| | receipted? | | (public log) | v | +----------------+ +------------+ 3. post-execution record | | Action |---------------------------------+ +------------+ In step 1 the operator records every version of every rule, including who set it, who approved it, the rule language it is written in and when it takes effect, and the recorders receipt each version before any decision may rely on it (Section 4). In step 2, before a Piehl Expires 14 April 2027 [Page 3] Internet-Draft AI Agent Rule Provenance October 2026 consequential action, the evaluator records and signs its decision: the exact request, a hash of the rules in force, the result, and any approval or override (Sections 5 and 6). In step 3 the action runs only if a final authorization says "permitted", is still valid, and has been receipted; the record of the action then points back to it (Sections 6.4 and 7.3). In step 4 the recorders publish the heads of their logs to an external service, so that history cannot be rewritten unnoticed (Section 9). Section 10 describes the checks a verifier then runs. 1.2. Related Work Several other individual drafts work on nearby problems, and this profile is meant to sit alongside them rather than replace them. [GILDA] defines a signed record of an authorization decision and its observed effect, with a digest of the policy that was used. [BRADLEY] makes the case for recording the decision itself, so that denials and permissions that were never used stay visible; this profile takes the same view, which is why its decision records are written before execution. [MIH] defines Agent Action Capsules for SCITT, which carry the disposition of each action, can record a person approving an individual action, and start a new configuration epoch when the policy manifest changes. [NELSON] defines signed receipts for what a person authorized an agent to do; such a receipt could be the content of a rule body here. [VAP] is a broader provenance framework with completeness checks and external anchoring, and it requires an escrow custodian that is independent of the operator. [KUEHLEWIND] describes an architecture for auditing agent delegation and interaction, and this profile could supply the rule and decision records within it. The policy digest in [GILDA] and the epochs in [MIH] already tie a decision to the policy that was in force. What this profile adds, as far as the author can tell from the revisions cited, is a history kept at the level of individual rules, with their authors, approvals and replacements; snapshots that anyone can recompute from rule records receipted by independent recorders; and criteria for the independence of recorders and evaluators that a verifier can report on. Using this profile with record formats other than [SHARIF] is listed as future work in Appendix B. 2. Conventions and Definitions 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 Piehl Expires 14 April 2027 [Page 4] Internet-Draft AI Agent Rule Provenance October 2026 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. All JSON defined by this profile is I-JSON [RFC7493], so that JCS [RFC8785] produces the same bytes in every implementation. This document uses the following terms: Rule: a statement that permits, forbids, limits, or requires approval for actions of an agent. Rule version: one fixed state of a rule, identified by rule_id and rule_version. A version is not edited once recorded; changes produce a new version. Principal: a person or organization that sets, approves or overrides a rule, identified by a stable identifier (see Section 13). Operator, vendor, integrator, model provider: the organization that runs the agent, the one that supplies the agent software, the one that configures and connects the agent for the operator, and the one that supplies the model the agent uses. Evaluator: the component that checks the rules, writes the records of a decision, and signs them with its own key (Section 6.1). An evaluator is "in-path" when the action cannot run without its signed decision. Consequential action: an action that matches an entry in the session's rp_consequential member (Section 3.1). An entry names an action type, and may narrow it to a tool. The operator has to list everything through which the agent can move money, commit the operator to an obligation, change data outside the agent's own workspace, or contact a person outside the operator's organization. Target action type: the [SHARIF] action_type of the action a decision is about, such as "tool_call" or "delegation". The decision itself is recorded with action_type "decision". Policy snapshot: the set of rule versions in force for an agent at a given time, and its hash (Section 5). Piehl Expires 14 April 2027 [Page 5] Internet-Draft AI Agent Rule Provenance October 2026 record_hash: the lowercase hex SHA-256 of the JCS form of a complete [SHARIF] record with any "batch" member removed. [SHARIF] attaches "batch" to a record only after the record's epoch has been built, and its Sections 3.2 and 6.3 also leave it out when computing prev_hash, although its Section 6.1 does not say so. Receipt: a statement signed by a recorder that binds a record_hash to the time the recorder received it, the recorder's identity, the record's position in the recorder's log, and the record's status (Section 7.2). Control: direct or indirect beneficial ownership of 10 percent or more of an organization, counting related parties together and including interests held through intermediaries, or any right, by ownership, contract or otherwise, to appoint its officers or directors or to direct its operations. Shares held through a diversified fund that the holder does not direct are not counted. Related parties: a party together with every party it controls, is controlled by, or is under common control with. For an individual this includes their spouse or domestic partner, parents, children, siblings, the spouses of any of them, and anyone living in the same household. A person or company acting on behalf of a party, such as a nominee holding shares for it, counts as that party. Independent recorder: a recorder that meets the criteria of Section 8.1 for the records in question. 3. Relationship to the Agent Audit Trail This document profiles revision -06 of [SHARIF]. Records made under it are ordinary [SHARIF] records with extra members in action_detail, a few features that [SHARIF] leaves optional become required, and the content of parameters_hash is fixed (Section 6.2). The profile adds no new action types, outcomes or lifecycle event values. Every member this profile adds directly to action_detail has a name beginning with "rp_" (for "rule provenance"); members nested inside those objects do not carry the prefix. [SHARIF] reserves "aat_" for its own use, and this profile stays out of it. This document defines the meaning of every "rp_" member, and another document should not define a new one without updating this one. Piehl Expires 14 April 2027 [Page 6] Internet-Draft AI Agent Rule Provenance October 2026 3.1. Profile Declaration The genesis record of every session, whether it is an agent session or a policy session, carries the following members in action_detail: rp_profile REQUIRED. The string "rp-00". rp_base REQUIRED. The string "sharif-06", naming the [SHARIF] revision the records follow. rp_operator_id REQUIRED. A URI identifying the operator. rule_id values are unique within an operator, and an operator has at most one open chain of policy sessions (Section 3.2). rp_recorders REQUIRED. The URIs of every recorder that will receive the session's records (Section 8.3). In an agent session, every recorder listed MUST also be listed in the policy session in force. rp_is_policy_session REQUIRED in policy sessions. The value true. rp_policy_session REQUIRED in agent sessions. The session_id of the operator's current policy session. rp_parties REQUIRED in agent sessions. An object naming the agent's "vendor", "integrator" and "model_provider" by URI, so that a verifier can check independence statements against them (Section 8.2). rp_default_posture REQUIRED in agent sessions. "default_allow" or "default_deny": what happens when no rule applies. rp_consequential REQUIRED in agent sessions. The consequential actions, as a list of entries. Each entry is either an action type, such as "delegation", or an object with "action_type" and "tool_name", and optionally "tool_server", naming a single tool. rp_synchronous REQUIRED in agent sessions. Entries, in the same form, for Piehl Expires 14 April 2027 [Page 7] Internet-Draft AI Agent Rule Provenance October 2026 consequential actions that never run without a receipt, even in degraded mode (Section 7.4). It MUST cover every action that can move money. heartbeat_interval_s REQUIRED in agent sessions that may contain consequential actions. The heartbeat interval defined in [SHARIF] Section 8.4. rp_retention_days REQUIRED in agent sessions that may contain consequential actions. How many days, at least 365, the session's records are kept after its session_end record, or after its last record if it has none (Section 3.4). rp_tolerance_s OPTIONAL. The clock tolerance T in seconds (Section 7.1). Default 5. rp_receipt_deadline_s OPTIONAL. The receipt deadline D in seconds (Section 7.2). Default 60. rp_degraded_mode OPTIONAL. true to allow degraded mode (Section 7.4). Default false. When true, rp_degraded_max_s (at most 3600) and rp_degraded_max_actions are REQUIRED. None of these members change during a session. In sessions that may contain consequential actions, the [SHARIF] sequence_number member, heartbeat records and session_end records are REQUIRED, and external anchoring (Section 9) is REQUIRED where [SHARIF] Section 6.4 only recommends it. If a later revision of [SHARIF] changes something this profile depends on, a new version of the profile will follow with a new rp_profile value; rp_base tells a verifier which rules to apply. A verifier that does not recognize the declared rp_profile or rp_base reports the session as "unsupported". An agent session whose genesis record declares a different rp_profile, rp_base or rp_operator_id from its policy session is reported as "profile_incomplete". Times in members defined by this profile are RFC 3339 timestamps [RFC3339] in UTC with the "Z" suffix. Hashes cover the string exactly as written, while comparisons use the instant it denotes. "Later than" means strictly later, so a time equal to a limit falls within it. Piehl Expires 14 April 2027 [Page 8] Internet-Draft AI Agent Rule Provenance October 2026 3.2. Policy Sessions Rule versions are not part of any agent's session. Each operator keeps them in a policy session: an ordinary [SHARIF] session, with a genesis record that meets [SHARIF] Section 8.1, whose agent_id is the URI of the operator's rule-administration service. Records of evaluator keys (Section 6.1) and of retired agents (Section 4.4) are kept there too. Records in a policy session have gap-free sequence numbers, but a policy session does not emit heartbeats and is exempt from the heartbeat and unclosed-session checks of Section 7.5. A rule version is recorded with action_type "lifecycle", action_detail.event "configuration_change", record_phase "pre_execution" and outcome "success", and carries an object named "rp_rule" (Section 4.1). Evaluator key records (Section 6.1) and agent retirement records (Section 4.4) are written the same way, carrying rp_evaluator_key or rp_agent_retired instead. Each of these records is written before the change it describes can take effect, as [SHARIF] Section 4.3 requires of a configuration change in a high-risk system. Under this profile these changes are made through the recorders, not by a separate step the operator performs. A rule version can become active only once every recorder named in the policy session has given it the status "accepted" (Section 4.2), an evaluator key can sign only once every such recorder has taken its record in (Section 6.1), and a retirement takes effect at the time given in Section 4.4. A key or retirement record that any of those recorders gives the status "rejected" never takes effect. The operator MUST NOT treat a change as made before these conditions are met. [SHARIF] Section 4.3 also expects a post-execution record documenting the outcome. Once every recorder named in the policy session when the pre-execution record was written has given it a final status (a record that is held is not yet final), the operator writes a "configuration_change" record with record_phase "post_execution" whose action_detail holds only the event and authorization_record_id, naming the pre-execution record. Its outcome says whether the change was made: "success" if every one of those recorders gave the status "accepted", and "failure" if any gave "rejected" or "void", in which case the change never takes effect and the pre-execution record stays in the history as evidence of the attempt. Statuses from recorders added later, including "backfilled", play no part. Because the recorders' statuses are what make the change, there is no other step whose failure the outcome could miss; an evaluator that fails to load a rule version that did take effect is caught as "snapshot_mismatch" (Section 5), not through this record. Piehl Expires 14 April 2027 [Page 9] Internet-Draft AI Agent Rule Provenance October 2026 Only the pre-execution record is a rule, key or retirement record; the post-execution record documents the outcome and changes nothing under this profile. A rule version itself becomes active later, at its effective_from. A policy session normally runs for a long time. An operator has one chain of policy sessions, linked by rp_continues, and at most one session in it is open at a time. When the operator starts a new one, the old session ends with a session_end record, and that record has to be receipted by every recorder named in the old session before the new session's genesis record is written. If that fails, the old session stays open and in use until it succeeds. The new genesis record carries rp_continues, an object holding the session_id, record_id and record_hash of the old session's final record, and its sequence numbers start again at 0. An operator that closes its policy chain for good puts rp_final true in the session_end record; the chain is never continued, and no new chain can be started for the same rp_operator_id. A recorder that already holds a policy chain for an rp_operator_id gives any later policy-session genesis record for the same rp_operator_id the status "rejected", with the reason "second_chain", unless its rp_continues names the session_end record that closed the latest session of that chain and that record does not carry rp_final. Every record of a rejected session is rejected as well, so none of its rule versions can become active. With each anchor (Section 9), every recorder publishes, signed with its log key, a policy-head statement for each operator whose policy records it holds: the session_id of the operator's latest policy session and the record_id and record_hash of the latest record in it. To check a decision, a verifier starts from the latest policy-head statement and walks back along rp_continues to the policy session named in the agent session's genesis record, covering the decision's evaluated_at. If a session in that chain cannot be obtained, it reports "policy_history_missing" as a check it could not perform, and the session can be at best "unverifiable". Agent sessions refer to rule versions only by rule_id, rule_version and rule_hash. Every recorder named in an agent session receives every record of the linked policy session and of the sessions it continues, so that each recorder can recompute snapshots and compare rule records in full. 3.3. Decision and Execution Records A decision about a consequential action is recorded in one or more [SHARIF] records with action_type "decision" and record_phase Piehl Expires 14 April 2027 [Page 10] Internet-Draft AI Agent Rule Provenance October 2026 "pre_execution", carrying the members described in Section 6. Their decision_type is "rp_authorization". The action itself is a separate record of its own action type with record_phase "post_execution", whose authorization_record_id ([SHARIF] Section 7.3) holds the record_id of the final authorization and whose rp_started_at gives the time the action started (Section 6.4). When the [SHARIF] member policy_ref is present, it MUST equal the rule_id of the governing rule (Section 4.5). It names the rule, not the version; the governing version is the one identified by rule_id, rule_version and rule_hash in rp_evaluation.rules, and that is what a verifier uses. When the result is "no_rule" or "unavailable" there is no governing rule and policy_ref is absent. 3.4. Compatibility with the Base Format [SHARIF] says that unknown members of action_detail SHOULD be preserved. A processor that drops rp_ members cannot support this profile, and one that claims to implement it MUST keep them. Note that being able to parse these records is not the same as being able to verify them. A verifier that implements only [SHARIF] will not, for example, check that policy_ref matches the governing rule. Such a verifier MUST report a session that declares rp_profile as "unsupported" and MUST NOT report it as verified under this profile. [SHARIF] Section 3.3 asks that records stay under 64 KB and requires records over 256 KB to be rejected. A rule record therefore uses rule_body_ref instead of rule_body (Section 4.1) whenever embedding the body would take the record over 64 KB. [SHARIF] Section 9.3 allows a record to be replaced by a tombstone when it has to be deleted. The records of consequential decisions and actions in an agent session MUST NOT be replaced by tombstones before the session's retention period (rp_retention_days, Section 3.1) has run out. The records of a policy session, including rule records and evaluator key records, MUST NOT be replaced while the retention period of any agent session whose rp_policy_session belongs to that chain is still running. A verifier reports a tombstone of such a record that a recorder received within those periods as "evidence_deleted", and any other tombstone as "tombstoned", for information only. A recorder's log still holds the original record either way, since the log only grows; Section 13 explains how personal data is kept out of these records, which is what makes this workable. Piehl Expires 14 April 2027 [Page 11] Internet-Draft AI Agent Rule Provenance October 2026 4. Rule Records 4.1. Fields An rp_rule object has the following members: rule_id REQUIRED. A stable name for the rule across its versions, unique within the operator: 1 to 128 characters from A-Z, a-z, 0-9, ".", "_", ":" and "-", compared octet by octet, so case matters. rule_version REQUIRED. An integer. The first version of a rule is 1, and each new version is exactly one more than the one before. language REQUIRED. The name and version of the rule language the body is written in, for example "example-rules/1.0". It is part of rule_hash, so a version cannot later be read under a different language. rule_body REQUIRED unless rule_body_ref is present. A JSON object holding the rule's content. rule_body_ref REQUIRED instead of rule_body when the content is kept elsewhere. An object with "uri" and "body_hash", where body_hash is the lowercase hex SHA-256 of the JCS form of the content. Content behind a reference never changes; a changed rule is a new version. Section 13 discusses confidential bodies. effect REQUIRED. One of "allow", "deny", "limit", "require_approval" or "retired" (Section 4.3). scope REQUIRED. An object with "agents", a list of distinct agent_id values or the single string "*" for all of the operator's agents; "action_types", a list of distinct [SHARIF] action_type values or "*"; and optionally "tools", a list of tool_name values that narrows the rule to those tools. agent_id values are compared octet by octet, and an operator MUST NOT reuse an agent_id for a different agent. A recorder marks a rule whose Piehl Expires 14 April 2027 [Page 12] Internet-Draft AI Agent Rule Provenance October 2026 action_types include a value that the declared rp_base does not define as rejected (Section 4.2). effective_from REQUIRED. The time at which the version begins to govern. It has to be later than the effective_from of the previous version of the same rule. effective_until OPTIONAL. The time at which the version stops governing. It has to be later than effective_from. rule_hash REQUIRED. The lowercase hex SHA-256 of the JCS form of an object holding exactly rule_id, rule_version, language, effect, scope, effective_from, whichever of rule_body and rule_body_ref is present, and effective_until if present. These are the members that identify the version and determine what it means; a verifier that computes a different value reports "rule_hash_mismatch". The remaining members are protected by the signature and chain of the record that carries them. set_by REQUIRED. The principal who created the version. set_at REQUIRED. When that principal created it, as reported by the operator. approved_by REQUIRED for any version that a decision about a consequential action relies on. The principal who approved the version. A verifier reports a decision about a consequential action that relies on a version without approved_by as "unapproved_rule". approved_at REQUIRED with approved_by. The time of approval. effective_from cannot be earlier than approved_at. Both approval members are statements by the operator, made attributable by the record's signature; this version of the profile cannot prove that the approver actually held that authority (Appendix B). supersedes REQUIRED when rule_version is greater than 1. The rule_id, rule_version and rule_hash of the version being replaced. Piehl Expires 14 April 2027 [Page 13] Internet-Draft AI Agent Rule Provenance October 2026 4.2. Acceptance A recorder takes every record it is sent into its log, so that the operator's hash chain is never broken at the recorder. What it decides is the status it gives the record in its receipt (Section 7.2). For rule records the status is one of "accepted", "void", "rejected" or "backfilled". Only an accepted version, or a backfilled copy of one, can ever become active. A recorder gives a version the status "rejected", with a reason, when it has already accepted a different rp_rule for the same rule_id and rule_version ("fork"), when its supersedes member does not match the previous accepted version ("bad_supersedes"), when its effective_from is not later than that of the previous version ("not_increasing"), when its scope names an undefined action type ("bad_scope"), or when it has waited 24 hours for a predecessor that never arrived ("missing_predecessor"). A version that arrives before its predecessor is held, and is taken into the log only once the predecessor has been; its received_at is that later time. Rejected records stay in the log, where they are evidence of what was attempted, and a verifier lists each rejected policy record it finds as "record_rejected". A version whose effective_from is earlier than its received_at, the moment the recorder took it into its log, is marked "void". There is no tolerance on this check, so a version held while waiting for its predecessor can become void. Only the recorders named in the policy session that holds the version decide whether it is void; if any of them marks it void, it is void everywhere. A void version never becomes active, does not end the active interval of the version before it, and keeps its place in the history so that every recorder holds the same history. The operator fixes the mistake by sending the next version with a later effective_from. In practice operators should set effective_from at least D seconds after they send a version, which leaves room for delivery delay and clock skew. A recorder that is added later, and receives older policy records that were written before it was named, gives them the status "backfilled". Backfilled records are checked for forks and order but not for voidness, and they take the status that the original recorders gave them. A decision MUST NOT rely on a version unless every recorder named in the agent session holds it as accepted, or as a backfilled copy of an accepted version; a version that is still held, or still being backfilled, does not count. A verifier reports reliance on a version it cannot find as "unknown_rule", and reliance on a rejected or void Piehl Expires 14 April 2027 [Page 14] Internet-Draft AI Agent Rule Provenance October 2026 version as "void_rule_used". 4.3. Active Intervals An accepted version is active from its effective_from until its effective_until, if it has one, or until the effective_from of the next accepted version of the same rule, whichever comes first. Because a version cannot take effect before the recorders accepted it, a version accepted later cannot change which version was active at the time of an earlier decision. A version with effect "retired" is never active and never matches an action. It ends the active interval of the version before it, and the rule stays switched off until a later version takes effect. If a version's effective_until passes before the next version starts, the rule is inactive in between and the session's default posture applies; the gap is visible in the records. Retired versions stay in the history. A rule that is changed back to an earlier meaning gets a new version, with its own set_by and approved_by. 4.4. Retiring an Agent An operator retires an agent with a "configuration_change" record in its policy session carrying rp_agent_retired, an object holding the agent_id and a time "at". Retirement takes effect at the later of "at" and the latest receipt of that record among the recorders named for the agent's sessions. From then on the agent's snapshot is empty, and every decision for it MUST end with rp_disposition "refused", whatever the default posture. Any decision for the agent that had not reached final authorization by then ends as "refused", and any final authorization that had not yet been used becomes void. The executing component MUST NOT act on it, and a post-execution record that does is reported as "retired_agent". Recorders keep accepting records for a retired agent_id so that later attempts are on record, and a verifier reports them as "retired_agent". Approvals or overrides that arrive after retirement are kept but change nothing, and rule versions accepted afterwards do not apply to the agent. Retirement is permanent; a replacement agent gets a new agent_id. 4.5. Matching and Precedence A version matches a decision when it is active at evaluated_at, its scope.agents includes the agent (or is "*"), its scope.action_types includes the target action type (or is "*"), and, if it has scope.tools, the request's tool_name is one of them. Whether the conditions in the body hold is decided by the rule language named in Piehl Expires 14 April 2027 [Page 15] Internet-Draft AI Agent Rule Provenance October 2026 the version's own language member. This version of the profile does not define a rule language. Each matching version whose conditions hold contributes an applied effect. The cap of a "limit" version is not one of its conditions: the conditions decide whether the version applies, and the cap decides what it contributes. Usually the applied effect is simply the version's effect, but a "limit" version that the request exceeds contributes "deny". The result is the strongest applied effect, in the order "deny", then "require_approval", then "limit", then "allow". All matching versions apply: if several limits match, the request has to satisfy each one, and if both "require_approval" and "limit" match, approval is needed and the limits still hold after it is given. A result of "limit" means the request, exactly as recorded, is within every matching limit and may go ahead. The evaluator MUST NOT quietly change a request to make it fit a limit; a request that is over a limit is either denied or replaced by a new request with a new decision. When nothing matches, the result is "no_rule" and the session's default posture decides what happens. rp_evaluation.rules lists every version that contributes an applied effect, which means every matching version whose conditions hold. A "limit" version contributes "limit" when the request is within its cap and "deny" when the request exceeds it, and an exceeded cap never removes the version from the list. Versions that contribute nothing are not listed. Each entry is {rule_id, rule_version, rule_hash, applied_effect}, and the entries are sorted first by applied effect in the order above and then by rule_id in octet order. The first entry is the governing rule, and its applied effect always equals the result. For "no_rule" and "unavailable" the list is empty and there is no governing rule. Whether a condition held or a cap was exceeded can only be checked by a verifier that implements the rule language; one that does not MUST NOT claim to have checked either, and reports "semantics_unverified" (Section 10). A verifier reports "undeclared_consequential" for each action that is not listed in rp_consequential although, at the time of its record, an accepted version with effect "deny", "limit" or "require_approval" was active and its scope covered the action. An action here is any record whose action_type is not "decision", "lifecycle", "error" or "tool_response". A rule that restricts an action is good evidence that the action matters. Rule conditions play no part in this check, so an operator that does not want every tool call to count scopes its restricting rules with tools. Piehl Expires 14 April 2027 [Page 16] Internet-Draft AI Agent Rule Provenance October 2026 5. Policy Snapshots For an agent at a time t, the policy snapshot is a JSON array with one object for every rule version active at t whose scope.agents covers the agent, regardless of action type, tools or conditions. Each object has exactly the members rule_id, rule_version and rule_hash, and the array is sorted by rule_id in octet order. Only one version of a rule can be active at a time, so a snapshot with two entries for the same rule_id is invalid. The snapshot hash is the lowercase hex SHA-256 of the JCS form of the array. Every decision record carries the snapshot hash its evaluator used. Anyone holding the rule records can recompute the snapshot for the same agent and time. A mismatch, reported as "snapshot_mismatch", means either that the evaluator used rules the recorder was never given or that it left out rules the recorder holds. A matching snapshot shows that the evaluator used the same rules the recorder holds. On its own it cannot show that the operator handed over every rule it has. That only becomes true when the evaluator is in-path and works solely from rule versions it received from an independent recorder, so that a rule which was never recorded cannot take effect (Section 11). 6. Decision Records 6.1. Evaluation The first record of a decision carries, in action_detail, the [SHARIF] member decision_type "rp_authorization", an object rp_request holding the action_detail that the target action will carry (Section 6.2), rp_parameters when the operator chooses to include them (Section 6.2), and an object rp_evaluation with the following members: decision_id REQUIRED. An identifier, unique within the operator, shared by every record about this decision. target_action_type REQUIRED. The target action type (Section 2). request_digest REQUIRED. A hash binding the decision to the exact request (Section 6.2). result REQUIRED. One of "allow", "deny", "limit", "require_approval", Piehl Expires 14 April 2027 [Page 17] Internet-Draft AI Agent Rule Provenance October 2026 "no_rule" or "unavailable". "unavailable" means the rules could not be evaluated, which is different from no rule applying. default_applied REQUIRED when result is "no_rule" or "unavailable". "allow" or "deny": what the action was permitted to do without a usable rule. fail_closed REQUIRED when result is "unavailable". true when the action is consequential, so that the denial follows from this profile's rule below whatever the default posture would have said; false otherwise. rules REQUIRED. The matching versions, as described in Section 4.5. snapshot_hash REQUIRED. The snapshot hash (Section 5) at evaluated_at. evaluated_at REQUIRED. The time of evaluation. It cannot be later than the [SHARIF] timestamp of the decision's first record (Section 7.1). evaluator_id REQUIRED. The key_id of the key the evaluator signs with (see below). in_path REQUIRED. true if the evaluator is in-path. This is the evaluator's own statement (Section 11). For a consequential action, "unavailable" counts as a denial: the evaluator MUST record default_applied "deny", whatever the session's default posture. The evaluator writes every record of a decision, including the approval and override records that carry what principals decided. On each one it signs the JCS form of the record's action_detail with rp_evaluator_signature removed, using an algorithm from the [SHARIF] signature algorithm registry, and places the signature in rp_evaluator_signature, encoded as base64url without padding [RFC4648]; for ES256 the signature is the 64-octet R || S value of [RFC7518] Section 3.4. Because the signature covers rp_request, rp_parameters, rp_approval, rp_override and the disposition as well as rp_evaluation, no other component can change any of them unnoticed. Piehl Expires 14 April 2027 [Page 18] Internet-Draft AI Agent Rule Provenance October 2026 The evaluator's public key is recorded in the operator's policy session by a lifecycle record with event "configuration_change" carrying rp_evaluator_key, an object with four members: key_id, the JWK thumbprint [RFC7638] of the key, which is how [SHARIF] identifies keys in signer_kid; jwk, the public key itself as a JWK [RFC7517]; alg, its algorithm from the [SHARIF] registry; and org, a URI naming the organization that runs the evaluator. A later rp_evaluator_key record with the same key_id and a fifth member, revoked_at, revokes the key (Section 14). A key can sign a decision only if every recorder named in the policy session took its record in before the decision's evaluated_at. A verifier reports a missing or invalid signature, or a key that is unknown, revoked or not yet recorded at evaluated_at, as "evaluator_unverified". Section 8.4 says how a verifier checks who runs the evaluator. The evaluator's signature is in addition to the [SHARIF] signature of the record itself, which belongs to the component that records the session (Section 7.5). 6.2. Request and Parameters rp_request is an exact copy of the action_detail that the target action record will carry, leaving out authorization_record_id and any member whose name begins with "rp_". For a tool call this includes the tool_name and parameters_hash that [SHARIF] Section 7.1 requires. [SHARIF] leaves open how the parameters are serialized before hashing; under this profile parameters_hash is the lowercase hex SHA-256 of the JCS form of an object with exactly two members: "parameters", the parameters sent to the tool, and "salt", at least 128 bits of fresh random data as lowercase hex. The salt keeps the hash from confirming a guess about what the parameters were (Section 13). request_digest is the lowercase hex SHA-256 of the JCS form of an object with exactly four members: "agent_id" and "session_id", copied from the record; "target_action_type", copied from rp_evaluation; and "request", a copy of rp_request. Appendix C has a worked example. Rules often depend on the parameters themselves, such as the amount of a refund, and [SHARIF] only logs their hash. The evaluator therefore needs the parameters, and so does any verifier that is to check the rule conditions. The operator either places the hashed object, salt included, in the decision record as rp_parameters, or keeps it and discloses it on request to parties entitled to verify the records. Section 13 explains when each is appropriate. A verifier that cannot obtain the parameters reports "parameters_unavailable" as a check it could not perform, and one whose copy does not hash to parameters_hash reports "parameters_mismatch". Piehl Expires 14 April 2027 [Page 19] Internet-Draft AI Agent Rule Provenance October 2026 6.3. Approvals and Overrides An approval request is a pre-execution decision record with outcome "escalated". It carries rp_approval with an approval_request_id that is unique within the operator, the decision_id and request_digest, a requested_at time, and an expires_at time later than requested_at. The answer is a later pre-execution decision record carrying rp_approval with the same approval_request_id, decision_id and request_digest, plus result ("approved" or "rejected"), by and at. Each request has at most one answer. A request without an answer is "pending" until expires_at and "expired" after it. An answer counts only if its "at" is no earlier than requested_at and no later than expires_at, and every recorder named in the session received it no later than expires_at plus T; otherwise the request has expired. An approval covers only the request whose digest it carries. A pending approval does not authorize anything, and neither does a decision that was abandoned before its final authorization. An approval record whose decision_id or request_digest does not match its decision, that answers a request that was never made, or whose "at" is earlier than requested_at, is reported as "approval_mismatch". An override is the case where a principal lets through an action that the decision would otherwise have refused: a result of "deny", a "no_rule" or "unavailable" result with default_applied "deny", or an approval that was rejected or expired. A request that is within its limits needs no override. The override is recorded in rp_override, which holds the decision_id, request_digest, by, at, a reason, and "overridden": the entries of rp_evaluation.rules that denied the action, or an empty list when no rule did. When rp_override is present, the [SHARIF] top-level human_override object MUST also be present on the same record, with operator_id equal to rp_override.by. The override's "at" can be no earlier than evaluated_at. When it overrides a rejected approval, it can be no earlier than the "at" of the rejection, and when it overrides an expired approval request, it has to be later than that request's expires_at. A verifier reports a breach of any of these as "override_inconsistent". Like the approval checks, these keep the recorded order consistent; they do not prove when a principal actually acted. 6.4. Decision Sequence and Final Authorization All the records of one decision are [SHARIF] decision records that share the same decision_id and request_digest, and they come in a fixed order. First is the evaluation record. Then come any approval requests, each followed by at most one answer; a new request may only be made after the previous one was rejected or expired, and at most one request is approved. Then, if needed, comes a single override Piehl Expires 14 April 2027 [Page 20] Internet-Draft AI Agent Rule Provenance October 2026 record. Each of these later records repeats rp_request and rp_evaluation unchanged, so the original request and result are never rewritten. A second answer to one request, a second approval, overlapping approval requests, or a second override are reported as "decision_conflict". The last pre-execution record of a decision is the final authorization, and it is the only one that carries rp_disposition and rp_disposition_basis. rp_disposition is "permitted" or "refused", and rp_disposition_basis is one of "rules", "approval", "override" or "default", so an action let through by an override shows "permitted" with basis "override", whatever the rules said. When an approval expires and no override follows, the evaluator writes a "refused" final authorization. A disposition that does not follow from the result, the default posture and Section 6.3 is reported as "result_inconsistent". A permitted final authorization carries rp_valid_until, the time after which it can no longer be used. It also stops being usable as soon as the agent's policy snapshot changes, so that an authorization collected under one set of rules cannot be spent after a stricter rule takes over. The executing component checks both before the action starts (Section 7.3) and records the moment it let the action start as rp_started_at in the record of the action. A verifier reports an action whose rp_started_at is later than rp_valid_until, or no earlier than the first change to the agent's snapshot after evaluated_at, as "authorization_expired". The record of the action itself carries authorization_record_id (which [SHARIF] makes optional) set to the record_id of the final authorization. Its action_detail, leaving out authorization_record_id and rp_ members, has to equal rp_request exactly, its action_type has to equal target_action_type, and its rp_started_at can be neither earlier than the final authorization's [SHARIF] timestamp nor later than its own; otherwise the verifier reports "execution_mismatch". Execution under a "refused" final authorization is reported as "refused_executed", and an action record whose authorization_record_id does not name a final authorization is reported as "authorization_unlinked". A final authorization allows exactly one execution, and a second action record pointing at the same one is reported as "authorization_reused". To make this hold in practice, the component that lets actions run MUST mark a final authorization as used before the action starts, in storage that survives a restart and is safe when requests arrive concurrently. Where the system being called accepts an idempotency key, deriving one from the final Piehl Expires 14 April 2027 [Page 21] Internet-Draft AI Agent Rule Provenance October 2026 authorization's record_id is a good idea. Even so, this profile cannot promise that an external side effect happened exactly once if the external system cannot enforce or report that. A decision is judged against the snapshot at its evaluated_at, and later rule changes do not alter it or undo side effects already committed. An operator that wants long-running actions to be checked again records a new decision, with a new decision_id, for each check. 6.5. Outcomes The decision records use only the outcomes [SHARIF] already defines. The evaluation record is "success" for "allow" and "limit", meaning authorized to proceed, "denied" for "deny", and "escalated" for "require_approval"; for "no_rule" and "unavailable" it is "success" when default_applied is "allow" and "denied" when it is "deny". Approval requests are "escalated", and an answer that is not the final authorization is "success" when it approves and "denied" when it rejects. The final authorization is "success" when permitted and "denied" when refused. The record of the action carries what actually happened: "success", "failure" or "timeout". 7. Recording, Delivery and Receipts 7.1. Time The recorder's clock is the reference for every timing check in this profile. A recorder MUST keep its clock within one second of UTC and should name its time source in its independence statement (Section 8.2); an authenticated source such as Network Time Security [RFC8915] is a sensible choice. Times reported by the operator or the evaluator are compared against the recorder's with the tolerance T. The first record of a decision has to carry an evaluated_at no later than its own [SHARIF] timestamp, and every named recorder has to receive that record within D + T of evaluated_at, or within rp_degraded_max_s + D + T when it was stored during a degraded episode (Section 7.4); otherwise a verifier reports "evaluation_time_invalid". The later records of a decision repeat evaluated_at unchanged and are not subject to this check, since an approval or override can take much longer. Without this check, an evaluator could date a decision before a stricter rule took effect and present the older, looser snapshot. A rule version has to be receipted before any decision relies on it. A verifier reports "retroactive_rule" when a decision relies on a version that one of the recorders named in the version's policy Piehl Expires 14 April 2027 [Page 22] Internet-Draft AI Agent Rule Provenance October 2026 session received more than T after evaluated_at, or after that recorder received the decision's first record, or whose approved_at is later than evaluated_at. Backfilled receipts are not used for this check. Since a version only becomes active at its effective_from, a decision that lists a version whose effective_from is later than evaluated_at is reported as "result_inconsistent". A verifier has no way to prove that a recorder's clock was right. If a recorder later finds that its clock was wrong for some period, it MUST publish that period with its anchors, and a verifier treats every timing check that depends on that period, including the acceptance checks of Section 4.2, as one it could not perform, reported as "clock_unreliable". The same applies to any period that two recorders of a session report differently. The session can then be at best "unverifiable". 7.2. Receipts A recorder is identified by a URI, and publishes its signing keys, with any rotations and revocations, alongside its anchors and its independence statement. For every record it takes in, it returns a signed receipt: a JSON object with record_hash, recorder_id, received_at, log_id, leaf_index, tree_size, and status, signed over its JCS form with an algorithm from the [SHARIF] signature algorithm registry. received_at is the time the recorder took the record into its log, which for a held rule record is when it was released (Section 4.2). status is "accepted" for ordinary records. Records of a policy session may instead be "backfilled" or "rejected", with a reason, and rule records "void" (Sections 3.2 and 4.2). The operator keeps its receipts. leaf_index and tree_size locate the record in a Merkle tree built as in [RFC9162], Section 2.1, over the recorder's whole log rather than a single session; the leaf input is the JCS form of the record with any "batch" member removed, which matches the leaves [SHARIF] Section 6.4 builds for its own epochs. To connect a receipt to an anchor, a verifier checks the inclusion proof of the record in the tree of size tree_size ([RFC9162], Section 2.1.3) and a consistency proof from that tree to the anchored tree head (Section 2.1.4). A record that should have a receipt and has none is reported as "receipt_missing". Records may be delivered in batches, and each still gets its own receipt and, on request, its own inclusion proof. Records of actions that are not consequential may be receipted after the action runs, which helps at high volume. A receipt is late when received_at is more than D + T after the record's [SHARIF] timestamp, and a record whose timestamp is more Piehl Expires 14 April 2027 [Page 23] Internet-Draft AI Agent Rule Provenance October 2026 than T after received_at is reported as "timestamp_future". Since the operator sets the timestamp, these two checks only bound how far its claimed time can drift from the recorder's, to D + T; they do not prove the operator's clock. A recorder that receives the same record_id twice with the same hash returns the same receipt. If the hash differs, it keeps both, and a verifier reports "record_conflict", except for a [SHARIF] tombstone, which Section 3.4 deals with. 7.3. Enforcing the Authorization Every decision about a consequential action is written with record_phase "pre_execution", and its final authorization is receipted by every recorder named in the session before the action runs or has any side effect, apart from the exception in Section 7.4. Immediately before the action, the component that lets it run MUST check that the final authorization says "permitted", that it carries a valid evaluator signature, that every named recorder has receipted it, that rp_valid_until has not passed, that the agent's current snapshot hash still equals the one in the decision, that its request matches the action about to be executed, and that it has not been used, and MUST block the action if any check fails. One consequence is worth stating: while any named recorder is down, consequential actions wait or fall back to degraded mode, and a new rule version cannot take effect. A deployment whose executing component skips these checks cannot claim to enforce this profile's authorization gate. Even when the gate is in place, the profile cannot show that nobody went around it by some other path. A request that is abandoned before execution does not need a receipt first, but its records still have to be delivered. An evaluator that cannot evaluate still writes an "unavailable" record, and if it cannot write anything at all, the action does not go ahead. 7.4. Recorder Failure and Degraded Mode By default, if a consequential action's final authorization cannot be receipted within D, the action does not run. A session that declares rp_degraded_mode true may instead keep going for a while. An episode of degraded operation starts with the first consequential decision that is not receipted within D and ends once every stored record has been receipted. The limits rp_degraded_max_s and rp_degraded_max_actions are counted across all episodes in a UTC day, so a string of short outages cannot reset them, and once either is reached consequential actions stop until receipts come back. Actions covered by rp_synchronous do not run without a receipt even in Piehl Expires 14 April 2027 [Page 24] Internet-Draft AI Agent Rule Provenance October 2026 degraded mode. Before the first action of an episode, the operator MUST durably write into the session an error record with error_code "rp_receipt_gap", error_message "recorder unreachable; degraded mode", error_category "external" and recoverable true, and it MUST keep every record durably, in sequence order, until it is receipted. When the recorder is back, the stored records are delivered in order. Actions taken this way are permitted exceptions, not failures. A verifier reports each consequential action that ran before its decision was receipted as "executed_without_receipt", in the exceptions class (Section 10), and does not report the late receipts of records stored during the episode as "receipt_late", as long as each was received within rp_degraded_max_s + D + T of its timestamp. It reports "degraded_limit_exceeded" if a limit was passed, and "gap_unmarked" if such an action was not preceded by the error record; both of those are failures. 7.5. Gap Detection Each session has one sequence counter, held by the component that records the session as described in [SHARIF] Section 5.2; other components, including the evaluator, hand their records to that component rather than numbering them themselves. Sequence numbers have no gaps within a session, and a verifier reports a missing one as "sequence_gap", in agent sessions and policy sessions alike. The rest of this section applies to agent sessions that may contain consequential actions. Heartbeat records ([SHARIF] Section 8.4) are written every heartbeat_interval_s from the genesis record onward, whatever else the session is doing, and every session ends with a session_end record. A verifier reports "missed_heartbeat" when the genesis record and the first heartbeat, two consecutive heartbeats, or the last heartbeat and the session_end record are more than heartbeat_interval_s + T apart. It reports "unclosed_session" when a session has no session_end record and its last record is older than heartbeat_interval_s + T by the verifier's own clock. These checks use the records' [SHARIF] timestamps, not the recorders' receipt times. They test whether the session wrote its heartbeats on time; whether records were delivered on time is a separate check, "receipt_late" (Section 7.2), so a heartbeat that reaches a recorder late does not by itself cause "missed_heartbeat". For example, with heartbeat_interval_s 300 and T of 5 seconds, heartbeats stamped 10:00:00 and 10:05:04 pass even if the second is received at 10:05:50, and heartbeats stamped 10:00:00 and 10:05:06 fail however promptly each was received. Section 7.2 keeps every timestamp within Piehl Expires 14 April 2027 [Page 25] Internet-Draft AI Agent Rule Provenance October 2026 D + T before, and T after, its receipt time, so an operator that misstates heartbeat times can hide a gap of at most about D + T; a deployment that needs a tighter bound sets a smaller D. 8. Independent Recorders 8.1. Criteria Independence is judged for particular records: a recorder can be independent for one operator's records and not for another's. The parties that matter are the operator and the vendor, integrator and model provider named in the session's rp_parties. For the records in question, a recorder is independent only if all of the following hold. 1. Control. None of those parties has control (Section 2) of the recorder, the recorder has no control of any of them, and no party that controls the recorder controls any of them. 2. Administration. Nobody with administrative, delegated or emergency access to the recorder's systems or keys is employed by, or holds such access at, any of those parties. Outsourced administrators and key custodians count. 3. Infrastructure. The recorder's signing keys, storage and hosting accounts are not controlled by any of those parties. Using the same cloud or hardware supplier as one of them is allowed but has to be disclosed. 4. Compensation. The recorder's fees do not depend on what the records show, and it is not paid anything linked to the outcome of an action, claim, loan or dispute that the records concern. Flat fees per record, per read or per period are fine. 5. Dependence. In the previous 12 months, no more than half of the recorder's revenue came from those parties combined, counting related parties together. A recorder in its first 12 months is exempt but has to disclose its share, and a verifier reports the exemption as "dependence_exempt". 6. Disclosure. The recorder discloses every party, counting related parties together, that provided more than 10 percent of its revenue in the previous 12 months, along with any material conflict of interest and any material shared dependency. Signing keys SHOULD be kept in hardware security modules. Records of consequential actions MUST go to at least one independent recorder, Piehl Expires 14 April 2027 [Page 26] Internet-Draft AI Agent Rule Provenance October 2026 and a verifier reports a session where none of the named recorders is independent for them as "recorder_not_independent". A recorder component inside the operator's own systems, as in [SHARIF] Section 5.2, does not qualify. When a recorder fails any criterion for some records, for instance because it shares an owner with their operator, every record of those sessions MUST also go, as it is written, to a second recorder that meets every criterion for them. 8.2. Independence Statements A recorder publishes a statement covering each criterion and naming the parties it covers, signed with its log key and published alongside its anchors, so a false statement can be traced back to it. Each statement names the period it covers. When something changes, a new statement follows within 30 days, with a period starting on the date of the change itself, so that records accepted in the meantime are judged by the new statement. A verifier checks records against the statement that covered the time they were accepted, and checks that it covers the parties named in rp_parties. All a verifier can actually check is that a statement exists, is signed, and covers the right parties; whether it is true is a question for an auditor. An independent audit is therefore RECOMMENDED, and a verifier reports independence as "asserted" unless an audit report for the statement's period is available, in which case it reports "audited". Independence is an organizational property and no amount of cryptography will prove it. What it buys is narrow but useful: no single party whose conduct is on record controls every copy of the record or every key that signs it. 8.3. More Than One Recorder Every recorder named in rp_recorders receives every record of the session, which stops an operator from sending different records to different recorders. A verifier reports "recorder_missing_record" for a record that a named recorder still lacks once D plus 24 hours have passed since its timestamp. It reports "recorder_conflict", naming both recorders, when two recorders hold different content for the same record_id, give the same rule record different statuses (other than "backfilled"), or hold rp_rule objects for the same rule version that differ in any member, including set_by, approved_by, approved_at and supersedes, even if the rule hashes and snapshot hashes agree. It also recomputes the snapshot separately from each recorder's rule records, and if they differ for a decision, it reports "recorder_conflict" and does not treat the decision as verified on the strength of either one. This version of the profile detects disagreement between recorders; Piehl Expires 14 April 2027 [Page 27] Internet-Draft AI Agent Rule Provenance October 2026 it does not try to decide which one is right. Both recorders and the operator keep the conflicting records exactly as they are, and none of them may reconcile the records quietly. Note that independence is about who holds the record. It does not make the record complete, since an independent recorder will faithfully keep whatever the operator sends it. Section 11 returns to this point. 8.4. Independent Evaluators An evaluator is independent for a session when the organization named in the org member of its rp_evaluator_key record meets the criteria of Section 8.1 for that session, with the evaluator in place of the recorder, and publishes a signed statement as recorders do under Section 8.2, listing the key_id of every key it uses for the operator. A verifier checks the key that signed a decision against that statement. When org names an organization other than the operator and that organization's statement does not list the key, it reports "evaluator_key_unconfirmed", since an operator could otherwise sign its own decisions and attribute them to someone else. The report states evaluator independence as "operator" when org is the operator's rp_operator_id, as "not independent" when the statement shows that a criterion is not met, and otherwise as "asserted" or "audited", on the same terms as for recorders. 9. External Anchoring An independent recorder MUST publish a signed head of its log, covering each consequential record and each record of a policy session, to an external service within 24 hours of taking that record in. Until then the record is reported as "anchor_pending", which is not a failure; after the deadline it is reported as "unanchored". Two kinds of service are acceptable, and they prove different things. A transparency log that provides inclusion and consistency proofs as in [RFC9162] shows that a head existed by a given time and that later heads extend it, which lets monitors notice a recorder showing different histories to different people. A transparency service built on the architecture of [RFC9943] qualifies when the proofs it returns are [RFC9162] inclusion and consistency proofs that a verifier can check for itself; other proof formats are outside this version. A time-stamping authority following [RFC3161] proves only that a head existed by a given time, so a recorder that relies on time-stamping alone also has to publish every signed head where anyone can retrieve Piehl Expires 14 April 2027 [Page 28] Internet-Draft AI Agent Rule Provenance October 2026 it and provide consistency proofs between any two of them on request. Two signed heads from the same log with the same tree size and different roots, or two heads for which the recorder does not provide a valid consistency proof on request, are reported as "recorder_equivocation". On request from a party entitled to the records, a recorder provides the inclusion proof that connects a receipt to an anchored head. 10. Verification A verifier works from a session's records, the policy records they rely on, the receipts, the anchors, the policy-head statements, and the recorders' statements and keys. It first runs the chain and signature checks of [SHARIF], reporting any failure as "chain_invalid", and then runs every check this document defines, keeps going after a failure, and reports each problem by name. Every name falls in one of four classes. A failure means the records break a rule of this profile. An exception means something this profile permits but wants visible, such as degraded mode. Not performed means the evidence a check needs was missing. Informational results change nothing. The names, with their classes and the sections that define them, are: Name Class Section ------------------------- ------------- ------------- chain_invalid failure [SHARIF] profile_incomplete failure 3.1 unknown_rule failure 4.2 void_rule_used failure 4.2 unapproved_rule failure 4.1 rule_hash_mismatch failure 4.1 retroactive_rule failure 7.1 evaluation_time_invalid failure 7.1 snapshot_mismatch failure 5 result_inconsistent failure 4.5, 6.4, 7.1 undeclared_consequential failure 4.5 evaluator_unverified failure 6.1 parameters_mismatch failure 6.2 approval_mismatch failure 6.3 override_inconsistent failure 6.3 Piehl Expires 14 April 2027 [Page 29] Internet-Draft AI Agent Rule Provenance October 2026 decision_conflict failure 6.4 authorization_expired failure 6.4 execution_mismatch failure 6.4 refused_executed failure 6.4 authorization_unlinked failure 6.4 authorization_reused failure 6.4 retired_agent failure 4.4 evidence_deleted failure 3.4 receipt_missing failure 7.2 receipt_late failure 7.2 timestamp_future failure 7.2 record_conflict failure 7.2 degraded_limit_exceeded failure 7.4 gap_unmarked failure 7.4 sequence_gap failure 7.5 missed_heartbeat failure 7.5 unclosed_session failure 7.5 recorder_not_independent failure 8.1 recorder_missing_record failure 8.3 recorder_conflict failure 8.3 evaluator_key_unconfirmed failure 8.4 unanchored failure 9 recorder_equivocation failure 9 executed_without_receipt exception 7.4 semantics_unverified not performed 10 parameters_unavailable not performed 6.2 policy_history_missing not performed 3.2 clock_unreliable not performed 7.1 rule_body_unavailable not performed 13 anchor_pending informational 9 dependence_exempt informational 8.1 principal_unresolvable informational 13 tombstoned informational 3.4 record_rejected informational 4.2 A verifier that does not implement the rule language named by a rule version can still check that the listed rules are in the snapshot and that the result follows from their applied effects. It reports "semantics_unverified" and MUST NOT claim that the rule conditions were checked or that the evaluator listed every rule that matched. The overall result is the first of these that applies: "unsupported" if the verifier does not implement this profile or the declared rp_base; "failed" if any failure was found; "unverifiable" if no failure was found but some check could not be performed; "verified_effects_only" if the only gap is "semantics_unverified"; and otherwise "verified". Exceptions and informational results are listed but do not change the overall result. Alongside it, the report Piehl Expires 14 April 2027 [Page 30] Internet-Draft AI Agent Rule Provenance October 2026 MUST state five things: whether integrity held (chain, receipts and anchors), whether decisions were "checked" in full or by "effects only", whether recorder independence was "asserted", "audited" or "not independent", whether the evaluator was run by the "operator" or was "asserted", "audited" or "not independent" (Section 8.4), and which completeness checks were run. Even a "verified" session is not proof that the agent obeyed every rule, and a verifier MUST NOT present it that way. Section 11 explains why. 11. Limitations It helps to keep three properties apart. Integrity means the records have not changed since they were receipted and anchored; this profile provides it, as long as the recorders' keys and the anchor service hold up. Completeness means nothing relevant was left out. The profile catches some omissions, such as gaps in sequence numbers, missed heartbeats, sessions that were never closed, disagreement between recorders, and snapshots that do not match the recorded rules. What it cannot catch is an action that the operator never recorded at all, outside any session, or a rule that was never handed to a recorder. Authenticity means the records describe what really happened. A record of an evaluation is only as good as the evaluator that signed it, and when the evaluator is run by the operator, the evaluation is the operator's own account. The strongest arrangement is an in-path evaluator run by an independent party, working only from rule versions it received from an independent recorder. Then a consequential action cannot run without a decision signed with a key that the operator does not hold, which a verifier can confirm (Section 8.4), and a rule that was never recorded cannot take effect. That arrangement is RECOMMENDED for consequential actions, though this version does not require it. The in_path member is still the evaluator's own statement, and this version has no way to prove it; Appendix B lists that as future work. 12. Implementation Status [RFC Editor: please remove this section before publication.] This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in [RFC7942]. The description of implementations in this section is intended to assist the IETF in its decision processes in progressing drafts to RFCs. Piehl Expires 14 April 2027 [Page 31] Internet-Draft AI Agent Rule Provenance October 2026 At the time of writing, no implementations of this profile are known. The test vectors in Appendix C were produced with a short script that follows Sections 4.1, 5 and 6.2. 13. Privacy Considerations A confidential rule can be recorded by reference, with only its body_hash in the record. Whoever holds the content MUST keep it for as long as the records that refer to it, and MUST disclose it, under whatever access rules the parties have agreed, to anyone entitled to verify those records. A verifier that cannot get content matching the hash reports "rule_body_unavailable", and the session can be at best "unverifiable". Bear in mind that a hash does not keep a short or guessable rule secret, since anyone can hash candidates until one matches. A confidential rule body should therefore include a member holding at least 128 bits of random data. Recorders will hold records about the operator's customers, and their logs only grow, so what goes into a record matters. Principals SHOULD be identified by stable pseudonyms. Personal data does not belong in rule bodies, decision records or rp_parameters. Where a record has to refer to it, it should do so by a keyed hash, such as an HMAC under a key the operator holds; destroying the key later makes the reference meaningless without touching the record, which is how this profile reconciles erasure with the retention rule of Section 3.4. parameters_hash is salted (Section 6.2) for the same reason, since a plain hash of a short or predictable value, such as an email address or an amount, lets anyone holding the record confirm a guess. Parameters that contain personal data are kept by the operator and disclosed on request rather than placed in rp_parameters; once they have been erased, a verifier reports "parameters_unavailable". The operator keeps the mapping from pseudonym to person for as long as the records, unless the law requires it to be erased, and records every disclosure of the mapping as a [SHARIF] lifecycle record. Erasing the mapping leaves the records and their hashes intact; the erasure itself is recorded, and a verifier reports "principal_unresolvable", which is for information only. Rule bodies MUST NOT contain credentials or other secrets. 14. Security Considerations The main threat this profile is built for is an operator rewriting history after something goes wrong. A rule added after an incident is caught because rule versions have to be receipted before use, by the retroactive_rule and evaluation-time checks, and because logs are anchored publicly. A rule read under a different language later is prevented by fixing the language in rule_hash. A rule hidden from a reviewer shows up as a snapshot that does not match the recorders' Piehl Expires 14 April 2027 [Page 32] Internet-Draft AI Agent Rule Provenance October 2026 rule records. Two conflicting versions of a rule are kept as evidence and rejected. Deleting records selectively runs into sequence numbers, heartbeats, session_end records, receipts, second recorders and the retention period during which evidence cannot be tombstoned. The profile also covers some threats from recorders. A recorder that shows different histories to different people is caught by consistency proofs and published heads, and one that denies receiving a record is answered by the signed receipt the operator kept. Approvals reused for a different action fail the request_digest check and expire, and authorizations cannot be held back and spent under later rules because of rp_valid_until and the snapshot check. An approval or override altered on its way into the record breaks the evaluator's signature, and a decision attributed to someone else's evaluator fails the key check of Section 8.4. Degraded mode cannot be used to fail open indefinitely because of its daily limits. Several threats are not fully addressed, as Section 11 and Appendix B explain: an operator that never records an action, a compromised evaluator key, collusion between an operator and its recorders, and false independence statements. Keys change in two places. Operator and evaluator keys are rotated and revoked through [SHARIF] key_rotation lifecycle records and rp_evaluator_key records in the policy session, and recorder keys through statements published with the recorder's anchors. A revocation gives the time from which the key is considered compromised, and signatures made with that key remain valid only if an anchor made before that time covers them. When the evidence cannot show whether a signature came before the compromise, the check is reported as not performed rather than passed. 15. IANA Considerations This document has no IANA actions. It adds no action types, outcomes or lifecycle event values to [SHARIF]: rule, evaluator key and retirement records use the existing "configuration_change" event, decisions use the existing "decision" action type, and receipt gaps use the existing "error" action type. The members it defines all sit under the "rp_" prefix inside action_detail (Section 3). If [SHARIF] sets up a registry for extension prefixes or profiles, a later version of this document will register "rp_" and "rp-00" there. 16. References 16.1. Normative References [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997. Piehl Expires 14 April 2027 [Page 33] Internet-Draft AI Agent Rule Provenance October 2026 [RFC3161] Adams, C., Cain, P., Pinkas, D., and R. Zuccherato, "Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)", RFC 3161, August 2001. [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, July 2002. [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, October 2006. [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, March 2015. [RFC7517] Jones, M., "JSON Web Key (JWK)", RFC 7517, May 2015. [RFC7518] Jones, M., "JSON Web Algorithms (JWA)", RFC 7518, May 2015. [RFC7638] Jones, M. and N. Sakimura, "JSON Web Key (JWK) Thumbprint", RFC 7638, September 2015. [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, May 2017. [RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, "JSON Canonicalization Scheme (JCS)", RFC 8785, June 2020. [RFC9162] Laurie, B., Messeri, E., and R. Stradling, "Certificate Transparency Version 2.0", RFC 9162, December 2021. [RFC9943] Birkholz, H., Delignat-Lavaud, A., Fournet, C., Deshpande, Y., and S. Lasker, "An Architecture for Trustworthy and Transparent Digital Supply Chains", RFC 9943, June 2026. [SHARIF] Piehl Expires 14 April 2027 [Page 34] Internet-Draft AI Agent Rule Provenance October 2026 Sharif, R., "Agent Audit Trail: A Standard Logging Format for Autonomous AI Systems", Work in Progress, Internet-Draft, draft-sharif-agent-audit-trail-06, 29 September 2026. 16.2. Informative References [BRADLEY] B, B., "Signed Decision Records for Agent Authorization: Disclosures, Entry Emission, and Ordering Evidence", Work in Progress, Internet-Draft, draft-bradleyb-audit-decision-records-00, 13 August 2026. [GILDA] Gilda, S., "An Audit Record Format for AI Agent Authorization Decisions", Work in Progress, Internet-Draft, draft-gilda-wimse-agent-audit-record-02, 4 October 2026. [KUEHLEWIND] Kuehlewind, M. and H. Birkholz, "An Architecture for Auditing Agent Delegation and Interactions", Work in Progress, Internet-Draft, draft-kuehlewind-audit-architecture-01, 7 September 2026. [MIH] Mih, S., "An Agent Action Capsule Profile for SCITT", Work in Progress, Internet-Draft, draft-mih-scitt-agent-action-capsule-05, 26 September 2026. [NELSON] Nelson, R., "Agent Delegation Receipts", Work in Progress, Internet-Draft, draft-nelson-agent-delegation-receipts-12, 10 October 2026. [RFC7942] Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, July 2016. [RFC8915] Franke, D., Sibold, D., Teichel, K., Dansarie, M., and R. Sundblad, "Network Time Security for the Network Time Protocol", RFC 8915, September 2020. Piehl Expires 14 April 2027 [Page 35] Internet-Draft AI Agent Rule Provenance October 2026 [VAP] Yamakawa, S., Ed., "Verifiable AI Provenance (VAP) Framework and Legal AI Profile (LAP)", Work in Progress, Internet-Draft, draft-ailex-vap-legal-ai-provenance-04, 30 September 2026. Appendix A. Examples These examples follow one refund through the profile. They show only the action_detail members that matter here; hash values are real and are the test vectors of Appendix C, while signatures and key identifiers are shortened. The operator's rule caps refunds issued through the issue_refund tool at 200 US dollars. This is version 2 of the rule, recorded in the operator's policy session: { "event": "configuration_change", "rp_rule": { "rule_id": "refunds-cap", "rule_version": 2, "language": "example-rules/1.0", "rule_body": {"max_refund_usd": 200}, "effect": "limit", "scope": {"agents": ["urn:example:agent-17"], "action_types": ["tool_call"], "tools": ["issue_refund"]}, "effective_from": "2026-10-20T00:00:00Z", "rule_hash": "8760c0bbf1d8c57e362c477f680a0fcebb9e548330935708ebb426be71cfe9fd", "set_by": "p-owner-1", "set_at": "2026-10-19T21:02:11Z", "approved_by": "p-owner-1", "approved_at": "2026-10-19T21:05:40Z", "supersedes": {"rule_id": "refunds-cap", "rule_version": 1, "rule_hash": "68570cf908d655e1368a9a7541683e892859eea3abe5c48caccf24e88d063a44"} } } On 21 October the agent wants to refund 340 dollars for order A-1009. The amount is over the cap, so the evaluator's result is "deny". A manager sees that the customer was charged twice and overrides the denial. The record below is the override record, which is also the Piehl Expires 14 April 2027 [Page 36] Internet-Draft AI Agent Rule Provenance October 2026 final authorization of decision d-88412. The [SHARIF] top-level human_override object on the same record (not shown) carries operator_id "p-manager-4". { "decision_type": "rp_authorization", "policy_ref": "refunds-cap", "rp_request": { "tool_name": "issue_refund", "parameters_hash": "3bf674e24877543f350302c09e517ee041b2b21c57946c6141cef2054316cf6f" }, "rp_parameters": {"parameters": {"amount_usd": 340, "order_id": "A-1009"}, "salt": "3f9a1c0e7b2d4f6a8c5e1b7d9f0a2c4e"}, "rp_evaluation": { "decision_id": "d-88412", "target_action_type": "tool_call", "request_digest": "981de1bd56554fa82908b7a45f1bc4f49ac9af5ecac67a39c3282914e26ca8d6", "result": "deny", "rules": [{"rule_id": "refunds-cap", "rule_version": 2, "rule_hash": "8760c0bbf1d8c57e362c477f680a0fcebb9e548330935708ebb426be71cfe9fd", "applied_effect": "deny"}], "snapshot_hash": "80d61a412f499eeb5b351c042352b0e7c3089295294d403990c60770c291e4d3", "evaluated_at": "2026-10-21T15:44:02Z", "evaluator_id": "NzbLsXh8...RGC9Xs", "in_path": true }, "rp_override": { "decision_id": "d-88412", "request_digest": "981de1bd56554fa82908b7a45f1bc4f49ac9af5ecac67a39c3282914e26ca8d6", "by": "p-manager-4", Piehl Expires 14 April 2027 [Page 37] Internet-Draft AI Agent Rule Provenance October 2026 "at": "2026-10-21T15:51:30Z", "reason": "Customer charged twice; full refund owed", "overridden": [{"rule_id": "refunds-cap", "rule_version": 2, "rule_hash": "8760c0bbf1d8c57e362c477f680a0fcebb9e548330935708ebb426be71cfe9fd", "applied_effect": "deny"}] }, "rp_disposition": "permitted", "rp_disposition_basis": "override", "rp_valid_until": "2026-10-21T16:51:30Z", "rp_evaluator_signature": "kM3x...Vb9A" } The refund itself is then recorded as a [SHARIF] tool_call with record_phase "post_execution". Its action_detail holds tool_name "issue_refund", the same parameters_hash, authorization_record_id naming the record above, and rp_started_at, the moment the executing component let the refund start. The parameters here contain no personal data, so the operator chose to put them in rp_parameters (Section 13). Appendix B. Open Issues The author knows of the following gaps and intends to work on them in later versions. They are listed here so that implementers and reviewers can test against them. There is no common rule language yet, nor a registry of rule languages, so rule conditions can only be checked by a verifier that happens to implement the language a rule names. Scopes are limited to exact agent identifiers, action types and tool names, and there is no model for layering policies across tenants, operators, vendors and model providers. Time rests on a synchronized recorder clock and a tolerance, which is weaker than it could be, and the moment an action started is the operator's own statement, bounded only by the records around it. When two recorders disagree, this version detects it but cannot say which is right. There is no audit standard for independence statements, no way yet to prove that an evaluator is in-path and works only from rules it received from an independent recorder, and no proof that an approver or overriding principal actually held that authority, or of when that authority was revoked; approvals and overrides are recorded and signed by the evaluator, not by the principals who gave them. The authorization is bound to the recorded request, not to the exact operation an external system received, and Piehl Expires 14 April 2027 [Page 38] Internet-Draft AI Agent Rule Provenance October 2026 there are no compensating records for side effects of a long-running action that a later decision stops. An operator can still run an agent session that it never names to anyone; an index, kept by recorders, of the sessions each agent has opened would narrow that gap. Finally, machine-readable schemas and negative test vectors are still to come, as are bindings of this profile to record formats other than [SHARIF], such as those of [MIH] and [GILDA], and interoperability testing with independent implementations of [SHARIF]. Appendix C. Test Vectors Each vector gives the object that is hashed, its JCS [RFC8785] form (wrapped here for width; the real form is a single line with no added spaces), and the expected SHA-256. The record in Appendix A belongs to session 6f1c2a9e-3b7d-4e2a-9c1f-0a8b7d6e5f43 of agent urn:example:agent-17. C.1. rule_hash of refunds-cap version 1: {"effect":"limit","effective_from":"2026-09-01T00:00:00Z","langu age":"example-rules/1.0","rule_body":{"max_refund_usd":100},"rul e_id":"refunds-cap","rule_version":1,"scope":{"action_types":["t ool_call"],"agents":["urn:example:agent-17"],"tools":["issue_ref und"]}} SHA-256: 68570cf908d655e1368a9a7541683e892859eea3abe5c48caccf24e88d063a44 C.2. rule_hash of refunds-cap version 2: {"effect":"limit","effective_from":"2026-10-20T00:00:00Z","langu age":"example-rules/1.0","rule_body":{"max_refund_usd":200},"rul e_id":"refunds-cap","rule_version":2,"scope":{"action_types":["t ool_call"],"agents":["urn:example:agent-17"],"tools":["issue_ref und"]}} SHA-256: 8760c0bbf1d8c57e362c477f680a0fcebb9e548330935708ebb426be71cfe9fd C.3. Snapshot hash for urn:example:agent-17 at 2026-10-21T15:44:02Z, when version 2 is the only active version: [{"rule_hash":"8760c0bbf1d8c57e362c477f680a0fcebb9e548330935708e bb426be71cfe9fd","rule_id":"refunds-cap","rule_version":2}] SHA-256: Piehl Expires 14 April 2027 [Page 39] Internet-Draft AI Agent Rule Provenance October 2026 80d61a412f499eeb5b351c042352b0e7c3089295294d403990c60770c291e4d3 C.4. parameters_hash of the refund's parameters, with their salt: {"parameters":{"amount_usd":340,"order_id":"A-1009"},"salt":"3f9 a1c0e7b2d4f6a8c5e1b7d9f0a2c4e"} SHA-256: 3bf674e24877543f350302c09e517ee041b2b21c57946c6141cef2054316cf6f C.5. request_digest of decision d-88412: {"agent_id":"urn:example:agent-17","request":{"parameters_hash": "3bf674e24877543f350302c09e517ee041b2b21c57946c6141cef2054316cf6 f","tool_name":"issue_refund"},"session_id":"6f1c2a9e-3b7d-4e2a- 9c1f-0a8b7d6e5f43","target_action_type":"tool_call"} SHA-256: 981de1bd56554fa82908b7a45f1bc4f49ac9af5ecac67a39c3282914e26ca8d6 Author's Address Parker Piehl United States of America Email: parkerpiehl@gmail.com Piehl Expires 14 April 2027 [Page 40]