Event Schema

Every event the wrapper SDK emits is a CloudEvents 1.0 envelope wrapping an AGT AuditEntry with a Wytness envelope sidecar. The canonical-shape data payload is byte-comparable across Python and TypeScript — same wire format, same dashboard view.

Three layers of trust on every event

Wytness inherits two cryptographic properties from AGT and adds two of its own. Each event carries all four:

LayerPrimitivePropertyKey holder
AGT — identityEd25519 on agent DIDs + IATP delegationWho ran thisCustomer (AGT runtime)
AGT — tamper-evidenceSHA-256 hash chain + optional HMAC-SHA256Chain wasn't alteredCustomer (HMAC secret, optional)
Wytness — non-repudiationPer-event Ed25519 in wrapper envelopeAgent owner attested to this exact actionCustomer (browser-generated)
Wytness — zero-knowledgeHMAC-SHA256 + X25519 + ChaCha20-Poly1305 token mapWytness never sees PIICustomer (browser-generated)

Reads as: who → what (intact) → who-attested → without-seeing-the-secrets. AGT owns identity + chain; Wytness owns non-repudiation + privacy. The layers do not overlap; they compose.

CloudEvents envelope

Each POST batch is a JSON array of CloudEvents 1.0 envelopes. The wrapper batches up to batchSize (default 100) entries or up to flushIntervalMs (default 5000 ms), whichever comes first.

wire format
[
{
"specversion": "1.0",
"id": "<uuid>",
"source": "wytness-agt",
"type": "AuditEntry",
"datacontenttype": "application/json",
"time": "2026-05-22T00:00:00.000Z",
"data": {
"timestamp": "2026-05-22T00:00:00.000Z",
"agent_id": "billing-agent",
"event_type": "tool_invocation",
"action": "send_invoice",
"policy_decision": "allow",
"entry_hash": "<AGT-supplied SHA-256 hex>",
"previous_hash": "<previous entry_hash>",
"entry_id": "<uuid>",
"data": {
"customer": { "email": "EMAIL_3c866e6f" },
"amount": 99.99
},
"outcome": "success",
"resource": "https://billing.example.com/invoices"
},
"wytness_envelope": {
"envelope_version": 2,
"key_id": "<16-char base64url SHA-256(pubkey)>",
"signature_ed25519": "<base64 Ed25519 sig over canonical_json({data, id, time, type})>",
"pseudonymization_version": "1"
}
}
]

Content-Type

The wrapper POSTs to /ingest with one of three Content-Types — the backend branches on it:

Content-TypeUsed byWhat it means
application/vnd.wytness.agt+jsonwytness SDK (Python / TypeScript) with signEnvelope=true (default)Wrapper-mode batch. Backend verifies the Ed25519 envelope against the registered key, branches on wytness_agt_py / wytness_agt_ts source_format, ingests with three-layer crypto.
application/cloudevents-batch+jsonwytness SDK (Python / TypeScript) with signEnvelope=false, OR direct AGTDirect-mode batch. No Wytness envelope — AGT identity + hash chain only.
application/cloudevents+jsonsingle events (direct AGT)Single CloudEvent (not a batch).

Canonical shape — the data payload

The inner data object is the AGT AuditEntry in canonical snake_case shape. Python emits this shape natively; TypeScript transforms its camelCase AGT-TS entry at the sink boundary so the wire bytes are identical.

FieldTypeDescription
timestampstring (ISO 8601 UTC)When the entry was created. Set by AGT.
agent_idstringAgent identifier — matches the AGT DID on the registered identity.
event_typestringAction category, e.g. "tool_invocation", "policy_decision", "agent_message".
actionstringSpecific action within the category, e.g. "send_invoice".
policy_decisionstringAGT policy verdict — "allow", "deny", or "review".
entry_hashstring (hex)SHA-256 of the canonical entry. AGT-supplied — links into the AGT hash chain.
previous_hashstring (hex)SHA-256 of the previous entry in the chain. Empty string on the first entry.
entry_idstring (UUID)Per-entry identifier. AGT-supplied.
dataobjectFree-form payload. The wrapper recursively pseudonymises any path matching piiFields plus any value matching the built-in PII regexes.
outcomestringOptional — "success", "failure", "timeout". Wytness extra; populated via setNextEntryExtras() in TS or kwarg in Python.
resourcestringOptional — URL or identifier of what the action touched. Wytness extra.

New fields in AGT 4.0.0+ (forward-compatible)

