Skip to content

AEP Schema Contract (aep/v0.3; DSSE variant aep/v0.4; attribution aep/v0.5)

The Agent Evidence Protocol (AEP) is the cross-repo evidence contract for the WasmAgent ecosystem. AEPRecord is emitted by @wasmagent/aep after every agent run and consumed by trace-pipeline (evomerge) for audit and training data export. New emitters build aep/v0.3 records; useDsse: true produces aep/v0.4 DSSE/in-toto envelopes; schemaVersion: "aep/v0.5" emits the canonical attribution-grading vocabulary (authority_origin, identity_source, attribution_backing, run_attribution_backing_floor, run_attribution_backing_observed, authorized_by — canonical WasmAgent/wasmagent-protocol 0.1.9, shared with the OWASP Verifiable Authorization Lineage recommended control).


Schema versions

aep/v0.3 — the base contract. aep/v0.3 builds on the v0.2 schema — which introduced the required Ed25519 signature field (the emitter always signs records via AEPSigner; default LocalEd25519Signer, KMS adapter slot reserved) — and adds:

  • recording_mode and side_effect_class on every ActionEvidence (defaults "validation" / "unknown")
  • run-level run_side_effect_class_max
  • state_digest_kind / state_digest_coverage state-digest metadata
  • argument_drift detection
  • approval_mode / approval_extension / deny_reason_class on CapabilityDecision
  • external timestamp_proof via AEPTimestamper
  • session_id / turn_index run context

aep/v0.4 is the DSSE/in-toto emission variant: when the emitter is constructed with useDsse: true, emit() wraps the record in a DSSE envelope (dsse_envelope), signs the envelope via PAE, and stamps schema_version: "aep/v0.4" while still populating the legacy signature field for backward compatibility.

aep/v0.5 adds the attribution-grading vocabulary as optional fields (see below). useDsse: true combined with schemaVersion: "aep/v0.5" emits a DSSE-signed v0.5 record.

v0.1 and v0.2 records are still parsed for backward compatibility but no longer produced. By default new emitters write "aep/v0.3" (or "aep/v0.4" when DSSE emission is enabled); pass schemaVersion: "aep/v0.5" to emit the attribution fields.

New optional fields may be added without a version bump. Breaking changes require a version bump and a migration script.

v0.5 attribution grading

FieldMeaning
authorized_byPrincipal that granted/approved the authority, when it differs from user_id (requester vs authorizer)
authority_originsubject_consented / administrator_assigned / organization_wide / unknown — how the authority was conferred
identity_sourceself_asserted / organization_attested / notified_eid / qualified_certificate / unknown — how the identity behind the backing key was established
attribution_backingoperator_asserted / principal_key_signed / qualified_signature / unknown — what stands behind the attribution
run_attribution_backing_floorWeakest grade present across the run — MUST NOT round up
run_attribution_backing_observedEvery grade observed across the run (floor and itemization ship together)

Vocabulary shared with the OWASP MCP Top 10 "Verifiable Authorization Lineage" recommended control.


AEPRecord fields

