AgentBoundary · v0.1 · open spec

AgentBoundary Action Receipt — v0.2-alpha

Status: Draft. Subject to revision before v0.2 stabilises. Backward compatibility: v0.1 receipts continue to validate unchanged. v0.2-alpha receipts use "version": "agentboundary/v0.2-alpha" and carry two new optional fields.

This document describes only the delta from v0.1. All v0.1 semantics still apply to v0.2-alpha receipts unless explicitly overridden here.


1. Goals

v0.1 receipts answer what an agent was allowed to do. They do not answer how confident the emitter was in each field of that answer. A receipt produced by translating a foreign audit log (e.g. Microsoft AGT, LangSmith Gateway, Cloudflare HITL) inevitably has fields the translator had to synthesize — but a v0.1 verifier reading the result has no way to tell.

v0.2-alpha adds two optional fields that let an emitter self-report which fields it observed directly, which it inferred deterministically from observed data, and which it synthesized at translation time. The score derived from those reports is computable, not asserted — a verifier MUST recompute, and a Level 4 check fails the receipt if the math doesn’t match.

This is what Microsoft AGT’s DecisionBOM.completeness_score does, with two improvements: the formula is normative (so the verifier recomputes), and per-field metadata is a flat enum (three values) rather than a six-attribute record.

2. New fields

2.0 prior_receipt (optional)

Singly-linked back-reference to the previous receipt this emitter issued.

"prior_receipt": {
  "receipt_id": "uuid-of-the-prior-receipt",
  "receipt_hash": "sha256-hex-of-the-prior-receipt"
}

Semantics: an emitter that maintains an ordered receipt log includes this field on every receipt after the first, naming the immediately-preceding receipt by its receipt_id and committing to its receipt_hash. A verifier walking the chain detects:

The first receipt in a stream omits this field. A clean restart of an emitter that has lost its chain state should also omit it — honest “I don’t know my predecessor” is preferable to a fabricated link.

Forking (two receipts claiming the same prior) is permitted; resolution of fork policy is verifier-side, not specified here.

Comparison with AGT: AGT’s AuditEntry.previous_hash carries the same semantic — the hash of the prior entry — but does NOT pair it with the prior entry_id. AgentBoundary v0.2-alpha pairs both so a verifier can resolve the link without walking the entire log.

2.1 provenance (optional)

A flat map from dotted path → enumerated value.

"provenance": {
  "actor.id": "observed",
  "agent.framework_version": "observed",
  "tool.version": "synthesized",
  "policy.version": "synthesized",
  "approval.approver.role": "inferred"
}

Value enum:

ValueMeaning
observedEmitter saw this field’s value directly at runtime
inferredEmitter derived the value deterministically from observed data (e.g. framework name from process.argv[0])
synthesizedTranslator, adapter, or default-fill produced this value (the emitter did not see it)

Allowed keys are the 28 dotted paths listed in §3, no more. Unknown keys MUST be rejected by schema validation.

Lenient default: if a path P is present in the receipt body but provenance[P] is absent, the score formula treats it as synthesized. Receipt remains valid; emitter is honest about its limits.

Ignored entries: if provenance contains an entry for a path P that is not present in the receipt body, the entry is silently ignored. Allows translators to over-emit without surprising the verifier.

2.2 completeness_score (optional)

A number in [0.0, 1.0] representing the deterministic score derived from provenance. Three-decimal precision. MUST equal the result of the formula in §4 evaluated against the receipt’s provenance block.

Both-or-neither: if completeness_score is present, provenance MUST also be present. Enforced by schema dependency.

3. Provenance path set

The 28 paths a v0.2-alpha provenance map may key. Always-applicable (counted in every receipt’s score):

receipt_id              issued_at
actor.type              actor.id
agent.framework         agent.framework_version    agent.model
tool.name               tool.capability
target.system           target.environment
arguments_hash
policy.name             policy.version             policy.decision
execution.status        execution.completed_at

Conditional (counted only when the corresponding leaf is present in the receipt):