AGT 4.0.0 (shipped 2026-06-01) added five fields to AuditEntry that flow through the wrapper's canonical-shape transform. The Wytness wrapper SDKs (wytness-ai 1.12.0 — Python + TypeScript) pin the AGT 5.0 train (Python 4.1.0 / TypeScript 5.0.0) and emit these fields automatically on every event.

FieldTypeDescription
arguments_hashstring (hex)SHA-256 of the tool's arguments payload. Lets you fingerprint a call without storing the arguments themselves — useful for HITL replay and dedup.
approver_didstringDID of the human approver for HITL-gated tool calls. Empty when no human approval was required. Pairs with Shield's approval routing.
policy_versionstringVersion of the AGT policy that evaluated this event. Lets you tell which policy edition was in force when an action was allowed/denied/reviewed.
issued_atstring (ISO 8601 UTC)When the tool call was issued by the agent. Together with completed_at, gives you a real per-call latency measurement separate from the AGT chain-write timestamp.
completed_atstring (ISO 8601 UTC)When the tool call returned (success, failure, or timeout). Always >= issued_at.
Note
Live since wytness-ai 1.0.2 (2026-06-05). The AGT 4.0.0 pin landed in sdk-python-agt + sdk-typescript-agt the same day. Upgrade to the latest wrapper and these fields appear automatically on the canonical-shape data payload — no wire-format break.

Skill provenance (AGT 5.0 train)

The AGT 5.0 train adds skill-audit metadata — provenance for the skill/tool implementation an agent invoked. The wrapper carries it as an optional skill_audit_metadata object on the canonical payload (omitted when absent — events without it are byte-identical to before). On TypeScript the source field is part of AGT's hash-covered audit entry, so it is chain-protected end-to-end.

Sub-fieldTypeDescription
skill_namestringName of the skill/tool implementation that ran.
skill_originstringWhere the skill came from (registry, package, inline).
provenance_source_truststring"trusted" when the skill metadata came from a trusted source registered with the AGT kernel.
context_hash_beforestring (hex)SHA-256 of the agent context immediately before the skill ran.
context_hash_afterstring (hex)SHA-256 of the agent context immediately after — pairs with the before-hash to evidence what the invocation changed.

Wytness envelope sidecar

When signEnvelope is true (the default), each event carries an additional wytness_envelope object outside the CloudEvents-spec fields:

FieldTypeDescription
envelope_versionintegerSchema version — currently 2. Signature covers canonical_json({data, id, time, type}).
key_idstring16-character base64url-encoded SHA-256 prefix of your Ed25519 public key. Lets the backend look up the right verification key without scanning.
signature_ed25519string (base64)Ed25519 signature over canonical_json({data, id, time, type}) — RFC 8785 canonicalisation. Verifies the data block, the event id, time, and type have not been tampered with since you signed it.
pseudonymization_versionstringCurrently "1". Encoded so the dashboard can pick the right reveal path if the algorithm evolves.

Encrypted token map (when pseudonymisation matched)

For every event where the SDK pseudonymised at least one value, a per-event encrypted_token_map is attached inside the data payload. It maps pseudonyms back to originals, encrypted with ChaCha20-Poly1305 using a fresh ephemeral X25519 keypair per event. Only the holder of your X25519 private key can decrypt it — see PII Protection — Revealing PII.

AGT-supplied hash chain

AGT writes each AuditEntry as a hash-chained record: entry_hash = SHA-256(canonical(entry)), and the next entry's previous_hash points at it. Any tamper to a historical entry breaks the chain forward. The wrapper does not produce this chain — it inherits it intact from AGT and surfaces it on the dashboard Integrity Verifier and the Evidence Pack PDFs.

Note
The dashboard refers to this as AGT hash chain — sometimes written as "AGT-supplied hash chain" or "AGT chain" in the UI. They mean the same thing.

Schema versioning

FieldWhereCurrent value
specversionCloudEvents envelope1.0
envelope_versionwytness_envelope2
pseudonymization_versionwytness_envelope"1"
source_format (dashboard chip)ingested per event"wytness_agt_py" (Python) or "wytness_agt_ts" (TypeScript)
Tip
Breaking changes to any of these surface as version bumps + a CHANGES entry in the SDK changelog. The wire format is stable.

We set no cookies. Sign-in and preferences use essential first-party browser storage only — no tracking, advertising, or third-party analytics. Privacy Policy

Event Schema
TABLE OF CONTENTS