FieldTypeRequiredDescription
schema_version"aep/v0.1" | "aep/v0.2" | "aep/v0.3" | "aep/v0.4" | "aep/v0.5"yesThe literal schema tag. Default "aep/v0.3"; "aep/v0.4" when DSSE emission is enabled; "aep/v0.5" when schemaVersion: "aep/v0.5" is set.
run_idstringyesUnique identifier for this agent run
user_idstringnoUser identity for cross-run behavior audit
subject_idstringnoSubject identity for cross-run behavior audit
created_at_msnumberyesUnix epoch ms when the record was built
trace_idstringnoOpenTelemetry-compatible trace ID for cross-signal correlation
parent_trace_idstring | nullnoParent trace ID for nested/multi-agent runs
repo_commitstringnoGit commit SHA of the running code
runtime_versionstringno@wasmagent/core version string
model_providerstringnoe.g. "anthropic", "openai"
model_idstringnoe.g. "claude-sonnet-4-6"
policy_bundle_digeststringnosha256 hex of the PolicyBundle applied
tool_manifest_digeststringnosha256 hex of the MCP tool manifest used
mcp_server_card_digeststring | nullnosha256 hex of the ServerCard
input_refsInputRef[]noDigested references to run inputs
output_refsOutputRef[]noDigested references to run outputs
capability_decisionsCapabilityDecision[]noPolicy decisions made during the run
actionsActionEvidence[]noEvidence for each tool call
verifier_resultsVerifierResult[]noPer-verifier pass/fail + score
budget_ledgerBudgetLedgernoBudget consumption for tokens, latency, tools, risk, retries, human approvals
prev_record_hashstring | nullnosha256 hex of the canonical previous record (excluding its signature); set automatically by the emitter to build a hash-linked chain
run_contextRunContextnoExecution environment and delegation metadata (agent_id, session_id, turn_index, delegation_chain, environment/dependency digests)
run_side_effect_class_maxSideEffectClassnoHighest side_effect_class observed across the run; computed automatically by the emitter (v0.3)
timestamp_proof{ timestamp, authority, proof, logIndex? }noExternal timestamp proof attached by an AEPTimestamper after signing (v0.3)
signature{ alg: "ed25519", key_id, sig }yes (since v0.2)Ed25519 cryptographic signature over the canonical bytes of the record. Required by AEPRecordSchema since aep/v0.2; verification via verifyAEPRecord(record, publicKey). On aep/v0.4 records it is derived from the DSSE envelope for backward compatibility.
dsse_envelope{ payloadType, payload, signatures[] }noDSSE/in-toto envelope attached when the record is emitted with useDsse: true; present on aep/v0.4 records (v0.4)

ActionEvidence fields

FieldTypeRequiredDescription
action_idstringyesUnique ID for this action
tool_namestringyesName of the tool called
state_changingbooleanyesWhether this tool modifies external state
timestamp_msnumberyesUnix epoch ms when the action was taken
recording_mode"validation" | "delta" | "full"yes (v0.3)Evidence capture depth; emitter defaults to "validation"
side_effect_class"read" | "mutate-local" | "mutate-external" | "network-egress" | "unknown"yes (v0.3)Side-effect classification; emitter defaults to "unknown"
precondition_digeststringnosha256 of relevant state before the call
result_digeststringnosha256 of the tool's return value
evidence_refsstring[]noURIs to additional evidence artifacts
capability_decisionCapabilityDecisionnoThe policy decision for this specific call
argument_driftArgumentDriftnoDetected drift between approved and observed arguments (v0.3)

CapabilityDecision fields

FieldTypeRequiredDescription
capabilitystringyesCapability name (typically tool name)
subjectstringyesWho is requesting (e.g. "agent")
resourcestringyesWhat is being accessed
decision"allow" | "deny" | "ask_user" | "dry_run"yesPolicy outcome
reason_codestringnoMachine-readable reason (e.g. "DENY_BLOCKED")
approval_mode"one-shot-payload" | "bounded-lease" | "policy-allow-with-receipt" | "policy-deny-with-evidence" | "re-approval-on-drift" | "none"yes (v0.3, default "none")How the approval decision was reached (v0.3)
approval_extensionApprovalExtensionnoNamespace-scoped extension evidence for the approval (v0.3)
deny_reason_class"tool-identity" | "argument" | "tainted-input" | "resource-scope" | "missing-delegation" | "policy-rule" | "other"noReason category for a deny decision (v0.3)

BudgetLedger fields

Each budget entry has { limit?: number, spent: number }.

FieldTypeDescription
token_budgetBudgetEntryLLM token consumption
latency_budget{ limit_ms?, actual_ms }Wall-clock latency
tool_budgetBudgetEntryNumber of tool calls
risk_budgetBudgetEntryRisk units consumed (e.g. high-risk actions)
retry_budgetBudgetEntryNumber of retries
human_approval_budgetBudgetEntryHuman-in-the-loop approvals requested

