| Internet-Draft | Agent Action Capsules | June 2026 |
| Mih | Expires 21 December 2026 | [Page] |
- Workgroup:
- SCITT
- Internet-Draft:
- draft-mih-scitt-agent-action-capsule-01
- Published:
- Intended Status:
- Standards Track
- Expires:
An Agent Action Capsule Profile for SCITT
Abstract
This document defines a SCITT statement profile for recording what an AI agent did: the Agent Action Capsule. A Capsule is a digest-committed record of one agent action carrying its verdict-level disposition (executed, blocked, denied, errored, timed out), the deterministic constraints that were evaluated, the effect that was committed together with a confirmed-effect binding that distinguishes a dispatched attempt from an observed result, and an honest human-in-the-loop flag. Capsules are expressed as SCITT Signed Statements (COSE_Sign1) and made transparent by registration in a SCITT Transparency Service. A Capsule is recorded on every verdict, including refusals: a blocked or denied Capsule is the auditor-grade evidence that a gate worked.¶
Note to Readers
This document is an individual submission. The intended venue for
discussion is the SCITT Working Group (scitt@ietf.org). The source of
truth for the profile's prose is the specification repository from which
this document is derived; see the repository's docs/ietf-draft/README.md
for the section mapping.¶
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 21 December 2026.¶
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.¶
1. Introduction
AI agents increasingly take actions with external consequences: writing records, sending payments, filing documents. Two distinct evidentiary questions follow. The question "was this action permitted?" is answered by authorization records produced before execution. The question this profile answers is different: "what did the agent actually do?" — including the cases where the answer is "it was stopped."¶
This document profiles SCITT [I-D.ietf-scitt-architecture] Signed Statements to carry an Agent Action Capsule: a digest-committed record of one agent action and its verdict-level disposition. The profile's central design commitments are:¶
-
The may/did distinction. A Capsule records what occurred, with an effect-state binding (Section 5.2) that structurally distinguishes "the effect was dispatched" from "the effect's result was observed and bound." A producer cannot present an attempt as a completion.¶
-
A Capsule on every verdict (Section 5.4.3). Capsules are recorded for refusals, blocks, errors, and timeouts — not only for executed effects. An evidence trail that records only successes is survivorship-biased and cannot prove its gates ever fired.¶
-
Independent verifiability. The substrate guarantees (envelope signature, registration, receipt) are SCITT's and are verified by reference; the agent-domain checks defined here (Section 6, Section 8.2) are deterministic and reproducible by any verifier from the record's own bytes, in two conformance classes (Section 7).¶
The terms "statement profile" and "profile" in this document always mean a SCITT statement profile in the sense of [I-D.ietf-scitt-architecture]: a constraint on the protected header and payload of a Signed Statement. The word is never used in any other sense in this document.¶
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 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
- Capsule:
-
The Agent Action Capsule — the JSON payload of a profiled Signed Statement, recording one agent action.¶
- Verdict:
-
The terminal outcome of one agent action — what the decision gate concluded and what is consequently known about the effect.¶
- Disposition:
-
The digest-committed block within a Capsule recording how the decision was disposed: the gate outcome, who disposed it, an honest human-in-the-loop flag, and optionally a verdict reason-class.¶
- Producer:
-
The party that constructs, signs, and (for the transparent tier) registers Capsules.¶
- Verifier:
-
Any party that validates a Capsule from its bytes, without trusting the Producer. Verifier conformance is split into two classes (Section 7).¶
- JSON-DIGEST:
-
HEX(SHA-256(JCS(normalize(v)))) — the lowercase-hex SHA-256 of the [RFC8785] JSON Canonicalization Scheme serialization of a value after absent-field normalization (members whose value is null, an empty array, or an empty object are removed, bottom-up). All JSON digests in this profile use this single construction.¶
3. The SCITT Signed Statement envelope
3.1. Protected header and payload media type
A Capsule is carried as the payload of a SCITT Signed Statement — a COSE_Sign1 [RFC9052] (a CBOR structure, [RFC8949]). The protected header MUST carry the CWT Claims parameter (label 15) [RFC8392] with:¶
| Claim | Req | Meaning |
|---|---|---|
| iss (CWT 1) | REQUIRED | The signing agent identity (the Capsule's developer). |
| sub (CWT 2) | REQUIRED | urn:agent-action-capsule:OPERATOR:ACTION_ID — the tenant-scoped action subject (provisional URN namespace; see below). |
| capsule_statement_type | REQUIRED | "agent_action" or "outcome". Additional values are reserved (Section 11). |
| capsule_action_type | RECOMMENDED | "fyi" or "decide" — lets a registration policy gate by action class without parsing the payload. |
| capsule_decision_id | RECOMMENDED | Correlates the statements of one decision (and its outcomes) at the SCITT layer. |
plus alg, kid, and content_type per COSE. The content_type MUST
be application/agent-action-capsule+json (or the outcome media type,
Section 3.3). The capsule_* protected-header claim set is CLOSED:
extensions are payload-only (Section 9). The capsule_* claim
labels are provisional string-keyed names pending registration in the
existing IANA "CWT Claims" registry; a future revision pins integer
labels. The urn:agent-action-capsule: namespace of the sub claim is
likewise provisional and used here by example; a future revision either
registers a formal URN namespace ([RFC8141]) or replaces it with a
profile-defined subject scheme. A plain structured-string subject (no URN
form) is under consideration for that revision, since the CWT sub claim
does not require URN syntax; the choice is deferred to avoid churning the
protected-header subject format in this revision.¶
A field is a protected-header claim only if a SCITT-generic party (a Transparency Service registration policy, or a profile-unaware verifier) must act on it without understanding this profile; everything semantically rich stays in the payload.¶
3.2. Registration and Receipts
A producer makes a Capsule transparent by registering its Signed
Statement with a SCITT Transparency Service per
[I-D.ietf-scitt-architecture] and attaching the returned Receipt
(COSE Receipts, [I-D.ietf-cose-merkle-tree-proofs]) to the unprotected
header, forming a Transparent Statement. This profile does not define
receipt formats or proof verification; both are the substrate's, by
reference. A verifier MUST NOT report attestation_mode: "anchored"
without having verified a Receipt from a Transparency Service whose key
it trusts. A conforming anchor is any SCITT Transparency Service; this
profile requires no specific operator. The transport of registration
requests is likewise out of scope: [I-D.ietf-scitt-scrapi] defines a
reference registration API, and a Transparency Service may employ a
receipt profile such as [I-D.ietf-scitt-receipts-ccf-profile]; this
profile is indifferent to both choices.¶
3.3. Outcomes
An asynchronously observed consequence — a reversal, dispute, correction,
or confirmation — is recorded as its own Signed Statement
(capsule_statement_type: "outcome", content type
application/agent-action-capsule-outcome+json) whose sub equals the
original action's sub. Correlation is by subject and decision id, never
by mutating the original statement: the log is append-only and the
original is immutable.¶
4. Registries of this profile (summary)
Six vocabularies of this profile are registry-governed under a
Specification Required policy ([RFC8126], Section 4.6):
verdict_class, disposition.decision, effect.type,
irreversibility_class, effect_attestation, and chain.relation. The
registries and their initial contents are defined in Section 12, kept at
the back of this document per convention.¶
The binding invariant, stated once here and again in Section 12: verifiers MUST treat unregistered values as informational and MUST NOT reject a Capsule for carrying one. Registration governs shared meaning, never acceptance. Every registry check in this profile is performable from the Capsule's own bytes and the registry contents alone.¶
5. The Agent Action Capsule
A Capsule is a JSON object: the envelope that is disclosed and digest-committed. Sensitive content (model reasoning, evaluated evidence, raw tool payloads) is not carried in the envelope; it is committed to by digest only. A Capsule also carries Constraint Records — the public verdicts of the deterministic checks that ran against the action; their detail is specified in Section 8.1.¶
5.1. Identity and parties
| Field | Type | Req | Meaning |
|---|---|---|---|
| spec_version | string | REQUIRED | The profile prose version the Capsule conforms to. The value defined by this profile version is "draft-mih-scitt-agent-action-capsule-01"; it tracks the document name and advances with each revision. |
| format_version | string | REQUIRED | The serialization-suite version of the envelope. The value defined by this profile version is "2"; the value reflects the pre-IETF reference-implementation serialization lineage this profile inherits, which is why a -00 document begins at "2" rather than "1". |
| capsule_id | string (64 hex) | REQUIRED | JSON-DIGEST of the canonical capsule form: the envelope minus capsule_id and chain-linkage fields, after absent-field normalization. Content-addresses the envelope. |
| action_id | string | REQUIRED | Stable identifier of the action; unique within one producer ledger. |
| action_type | string | REQUIRED | "fyi" (informational) or "decide" (a disposition was required). |
| operator | string | REQUIRED | The accountable tenant the action was performed for. |
| developer | string | REQUIRED | The agent identity and version that performed the action. |
| timestamp | string | REQUIRED | [RFC3339] UTC with "Z" suffix. |
Monetary and quantity values anywhere in a Capsule MUST be exact decimal strings, never JSON floating-point numbers; digests are not reproducible across implementations otherwise.¶
Chain-linkage fields are intentionally excluded from capsule_id so that
a Capsule's content-address remains stable regardless of what later chains
to it — including the chain block itself, which references a parent's
capsule_id and so could not be inside the address it helps compute. This
exclusion does not weaken integrity: the entire Capsule payload, the chain
block included, is signed within the COSE_Sign1 envelope (Section 3.1),
so the chain linkage is tamper-evident even though it is not part of the
content-address.¶
5.2. Effect Record and the confirmed-effect binding
The Effect Record describes the side effect the action committed. Its
status member takes one of five values:¶
| status | Meaning | Binding requirement |
|---|---|---|
| planned | Intended, not dispatched. | request_digest and response_digest MUST be absent. |
| dispatched | Sent; result not observed. | request_digest SHOULD be present; response_digest MUST be absent. |
| confirmed | Result observed and bound. | response_digest MUST be present and MUST be the JSON-DIGEST of the actual response. |
| failed | Attempted; runtime reported failure (state known). | response_digest, when present, digests the failure response. |
| reverted | A committed effect was undone. | Correlated via external_ref / decision_id. |
The confirmed-effect invariant: a producer MUST NOT emit
status: "confirmed" without a response_digest over the actually
observed response. A verifier MUST treat confirmed with a missing
response_digest as a verification failure. This is the byte-level
mechanism behind the may/did distinction: "confirmed" is an observed
result, never a promise.¶
The Effect Record also carries the logical type (registry-governed,
Section 12), an optional external_ref join key for later outcomes, and an
irreversibility_class — an ordered consequence enumeration (two_way,
one_way_recoverable, one_way_consequential, one_way_terminal;
registry-governed, Section 12).¶
The Effect Record additionally carries effect_attestation: WHO vouches
for the effect's execution — the evidence grade of the effect claim. The
vocabulary is registry-governed (Section 12; Specification Required), seeded
with two values:¶
| effect_attestation | Meaning |
|---|---|
| gate_executed | The commit transited the gate; the engine observed the effect boundary directly. |
| runtime_claimed | The gate issued a verdict only; the executing runtime asserted completion; the capsule records that claim, not an observation. |
Validity is checked against the assurance effect_mode (Section 5.3):¶
| effect_mode | effect_attestation |
|---|---|
| confirmed | REQUIRED (states WHO confirmed) |
| dispatched_unconfirmed | REQUIRED |
| not_applicable | MUST be absent — nothing executed, there is no claim to grade |
The planned carve: effect.status: "planned" asserts no execution, so
effect_attestation MUST be absent — there is nothing to grade, and a
phantom grade would poison grade-based queries. It becomes REQUIRED the
moment dispatch occurs.¶
The matrix is total over the effect.status values of Section 5.2. An
effect.status of failed (the effect was dispatched and the runtime
reported a failure; state known) derives effect_mode:
"dispatched_unconfirmed" — the effect was dispatched and its result, though
a failure, was not gate-confirmed; therefore effect_attestation is REQUIRED.
reverted (a previously-committed effect was undone) likewise derives
effect_mode: "dispatched_unconfirmed" and REQUIRES effect_attestation; the
underlying committed effect it reverses is correlated separately via
external_ref / decision_id (the Effect Record fields, Section 5.2), not
by a distinct effect_mode. So
every effect.status other than planned (carved above) and the
no-effect case (not_applicable) requires effect_attestation.¶
Consumers MUST treat an unregistered or unrecognized effect_attestation
value as no stronger than runtime_claimed; unknown values are
informational, never a verification failure, and unknown never grades up.
The grade is digest-committed in the Capsule payload and is available to
any payload-bearing verifier, which can thereby distinguish gate-observed
execution from runtime-claimed execution; promotion of the grade to a
protected-header (CWT claim) position is an explicit candidate for a -02
revision, to be decided once real transparency-log consumers exist. This
version deliberately claims no header-level visibility for the grade.¶
5.3. Assurance
Every Capsule carries an assurance object stating, as
independently-rederivable claims: attestation_mode ("self_attested" or
"anchored"), effect_mode ("not_applicable", "dispatched_unconfirmed", or
"confirmed"), and ledger_mode ("standalone", "chained", or "anchored").
ledger_mode records the custody tier of the record: "standalone" is a
lone Capsule (no chain linkage); "chained" is a Capsule whose hash-chain
linkage to a predecessor is present and intact; "anchored" is a chained
Capsule whose chain root has additionally been committed to an independent
transparency log. A verifier rederives ledger_mode from the bytes it can
check — "standalone" versus "chained" from the presence and integrity of
the hash-chain linkage, and "anchored" only after it verifies an inclusion
proof against a trusted log key — and the three tiers are ordered
standalone < chained < anchored for overclaim detection. A producer MUST
NOT record an assurance mode it did not achieve; a verifier rederives each
mode from the evidence present and reports any overclaim.¶
5.4. Disposition and the verdict reason-class
A Capsule's disposition block records how the decision was disposed:¶
-
decision(REQUIRED): "accept", "reject", "needs_input", or "deferred" (registry-governed, Section 12).¶ -
approver(REQUIRED): a closed enum, exactly "human" or "policy". The value domain is fixed by this specification (not registry-governed); an unknown approver value is not a conforming Capsule.¶ -
human_disposed(REQUIRED, boolean): the honest in-the-loop flag — true ONLY when a human actually acted. A policy auto-approval is false.human_disposed: trueREQUIRESapprover: "human"; a producer MUST NOT claim a human disposed what a policy did.¶ -
authority(OPTIONAL): an opaque reference to the authority under which a non-human disposition acted. A conforming Capsule carries at most the reference, never the authority's internal structure.¶ -
verdict_class(OPTIONAL): the terminal-verdict reason-class (Section 5.4.1). It is RECOMMENDED for any non-executed verdict, where it carries the terminal reason; it is legitimately absent for a cleanexecutedverdict (which has no reason-class, mirroring an absentreason_digest).¶ -
reason_digest(OPTIONAL): JSON-DIGEST of a structured, private reason object — machine-readable members such as the constraint identifier, the threshold, and the observed value; never free prose — so two engines attesting the same refusal produce the same digest. The member is absent (not a digest of an empty object) when a verdict has no reason, such as a clean "executed".¶ -
expiry_policy(OPTIONAL; deferral dispositions only): a digested{ttl_seconds, on_expiry}object —ttl_secondsis an integer count of seconds, never a duration string, andon_expiryis "expired" or "escalated".ttl_secondsis evaluated against the deferral Capsule's registration time — thetimestampfield inside the digest commitment — not the Transparency Service receipt time, and not a consumer's local wall clock; a named clock basis is what makes the expiry computation deterministically reproducible, so any verifier derives the same elapsed-time result from the record's own bytes. The deferral's frozen summary is a digest-committed, content-side layer written once at deferral time; it MUST NOT be regenerated.¶
5.4.1. The verdict_class vocabulary
verdict_class records WHY the action terminated as it did. The seeded
vocabulary (registry-governed, Section 12; unregistered values are
informational to a verifier, never a rejection):¶
| verdict_class | Meaning |
|---|---|
| executed | The action ran. |
| blocked | A blocking constraint stopped it before dispatch. |
| hitl_dispatched | Routed to a human operator; awaiting resolution. |
| denied | An operator or policy refused it before dispatch. |
| timeout | The decision timed out (see the orthogonality rule). |
| errored | The action ran and threw; final state unknown. |
| engine_failure | The engine could not evaluate the action. |
| deferred | A human elected to postpone the decision; open item. |
| needs_decision | Evaluation complete; decision required, not yet routed to a decider; open item. |
| expired | TTL policy on the deferral elapsed; terminal unless superseded by escalation. |
| escalated | Expiry or policy routed the item to a higher authority; open item at the new authority. |
| resolved | A terminal decision Capsule closed the chain without executing — the non-executing closure only (see the pairing rule, Section 5.4.2). |
hitl_dispatched and deferred are sequential states, not synonyms:
hitl_dispatched means sent to a decider and awaiting response;
deferred means a decider responded "later".¶
5.4.2. Orthogonality with effect_mode
verdict_class (why the verdict) and assurance.effect_mode (what is
known about the effect) are independent axes and MUST NOT be folded into
one another:¶
-
The pre/post-dispatch distinction lives in
effect_mode, not in the class. A timeout before dispatch isverdict_class: "timeout"witheffect_mode: "not_applicable"; a timeout after dispatch isverdict_class: "timeout"witheffect_mode: "dispatched_unconfirmed". Onetimeoutvalue covers both.¶ -
erroredpairs witheffect_mode: "dispatched_unconfirmed"— the effect was dispatched and may have left a partial side effect.not_applicablewould falsely assert nothing happened, which is the inverse of attesting an execution that did not occur and equally non-conforming.¶ -
A class that by its kind never dispatches (
blocked,hitl_dispatched,denied,engine_failure,deferred,needs_decision,expired,escalated,resolved) REQUIRES the derivedeffect_modeto be"not_applicable". A verifier reports any other derived mode as an error: an effect attempt contradicts a verdict that claims it never executed.¶ -
The pairing rule:
resolvedis exclusively the NON-executing closure (decline, waive, recorded-elsewhere) — it pairs witheffect_mode: "not_applicable"and an absenteffect_attestation. An EXECUTING closure is encoded asverdict_class: "executed"chainedsupersedesto the deferral (Section 5.4.4) — one valid encoding of "closed with effect", never two.¶ -
The effect status
"failed"(ran and returned a clean failure, state known) is distinct fromverdict_class: "errored"(ran and threw, state unknown). "failed" is an effect status, never a reason-class.¶
5.4.3. A Capsule on every verdict
A conforming producer MUST record a Capsule for every verdict, whatever
its disposition. This requirement is universal over the verdict_class
vocabulary — the IANA registry of this document (Section 12) — and
applies to every value later admitted by registration; it is
deliberately not stated as an enumerated list, which would go stale the
moment Specification Required admits a new value. A refusal or block with
no Capsule is invisible to an auditor; a blocked or denied Capsule is
auditor-grade evidence that the gate worked: the affirmative,
digest-committed record that the constraint or policy fired and the
action did not proceed. Recording only successes makes the evidence trail
survivorship-biased and the refusal path unverifiable.¶
5.4.4. Chained Capsules and human-in-the-loop resolution
Every Capsule that references a prior Capsule carries a digested chain
block: {parent_capsule_id, relation}. The relation vocabulary is
registry-governed (Section 12; Specification Required), seeded with one
value:¶
| relation | Meaning |
|---|---|
| supersedes | Terminal transition over the parent — resolution, expiry, escalation close or replace the parent's open state. |
Single-parent is intentional: a Capsule chains to exactly one parent.¶
Human-in-the-loop resolution is the supersedes relation: a
hitl_dispatched Capsule is sealed at dispatch time and is never
mutated. When the decision is later resolved, that resolution is a
second, linked Capsule carrying its own disposition and chaining to the
dispatch Capsule with relation: "supersedes". The dispatch Capsule
stays hitl_dispatched forever; resolution state lives only on the
resolution Capsule, preserving the append-only model.¶
Concurrent-supersedes rule: the ledger is append-only and totally
ordered; the earliest capsule in ledger order with relation=supersedes
over a given parent is authoritative; any later supersedes over the same
parent is structurally valid but MUST surface as a verification finding.¶
Open-items predicate: an item is open when its Capsule's
verdict_class is one of deferred, needs_decision,
hitl_dispatched, escalated, or blocked, and no Capsule in the
store carries chain.parent_capsule_id equal to its capsule_id with
relation: "supersedes".¶
6. Class 1 verification
Verification has two tiers. Substrate verification — the issuer's COSE_Sign1 signature, and for the transparent tier the Receipt's inclusion proof and Transparency Service signature — is performed by reference to [RFC9052], [I-D.ietf-scitt-architecture], and [I-D.ietf-cose-merkle-tree-proofs]; this profile does not respecify it.¶
The agent-profile checks below are normative here and constitute Class 1
verification (Section 7): every check is performable from the
Signed Statement, the Capsule payload, the registry contents
(Section 4), and — for the chain checks — the producer's store of
Capsules; no other input is needed. A verifier MUST return a structured
result, never throw; a single ok boolean gates trust in every other
reported field; findings are reported in a fixed order.¶
-
Structural: REQUIRED fields present and typed; no floating-point values in digest-bearing fields.¶
-
Identity: recompute
capsule_idover the canonical capsule form and compare.¶ -
Confirmed-effect binding:
effect.status: "confirmed"without a well-formedresponse_digestis a failure (Section 5.2).¶ -
Verdict/effect orthogonality: a never-dispatching
verdict_classwith a derivedeffect_modeother than"not_applicable"is a failure (Section 5.4.2);resolvedis in the never-dispatch set per the pairing rule.¶ -
Effect-attestation matrix:
effect_attestationmissing where the matrix REQUIRES it, or present where it MUST be absent — including the planned carve — is a failure (Section 5.2).¶ -
Chain semantics (store-level): a missing chain parent is a failure; concurrent supersedes surface as findings per Section 5.4.4.¶
-
Assurance reconciliation: rederive the assurance modes from evidence actually verified; report overclaims.¶
-
Unknown registry values (
verdict_class,decision,effect.type,irreversibility_class,effect_attestation,chain.relation): report as informational findings; MUST NOT reject (Section 12). An unknowneffect_attestationis additionally graded no stronger thanruntime_claimed(Section 5.2).¶
Disposition honesty is structurally guaranteed, not a live check above.
The honesty invariant — human_disposed: true REQUIRES approver:
"human" (Section 5.4) — is enforced when the disposition is
constructed: the typed disposition carrier rejects human_disposed:
true paired with any non-human approver, so a violating Capsule
cannot be formed or signed at all. A Class 1 verifier
therefore does not re-assert it in the enumeration above; like
parse- and type-level malformations that a typed record cannot
represent, a dishonest disposition is an unrepresentable state rather
than a runtime failure mode. A verifier consuming arbitrary bytes not
produced by a conforming constructor SHOULD nonetheless assert the
invariant defensively against hand-crafted input. The
closed approver enum (Section 5.4) is likewise structural: an
approver value outside {human, policy} is non-conforming by
construction and so is absent from the unknown-registry-value reporting
of check 8.¶
NOTE (Class 1 test vector, effect-attestation matrix, check 5): a Capsule
carrying effect.status: "failed" derives effect_mode:
"dispatched_unconfirmed" (Section 5.2); the matrix therefore REQUIRES
effect_attestation. A conforming verifier MUST report a check-5 failure
for such a Capsule when effect_attestation is absent, and MUST NOT treat
the failed status as exempt (only planned is carved, and only
not_applicable is the no-effect case). The same expectation holds for
effect.status: "reverted", which likewise derives
dispatched_unconfirmed. This vector exists to demonstrate the matrix is
total over effect.status: the runtime reporting a failure is still a
dispatch, and a dispatch that escapes attestation is the precise condition
check 5 exists to catch.¶
A verifier MUST NOT consult a model, a clock-dependent heuristic, or
network state to decide ok for the checks above. Manifest-dependent
verification is Class 2 (Section 8.2).¶
7. Conformance: two verifier classes
This profile defines two verifier conformance classes. Producer conformance is a single class and is unchanged by this split: a conforming producer emits the same Capsules regardless of which verifier class consumes them.¶
- Class 1 verifier:
-
Verifies the Signed Statement envelope and the Capsule payload WITHOUT any constraint manifest: substrate verification by reference, the structural and identity checks, the registry vocabularies, the digest recomputations, and the validity matrices (confirmed-effect binding, verdict/effect orthogonality, effect-attestation, chain semantics). The complete Class 1 check set is Section 6.¶
- Class 2 verifier:
-
A Class 1 verifier that additionally performs manifest-aware verification (Section 8.2): constraint evidence-schema checks and manifest-sourced thresholds. Class 2 conformance presupposes access to the producer's constraint manifest and the private evidence its Constraint Records bind; absent those inputs, a Class 2 verifier reports Class 1 results unchanged.¶
8. Manifest-dependent material
The producer's constraint manifest — the private definition of each constraint's predicate, evidence schema, and thresholds — is not carried in the Capsule. The material in this section depends on it: the detail of Constraint Records and the Class 2 checks. Manifest discovery and authentication are out of scope for this profile; they are expected to be handled via out-of-band tenant configuration or a future discovery mechanism.¶
8.1. Constraint Records
A Constraint Record is the public verdict of one deterministic check that
ran against the action. It carries only sanitized categories — an id,
optional check_type and method labels, a result of "pass" / "fail" /
"n/a", severity, a blocking flag recording whether the check actually
gated this decision, and an optional evidence_digest (JSON-DIGEST)
binding the verdict to the private evidence the check evaluated. The
content a check evaluated MUST NOT appear in the public record; it is
bound by digest only. The check's predicate, evidence schema, and
thresholds live in the producer's manifest.¶
Every recorded result MUST be the output of a deterministic predicate
over disclosed or digest-committed evidence. The live decision path MUST
NOT re-prompt a model to make a check pass, and a verifier MUST NOT
re-prompt a model to "re-check" one: re-running a non-deterministic check
is not verification.¶
Constraint id, check_type, and method values are lowercase
snake_case categories. New values follow the namespacing convention of
Section 9.1.¶
8.2. Class 2 verification
The checks below are manifest-aware: they require the producer's constraint manifest and the private evidence a Constraint Record binds by digest. A Class 2 verifier performs them in addition to the complete Class 1 set (Section 6); their results never weaken a Class 1 result — they extend it.¶
-
Constraint evidence-schema check: for each Constraint Record (Section 8.1) carrying an
evidence_digest, confirm the bound evidence conforms to the manifest's evidence schema for that constraintidand that the recomputed digest matches; a mismatch is a failure.¶ -
Threshold checks: confirm that manifest-sourced thresholds were applied as the manifest states.¶
9. Extensibility
All extension points are payload-only. The protected-header capsule_*
claim set is closed by this profile version: a strict Transparency
Service registration policy may reject statements bearing header claims
it does not recognize, while payload bytes are opaque to it — so a
payload-only extension can never make a Capsule unregistrable. A verifier
encountering an unrecognized capsule_* header claim MUST still verify
and report it as informational; rejection of unknown header claims is a
registration-policy prerogative, not a verifier behavior.¶
9.1. Namespacing convention
Three vocabularies are deliberately not registry-governed — constraint
id/check_type, compliance.framework_tags, and
assurance.sources[].kind — because their value space is producer-local
by nature. Bare names (no namespace separator) are reserved for the
values seeded in this document; any party introducing a new value MUST
namespace it with a URI or reverse-DNS prefix (for example,
com.example.margin_floor). A bare, unseeded name is non-conforming for
a producer; a verifier still treats it as informational.¶
9.2. Selective Disclosure
The base confidentiality posture of this profile is whole-envelope: a producer discloses a Capsule by sharing its full payload, or withholds it entirely. Sensitive content not carried in the envelope leaves no on-wire indicator of its existence. This whole-envelope posture is sufficient for the common case where the unit of disclosure is the Capsule as a whole.¶
For cases in which a producer must reveal a subset of payload fields to a verifier while concealing both the values and the existence of unrevealed fields, a per-field selective-disclosure mechanism is needed. This profile reserves an extension point in the Capsule payload for such a mechanism. The intended field-level technique follows the SD-JWT selective-disclosure model [RFC9901] — salted-hash commitments over JCS-canonicalized arrays — because the Capsule payload is JSON; it is written to stay aligned with SPICE's SD-CWT [I-D.ietf-spice-sd-cwt] (the CBOR sibling) for SCITT-ecosystem consistency.¶
The complete normative profile of this extension — including the
commitment encoding, disclosure syntax, and verifier checks — is defined
in the companion Internet-Draft [I-D.mih-scitt-agent-action-capsule-selective-disclosure].
That document profiles the _sd_alg / _sd payload vocabulary, the
salted-hash commitment construction over JCS-serialized disclosure arrays,
the decoy-digest mechanism, the set of eligible fields, and the ordered
verifier check set (SD-1 through SD-6 plus integration with the base
Class 1 and Class 2 checks).¶
Implementations of this profile version MUST NOT generate or interpret selective-disclosure payload structures unless they additionally implement [I-D.mih-scitt-agent-action-capsule-selective-disclosure]: the extension point is defined only in that companion, and no conformance claim or verification behavior is defined for it in this document.¶
11. Future Work
An extension for additional attestation scenarios is in preparation; it will define additional statement-type and verdict values, which are reserved for that purpose.¶
The companion Internet-Draft [I-D.mih-scitt-agent-action-capsule-selective-disclosure] normatively profiles the selective-disclosure extension point reserved in Section 9.2, specifying the per-field commitment structure, disclosure syntax, eligible fields, and verifier checks, aligned with [I-D.ietf-spice-sd-cwt].¶
12. IANA Considerations
12.1. New registries
Every registry requested below governs a vocabulary that lives entirely
in the Capsule payload — values a SCITT-generic Transparency Service
never parses, since registration, inclusion, and Receipt issuance operate
on the COSE_Sign1 envelope and its protected header, not on payload
content. The registrations this profile requests against existing IANA
registries are the capsule_* CWT claims (Section 12.2) and the
two media types of Section 12.3; both are addressed separately from the
payload-vocabulary registries here. This profile requests no new COSE
header parameter registry and no new CWT claim registry; the new
registries here are payload-vocabulary registries only.¶
IANA is requested to create a new registry group, "Agent Action Capsule Parameters", containing the six registries below. The registration policy for each is Specification Required ([RFC8126], Section 4.6).¶
Specification Required is chosen deliberately. The threat it answers is a vocabulary value whose meaning is defined only inside a closed product — two verifiers would then disagree on what the value means, and the interoperable, falsifiable-from-the-record property this profile depends on would erode. The mitigation is the policy's publicly-available-spec requirement: a value enters the shared vocabulary only once its semantics are pinned in a specification any implementer can read. Accordingly, for each registry the designated expert approves a registration when (1) the citing specification defines the value's semantics precisely enough that two independent implementations would apply it identically — for verdict_class, including its dispatch consequence and its effect_mode pairing under Section 5.4.2; (2) the value's meaning is not already expressible by an existing registered value; and (3) the citing specification is publicly available.¶
Binding invariant for all six registries: verifiers MUST treat unregistered values as informational and MUST NOT reject a Capsule for carrying one. Registration governs shared meaning, never acceptance.¶
Initial contents are the seeded values of this document, verbatim:¶
-
"verdict_class" registry (Section 5.4.1): executed, blocked, hitl_dispatched, denied, timeout, errored, engine_failure, deferred, needs_decision, expired, escalated, resolved. The
deferredtoken's semantics are OWNED by this registry; the entry of the same spelling in the "disposition.decision" registry is a cross-reference to it.¶ -
"disposition.decision" registry (Section 5.4): accept, reject, needs_input, deferred. The
deferredentry is a cross-reference to the "verdict_class" registry, which owns the token's semantics.¶ -
"effect.type" registry (Section 5.2): write_order, send_payment.¶
-
"irreversibility_class" registry (Section 5.2; ordered by ascending consequence — a registration states its position): two_way, one_way_recoverable, one_way_consequential, one_way_terminal.¶
-
"effect_attestation" registry (Section 5.2): gate_executed, runtime_claimed. The registry definition carries the grade-floor invariant of Section 5.2 — an unregistered or unrecognized value is graded no stronger than runtime_claimed; unknown never grades up — and the planned carve of Section 5.2: with
effect.status: "planned"the member MUST be absent, and it becomes REQUIRED the moment dispatch occurs. Designated-expert guidance: plausible future registrations exist and are deliberately not seeded — for example, independent sensor confirmation of a claimed effect, or hardware- or TEE-anchored execution; a registration states where its grade sits relative to the seeded values.¶ -
"chain.relation" registry (Section 5.4.4): supersedes. Designated-expert guidance: this registry is seeded with the single terminal relation; additional non-terminal relations (for example, deposit-toward-open and effort-toward-open relations, or amends / contradicts) are expected future registrations, each admitted once its semantics and any verifier consequence are pinned in a publicly available specification.¶
Interim registry of record: until this document is published as an RFC,
the registry of record is the REGISTRY.md file of the source
specification repository, seeded with the same initial contents and the
same policy; on publication the IANA registries become the registry of
record. Change controller: Action State Group, Inc. (interim); the IETF
on publication.¶
12.2. No new registry
-
Attestation/signature algorithms: this profile defines no algorithm registry; algorithm identifiers are those of the existing IANA "COSE Algorithms" registry ([RFC9053]).¶
-
Constraint
id/check_type,compliance.framework_tags, andassurance.sources[].kind: no registry; governed by the namespacing convention of Section 9.1.¶ -
The
capsule_*CWT claim labels: registration is requested in the existing IANA "CWT Claims" registry ([RFC8392]), not in a new registry; the claim set is closed by this profile version.¶
12.3. Media Type Registrations
This profile mandates two media types (Section 3.1, Section 3.3); IANA is
requested to register both in the "Media Types" registry per the templates
below ([RFC6838], with the +json structured-syntax suffix of
[RFC8259]).¶
Agent Action Capsule media type:¶
-
Type name: application¶
-
Subtype name: agent-action-capsule+json¶
-
Required parameters: N/A¶
-
Optional parameters: N/A¶
-
Encoding considerations: binary; the payload is JSON ([RFC8259]) as defined in this document, carried as the payload of a COSE_Sign1 ([RFC9052]) Signed Statement.¶
-
Security considerations: see Section 13 of this document.¶
-
Interoperability considerations: see this document.¶
-
Published specification: this document (and its successors).¶
-
Applications that use this media type: SCITT ([I-D.ietf-scitt-architecture]) producers and verifiers recording and verifying AI agent actions.¶
-
Fragment identifier considerations: as for application/json ([RFC8259]) per the
+jsonsuffix ([RFC6839]).¶ -
Additional information: Deprecated alias names: N/A. Magic number(s): N/A. File extension(s): N/A. Macintosh file type code(s): N/A.¶
-
Person & email address to contact for further information: the author of this document.¶
-
Intended usage: COMMON¶
-
Restrictions on usage: N/A¶
-
Author: see the Authors' Addresses section of this document.¶
-
Change controller: Action State Group, Inc. (interim); the IETF on publication.¶
-
Provisional registration: yes (pending publication of this document).¶
Agent Action Capsule outcome media type:¶
-
Type name: application¶
-
Subtype name: agent-action-capsule-outcome+json¶
-
Required parameters: N/A¶
-
Optional parameters: N/A¶
-
Encoding considerations: binary; the payload is JSON ([RFC8259]) as defined in Section 3.3 of this document, carried as the payload of a COSE_Sign1 ([RFC9052]) Signed Statement.¶
-
Security considerations: see Section 13 of this document.¶
-
Interoperability considerations: see this document.¶
-
Published specification: this document (and its successors).¶
-
Applications that use this media type: SCITT ([I-D.ietf-scitt-architecture]) producers and verifiers recording asynchronous outcomes correlated to an agent action.¶
-
Fragment identifier considerations: as for application/json ([RFC8259]) per the
+jsonsuffix ([RFC6839]).¶ -
Additional information: Deprecated alias names: N/A. Magic number(s): N/A. File extension(s): N/A. Macintosh file type code(s): N/A.¶
-
Person & email address to contact for further information: the author of this document.¶
-
Intended usage: COMMON¶
-
Restrictions on usage: N/A¶
-
Author: see the Authors' Addresses section of this document.¶
-
Change controller: Action State Group, Inc. (interim); the IETF on publication.¶
-
Provisional registration: yes (pending publication of this document).¶
13. Security Considerations
Tamper-evidence is for record bytes, not recorder honesty. This profile attests what was recorded; it cannot prove the recording runtime was honest at the moment of recording. A dishonest runtime with no external witness can produce an internally valid record of a fiction. Registration in a Transparency Service bounds the timing of such a record and makes its omission or later substitution detectable; it does not make its content true.¶
Confirmed means observed-and-bound, not world-state. A confirmed
effect proves the producer bound the bytes of an observed response, not
that the external world reached the claimed state. The same boundary
extends one hop upstream: binding an observed response proves the producer
observed those bytes, not that the responding system was authentic or that
the channel was on-path-intact. An attacker who substitutes or forges the
response — a false success delivered on-path — induces an honest
confirmed Capsule for an effect that did not land; this profile does not
mitigate upstream spoofing of the response itself, which is bounded by the
same trust assumption as runtime honesty above. Later, independently
sourced outcome statements (Section 3.3) are the mechanism by which such
a spoofed confirmation is contradicted over time.¶
Self-attested versus anchored tiers differ in evidentiary weight. A self-attested Capsule is verifiable against its own bytes and signer; an anchored (registered) Capsule additionally resists omission and back-dating through the Transparency Service's append-only log and receipts. A verifier reports the tier it actually verified and never upgrades a claim it could not check.¶
The honest human-in-the-loop flag (Section 5.4) is itself
security-relevant: it prevents a policy auto-approval from being
presented as human oversight. The invariant — human_disposed: true
requires approver: "human" — is structurally guaranteed: a conforming
producer cannot construct or sign a Capsule that violates it, so the
combination simply does not arise in well-formed records, and the claim
is falsifiable from the record alone. A verifier consuming
non-constructor-produced bytes SHOULD assert the invariant defensively
against hand-crafted input (Section 6).¶
Digests can leak the values they commit. A digest is hiding only to the
extent its committed value space is large and unguessable; when the
committed value is low-entropy — a small enumeration, a short identifier,
a bounded amount — an adversary can recover it by digesting candidate
values and matching (a dictionary attack), so a reason_digest,
evidence_digest, or any other digest over a low-entropy value is not
confidential merely by being a digest. Producers SHOULD commit such values
under a per-tenant salt or via a tenant-private manifest rather than
digesting the bare value, so that recovering the input requires the secret
and not merely a guess of the value space.¶
14. References
14.1. Normative References
- [I-D.ietf-scitt-architecture]
- Birkholz, H., Delignat-Lavaud, A., Fournet, C., Deshpande, Y., and S. Lasker, "An Architecture for Trustworthy and Transparent Digital Supply Chains", Work in Progress, Internet-Draft, draft-ietf-scitt-architecture-22, , <https://datatracker.ietf.org/doc/html/draft-ietf-scitt-architecture-22>.
- [RFC2119]
- Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
- [RFC3339]
- Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, , <https://www.rfc-editor.org/rfc/rfc3339>.
- [RFC6838]
- Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, DOI 10.17487/RFC6838, , <https://www.rfc-editor.org/rfc/rfc6838>.
- [RFC8126]
- Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, , <https://www.rfc-editor.org/rfc/rfc8126>.
- [RFC8174]
- Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
- [RFC8259]
- Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/rfc/rfc8259>.
- [RFC8392]
- Jones, M., Wahlstroem, E., Erdtman, S., and H. Tschofenig, "CBOR Web Token (CWT)", RFC 8392, DOI 10.17487/RFC8392, , <https://www.rfc-editor.org/rfc/rfc8392>.
- [RFC8785]
- Rundgren, A., Jordan, B., and S. Erdtman, "JSON Canonicalization Scheme (JCS)", RFC 8785, DOI 10.17487/RFC8785, , <https://www.rfc-editor.org/rfc/rfc8785>.
- [RFC9052]
- Schaad, J., "CBOR Object Signing and Encryption (COSE): Structures and Process", STD 96, RFC 9052, DOI 10.17487/RFC9052, , <https://www.rfc-editor.org/rfc/rfc9052>.
14.2. Informative References
- [I-D.dawkins-scitt-ai-article50]
- Dawkins, V. S., "A SCITT Profile for EU AI Act Article 50 Transparency Receipts", Work in Progress, Internet-Draft, draft-dawkins-scitt-ai-article50-00, , <https://datatracker.ietf.org/doc/html/draft-dawkins-scitt-ai-article50-00>.
- [I-D.emirdag-scitt-ai-agent-execution]
- Emirdag, P., "AI Agent Execution Profile of SCITT", Work in Progress, Internet-Draft, draft-emirdag-scitt-ai-agent-execution-00, , <https://datatracker.ietf.org/doc/html/draft-emirdag-scitt-ai-agent-execution-00>.
- [I-D.ietf-cose-merkle-tree-proofs]
- Steele, O., Birkholz, H., Delignat-Lavaud, A., and C. Fournet, "COSE (CBOR Object Signing and Encryption) Receipts", Work in Progress, Internet-Draft, draft-ietf-cose-merkle-tree-proofs-18, , <https://datatracker.ietf.org/doc/html/draft-ietf-cose-merkle-tree-proofs-18>.
- [I-D.ietf-scitt-receipts-ccf-profile]
- Birkholz, H., Delignat-Lavaud, A., Fournet, C., and A. Chamayou, "CCF Profile for COSE Receipts", Work in Progress, Internet-Draft, draft-ietf-scitt-receipts-ccf-profile-03, , <https://datatracker.ietf.org/doc/html/draft-ietf-scitt-receipts-ccf-profile-03>.
- [I-D.ietf-scitt-scrapi]
- Birkholz, H., Geater, J., and A. Delignat-Lavaud, "Supply Chain Integrity, Transparency, and Trust (SCITT) Reference APIs", Work in Progress, Internet-Draft, draft-ietf-scitt-scrapi-10, , <https://datatracker.ietf.org/doc/html/draft-ietf-scitt-scrapi-10>.
- [I-D.ietf-spice-sd-cwt]
- Prorock, M., Steele, O., Birkholz, H., and R. Mahy, "Selective Disclosure CBOR Web Tokens (SD-CWT)", Work in Progress, Internet-Draft, draft-ietf-spice-sd-cwt-08, , <https://datatracker.ietf.org/doc/html/draft-ietf-spice-sd-cwt-08>.
- [I-D.kamimura-scitt-refusal-events]
- Tokachi, K., "Verifiable AI Refusal Events using SCITT", Work in Progress, Internet-Draft, draft-kamimura-scitt-refusal-events-02, , <https://datatracker.ietf.org/doc/html/draft-kamimura-scitt-refusal-events-02>.
- [I-D.kamimura-scitt-vcp]
- Tokachi, K., "A SCITT Profile for Verifiable Audit Trails in Algorithmic Trading: The VeritasChain Protocol (VCP)", Work in Progress, Internet-Draft, draft-kamimura-scitt-vcp-02, , <https://datatracker.ietf.org/doc/html/draft-kamimura-scitt-vcp-02>.
- [I-D.mih-scitt-agent-action-capsule-selective-disclosure]
- Mih, S., "Selective Disclosure Profile for Agent Action Capsules", Work in Progress, Internet-Draft, draft-mih-scitt-agent-action-capsule-selective-disclosure-00, n.d., <https://datatracker.ietf.org/doc/html/draft-mih-scitt-agent-action-capsule-selective-disclosure-00>.
- [I-D.munoz-scitt-permit-profile]
- Munoz, C., "A SCITT Profile for Pre-Execution AI Action Authorization Records", Work in Progress, Internet-Draft, draft-munoz-scitt-permit-profile-00, , <https://datatracker.ietf.org/doc/html/draft-munoz-scitt-permit-profile-00>.
- Michalak, J., "Agent Route Origin Authorization (AgentROA): A Cryptographic Policy Enforcement Framework for AI Agent Actions", Work in Progress, Internet-Draft, draft-nivalto-agentroa-route-authorization-01, , <https://datatracker.ietf.org/doc/html/draft-nivalto-agentroa-route-authorization-01>.
- [I-D.sato-soos-gar]
- Sato, "The Governance Audit Record (GAR) for Agentic AI Systems", Work in Progress, Internet-Draft, draft-sato-soos-gar-02, , <https://datatracker.ietf.org/doc/html/draft-sato-soos-gar-02>.
- [RFC6839]
- Hansen, T. and A. Melnikov, "Additional Media Type Structured Syntax Suffixes", RFC 6839, DOI 10.17487/RFC6839, , <https://www.rfc-editor.org/rfc/rfc6839>.
- [RFC8141]
- Saint-Andre, P. and J. Klensin, "Uniform Resource Names (URNs)", RFC 8141, DOI 10.17487/RFC8141, , <https://www.rfc-editor.org/rfc/rfc8141>.
- [RFC8949]
- Bormann, C. and P. Hoffman, "Concise Binary Object Representation (CBOR)", STD 94, RFC 8949, DOI 10.17487/RFC8949, , <https://www.rfc-editor.org/rfc/rfc8949>.
- [RFC9053]
- Schaad, J., "CBOR Object Signing and Encryption (COSE): Initial Algorithms", RFC 9053, DOI 10.17487/RFC9053, , <https://www.rfc-editor.org/rfc/rfc9053>.
- [RFC9901]
- Fett, D., Yasuda, K., and B. Campbell, "Selective Disclosure for JSON Web Tokens", RFC 9901, DOI 10.17487/RFC9901, , <https://www.rfc-editor.org/rfc/rfc9901>.
Acknowledgments
The author thanks the reviewers and contributors who shaped the design recorded here, and the SCITT and COSE working groups whose substrate this profile builds on.¶