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.