Compatibility policy

Change typeHandling
Add optional field to AEPRecord or ActionEvidenceAllowed without version bump
Add optional field to CapabilityDecision or BudgetLedgerAllowed without version bump
Add new required fieldRequires aep/v0.4 + migration script in evomerge
Remove any fieldRequires aep/v0.4 + deprecation period (min. 2 weeks)
Change enum valuesRequires aep/v0.4
Change field typeRequires aep/v0.4

Example AEPRecord

json
{
  "schema_version": "aep/v0.3",
  "run_id": "run-2026-06-26-001",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "model_provider": "anthropic",
  "model_id": "claude-sonnet-4-6",
  "policy_bundle_digest": "a3f4e2b1c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2",
  "actions": [
    {
      "action_id": "act-001",
      "tool_name": "bash",
      "state_changing": false,
      "recording_mode": "validation",
      "side_effect_class": "read",
      "precondition_digest": "sha256-abc123",
      "result_digest": "sha256-def456",
      "evidence_refs": [],
      "capability_decision": {
        "capability": "bash",
        "subject": "agent",
        "resource": "bash",
        "decision": "allow"
      },
      "timestamp_ms": 1750950000000
    }
  ],
  "verifier_results": [
    {
      "verifier_id": "build-passes",
      "passed": true,
      "score": 1.0,
      "claim_ids": []
    }
  ],
  "budget_ledger": {
    "token_budget": { "limit": 10000, "spent": 3421 },
    "tool_budget": { "limit": 20, "spent": 4 }
  },
  "run_side_effect_class_max": "read",
  "created_at_ms": 1750950001234,
  "signature": {
    "alg": "ed25519",
    "key_id": "local-dev-key-01",
    "sig": "<base64-encoded Ed25519 signature>"
  }
}

When the emitter is configured with useDsse: true, the emitted aep/v0.4 record additionally carries a dsse_envelope and a schema_version of "aep/v0.4".


What consumes AEP records

ConsumerHow
evomerge validate-aepSchema validation + completeness gate (trace-pipeline)
evomerge exportConvert to SFT/DPO/PPO/router training data
evomerge audit-reportGenerate Markdown audit report
wasmagent evidence exportCLI export to JSON/HTML report
agent-evidence-gate GitHub ActionCI validation + evidence artifact upload

Standards Alignment

AEP has been evaluated against the AgentHook v0.2 draft event model for agent runtime evidence. The full analysis is available in RFC: AEP <-> AgentHook v0.2 Field Alignment.

Key differentiators of AEP vs. AgentHook v0.2:

  • Policy-first design -- AEP records policy_bundle_digest, tool_manifest_digest, and structured CapabilityDecision arrays with approval modes. AgentHook models decisions as flat per-event fields without policy anchoring.
  • Budget accounting -- AEP's BudgetLedger tracks six resource dimensions (tokens, latency, tools, risk, retries, human approvals). AgentHook has no equivalent.
  • Verifier results -- AEP includes post-run verification verdicts (verifier_results) linking to specific claims. AgentHook does not model verification.
  • Tamper-evident chaining -- AEP's prev_record_hash creates a hash-linked sequence of records. AgentHook events are independent.
  • Content-addressed by default -- AEP digests inputs/outputs rather than storing raw content, supporting privacy-preserving audit. AgentHook stores full payloads in model_call and tool_output.
  • in-toto/DSSE wrapping -- since AEP v0.4, AEPEmitter with useDsse: true emits records as predicates inside DSSE/in-toto attestation envelopes (dsse_envelope), enabling supply-chain verification.

AgentHook v0.2 offers decision.confidence scoring and observation.trust_level enums that AEP does not yet provide; these are candidates for a future AEP version after v0.4.


Released under the Apache-2.0 License.