actor.display_name
agent.model_version
tool.version
target.resource_id
approval.approver.id    approval.approver.display_name    approval.approver.role
approval.approved_at    approval.context
execution.error_code    execution.result_ref

The path set is part of the schema version. Future versions may extend it; v0.2-alpha verifiers seeing v0.3 paths in a v0.2-alpha receipt MUST reject (schema enforces additionalProperties: false on the provenance map).

The receipt’s version, receipt_hash, provenance, and completeness_score are deliberately not in the provenance path set: they are meta-fields about the receipt itself, not claims about the world.

4. Score formula

weights = { observed: 2, inferred: 1, synthesized: 0 }

applicable = the subset of path-set paths where the leaf is present in the receipt
total = | applicable |
weighted_sum = sum( weights[ provenance[p] or "synthesized" ] for p in applicable )

completeness_score = floor( weighted_sum * 1000 / (2 * total) ) / 1000

Two normative properties:

  1. Integer arithmetic. The formula uses integer multiplication and integer floor division so the result is bit-for-bit identical across every language a verifier might use. Floating-point division and language-dependent rounding modes (Python’s banker’s rounding vs JavaScript’s round-half-up) would otherwise diverge.
  2. Floor, not round. Truncation toward zero. A score is the lower bound of completeness, not a best estimate.

Worked example: 17 always-required paths. 12 are observed, 5 are inferred. Weighted sum = 12·2 + 5·1 = 29. Score = floor(29 · 1000 / 34) / 1000 = floor(852.94…) / 1000 = 0.852.

5. Conformance

Two new Level 4 checks:

5.1 LEVEL_4_COMPLETENESS_SCORE_MISMATCH

Fires when the receipt has completeness_score and the declared value does not equal the recomputed value (at 3-decimal precision via integer milli-units).

Semantics: catches emitters that fabricate the score independently of provenance. Detects forgery and bugs in implementing emitters.

5.2 LEVEL_4_COMPLETENESS_BELOW_THRESHOLD

Fires when the verifier supplies a minimum_completeness (e.g. 0.7) and the receipt’s recomputed score is below it.

Semantics: lets a verifier (auditor, compliance dashboard, insurer) refuse evidence below a quality bar. Skipped silently when no minimum is supplied — opt-in, never surprising.

5.3 LEVEL_4_BROKEN_CHAIN

Fires when the receipt’s prior_receipt.receipt_id is either unknown to the verifier or has a recorded receipt_hash that disagrees with the receipt’s claim.

Verifier supplies prior_receipt_hashes: dict[str, str] mapping known receipt IDs to their hashes. When absent, the check skips with info-severity LEVEL_4_SKIPPED_NO_PRIOR_RECEIPT_HASHES.

Semantics: detects deletion, reordering, and forged-hash insertion within an emitter’s stream. A receipt without prior_receipt does not trip this check (first-in-stream is honest).

6. Known limitations

These are deliberately out of scope for v0.2-alpha and documented to set expectations:

7. Schema location

Normative schema: https://agentboundary.jamjet.dev/schemas/action-receipt-v0.2-alpha.json.

v0.1 receipts continue to validate against https://agentboundary.jamjet.dev/schemas/action-receipt-v0.1.json unchanged. The validator in this repo routes by receipt version field.

8. Comparison with Microsoft AGT

Microsoft AGT’s DecisionBOM carries completeness_score as a per-decision float plus per-field BOMField records with name, category, value, source, confidence, inferred. v0.2-alpha simplifies:

AGT BOMField attributev0.2-alpha equivalent
valueLives in the receipt’s regular fields, not in the provenance map
inferred: true/falseinferred provenance value
confidence: 0.0–1.0Folded into the three-tier enum
source: <string>Out of scope for v0.2-alpha (candidate for v0.3)
category: <string>Implicit in the dotted path
nameThe dotted path itself

The structural simplification: AgentBoundary path keys are dotted strings (actor.id, approval.approver.role); AGT’s are nested objects. The flat representation is denser and easier to validate against a closed schema.

The normative simplification: AGT lets implementers set completeness_score to any float. AgentBoundary derives the score by formula — the verifier recomputes and rejects on mismatch.