If you ship AI-assisted code in a regulated codebase and somebody asks "show me what the agent did", you have about a week before that question turns into a finding. The data exists somewhere. It is not in a single shape. It is rarely portable. It is almost never tamper evident.
AGEF is the spec I wrote to fix that. It stands for Agent Governance Evidence Format. The current text is v0.1.1 (pre-stable), with wire format agef_version: "0.1". The repo is at github.com/radotsvetkov/agef. Spec text is CC BY 4.0. Code is Apache-2.0. Akmon is the reference implementation; akmon-journal is a Substrate Profile, and Akmon Phase 4 brings full Bundle Profile support.
This article walks the spec end to end, with code, and with the design choices I made.
What AGEF actually is
AGEF defines how one AI agent session can be represented as a portable, tamper-evident bundle. A session is a logical run from SessionStart to SessionEnd. The bundle captures every event in order, with cryptographic linkage and content-addressed payloads.
The bundle is a tar.zst archive with three top-level paths:
-
manifest.json, a small UTF-8 JSON file with sorted keys and LF newlines. -
events.bin, an ordered stream of length-delimited canonical CBOR event records. -
objects/<hex>, a directory of content-addressed object files (one per hash).
That is the whole shape. Verifiers ignore unknown non-normative files unless explicitly configured to reject them.
The manifest
{
"agef_version": "0.1",
"producer": {"name": "akmon", "version": "2.0.0"},
"session": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"head": "5c1f8b2a3d4e7f6a8b1d3e2c4f6a8b9d2c3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c",
"created_at": "2026-05-06T09:14:02Z",
"ended_at": "2026-05-06T09:14:18Z"
},
"hash_algorithm": "sha256",
"object_count": 12,
"event_count": 9
}
A reader who has never seen the producer can answer four things from this object: which version of the format, who wrote it, when, and how big it is. Writers must keep counts honest. Readers must reject malformed or incomplete required fields.
Default hash algorithm is sha256. Readers must support sha256 and may support blake3. Bundles that declare unsupported algorithms must be rejected. Hex appears only in the manifest (session.head) and in object filenames. Hashes inside CBOR-encoded events are 32-byte byte strings.
The events stream
events.bin is the substance. It is a sequence of records, each framed by a 4-byte unsigned big-endian length prefix followed by exactly that many bytes of canonical CBOR encoding one event.
Length-delimited framing was a deliberate trade. It supports partial recovery from truncation and lets a verifier scan deterministically. Producers commit to canonical CBOR per RFC 8949.
Each event encodes:
-
parents, an array of zero or more parent event hashes. -
kind, one of the closed event kinds in v0.1. -
emitted_at, a CBOR tag 1 timestamp (integer epoch seconds, or floating point for sub-second precision). -
sequence, monotonic per session, starting at 0.
Linkage rules are strict in v0.1:
-
sequencestarts at 0 and increases by exactly 1 per event. - Every event except
SessionStarthas at least one parent. -
SessionStarthas exactly zero parents. - Every non-
SessionStartevent in v0.1 has exactly one parent, and that parent is the hash of the immediately preceding event by sequence. Multi-parent events are reserved for future versions. - Event hashes are computed over canonical CBOR bytes of the full event envelope.
- Event ordering in
events.binmatchessequence.
Event kinds in v0.1 (closed set)
Readers must recognize exactly these kinds in v0.1. Unknown kinds are rejected.
-
SessionStart: opens the session, fieldscwd_hashandconfig_hash. -
UserTurn: a user prompt, fieldprompt_hash. -
ProviderCall: a model provider call, fieldprovider_id, anattempts[]array ofAttemptRecord, optionalstream_hash. -
ToolCall: a tool execution, fieldstool_id,input_hash,output_hash, optionalside_effects_hash. -
RetrievalCall: a retrieval, fieldsindex_id,query_hash,results_hash. -
PermissionGate: a policy decision, fieldspolicy_id,decision(string, recommended lowercase verbs likeallowed,denied,deferred),context_hash. -
AssistantTurn: an assistant message, fieldsmessage_hash, optionaltool_calls_hash. -
SessionEnd: closes the session, optionalsummary_hash.
ProviderCall.attempts[] preserves chronological order. Each AttemptRecord has attempt_number (1-indexed), started_at, ended_at, a closed AttemptStatus, request_hash, optional response_hash, optional stream_hash, optional error_message. AttemptStatus is one of Success, RateLimited, NetworkError, ServerError, ClientError, Cancelled, or Other(string). v0.1 readers reject unknown variants.
Two design notes worth calling out.
First, PermissionGate.decision is open in v0.1. The spec recommends lowercase verbs but does not close the set. Closing it is a likely v1.0 change. If you are a producer, follow the recommendation now to make the v1 transition free.
Second, AttemptStatus and EventKind are intentionally closed. The cost is that adding a new variant is a normative spec change. The benefit is that two implementations cannot legitimately disagree on the meaning of a record.
The objects directory
Every object referenced by an event hash field exists as a file at objects/<hex> where <hex> is the lowercase hex digest for the active hash algorithm. Object bytes hash to their filename digest. Objects are opaque bytes; AGEF v0.1 does not require MIME metadata.
A typical bundle has many small objects (prompts, tool inputs, tool outputs, file diffs) and a few large ones (full file contents). Storage is efficient because identical content hashes once.
Hashing rules
default: sha256
optional: blake3
Readers must support sha256. They may support blake3. Within CBOR-encoded events, hashes must be encoded as CBOR byte strings (major type 2) of length 32 for both algorithms. Hex string representation is used only in manifest.json (session.head) and in object filenames. Once you internalize that, the rest of the spec falls into place.
Serialization rules in one paragraph
Event payloads in events.bin use canonical CBOR (RFC 8949). manifest.json is UTF-8 JSON with sorted keys and LF endings. Timestamps in CBOR-encoded events use CBOR tag 1. Producers may emit either integer epoch seconds or floating point; readers must accept both. The reference implementation akmon-journal v0.1 emits integer epoch seconds. Timestamps in manifest.json use RFC3339 strings. Implementations may use any internal storage format; AGEF rules apply only to the bytes emitted in events.bin and to the bytes used for event hashing.
Verification procedure
A conforming verifier runs this sequence:
- Extract the archive.
- Parse
manifest.json. Reject on schema or version failure. - Read
events.binusing the 4-byte length-delimited framing. - For each event: decode canonical CBOR, recompute event hash, verify
sequencemonotonicity, verify allparentsresolve to previously seen events, verify referenced content hashes resolve to files inobjects/. - For each referenced object: read bytes, hash with
manifest.hash_algorithm, compare to filename digest. - Confirm
manifest.event_countequals decoded event count,manifest.object_countequals object file count,manifest.session.headequals terminal event hash, andSessionStartis a reachable ancestor of head.
Default operation fails on the first invariant violation. Implementations may offer a "report-all" mode for diagnostics. They must not claim successful verification unless all required checks pass.
Conformance profiles
AGEF v0.1 defines two profiles:
- Bundle Profile, an implementation that produces or consumes AGEF bundles.
- Substrate Profile, an implementation that maintains an AGEF-compatible content-addressed event journal but does not necessarily emit bundles directly.
A Substrate Profile must be able to produce Bundle Profile output through an export pathway when required.
akmon-journal is currently a Substrate Profile. Akmon Phase 4 introduces Bundle Profile capability.
If you are an implementer, knowing which profile you are claiming is the most important conformance question.
Producing AGEF in practice
If you use Akmon, you already produce AGEF. Sessions land in .akmon/audit/<session-id>.jsonl and .akmon/evidence/<session-id>.json. With Phase 4 export, the same session is portable as a .akmon bundle.
If you build your own producer, the spec lists the libraries known to produce canonical CBOR with the right configuration: ciborium for Rust, fxamacker/cbor for Go, cbor2 for Python, cbor-x for JavaScript and TypeScript. Validate canonical encoding behavior with test vectors before claiming conformance.
Reading and verifying AGEF
For Akmon-produced bundles, the verification commands are part of the trust pipeline:
# Verify audit chain integrity for the live session journal
akmon audit verify .akmon/audit/<session-id>.jsonl
# Verify the evidence summary plus its linkage to the audit chain
akmon evidence verify .akmon/evidence/<session-id>.json
# Once Phase 4 export is on hand, verify a bundle on import
akmon bundle import evidence.akmon --verify-only
Independent verifier implementations are welcome. The spec is small enough to implement in a weekend if you start with a CBOR library that supports canonical encoding.
Security considerations
AGEF provides tamper evidence and portability. It does not provide identity attribution by itself. If producer trust matters in your environment, layer external signing on top of the bundle. Bundles may contain sensitive content; storage and sharing controls are the operator's job. Verification proves integrity, not semantic correctness.
For sharing, the redaction flow is the right answer. With Akmon:
akmon redact <session-id> \
--output sanitized.akmon \
--object <object-hash> \
--reason "Removed customer name before audit handoff"
This produces a derivative bundle in which the targeted objects are replaced by canonical CBOR sentinels. The sentinel payload records the original hash, original size, the supplied reason, and a redacted_at timestamp. The chain still verifies because the sentinel hashes correctly, and the audit trail makes the redaction explicit.
Compatibility and evolution
v0.x is pre-stable. Breaking changes are permitted. Future versions should preserve forward migration guidance. v1.0 is the first stable major. New event kinds in future majors must be version-gated. v0.1 readers must not silently ignore unknown required semantics.
If you build against v0.1, plan for one migration to v1.0. If you are a careful producer, the migration is small.
Why a new format
Three reasons.
First, no shared shape exists today. Every framework, every vendor, every gateway writes its own. A reviewer cannot move between them. The cost of a new format is small compared to the cost of having no shared format.
Second, evidence has a different audience than observability. Observability is for engineers in the moment. Evidence is for reviewers, regulators, customers, and the version of you reading the file in a year. Different shape, different guarantees, different expectations.
Third, regulated engineering needs an answer that does not depend on a vendor dashboard. The portability requirement is real. AGEF is built for it.
What you can do this week
If you build AI tooling, three small steps:
- Read
SPEC.mdend to end. It is short on purpose. - Implement a Bundle Profile verifier in your language of choice. Use the test vectors that ship in the
examples/minimal-bundlefolder. - Open an issue on the AGEF repo. Tell me what your runtime emits today and where the spec helps or gets in the way.
If you ship a coding agent, the smallest first step is one binary and the trust pipeline. The repo is at github.com/radotsvetkov/akmon.
The format spec is at github.com/radotsvetkov/agef.
The site is at radotsvetkov.github.io/akmon.
Standards become standards by being used. Implementations are welcome.
United States
NORTH AMERICA
Related News

‘The Testaments’ Just Brought Back Another Surprising ‘Handmaid’s Tale’ Character
2h ago
Islamic Medicine (2018)
April 19, 2026
LLM and Generative AI Interview Questions with Answers 2026
April 20, 2026
How nylas mcp uninstall Works: Remove MCP integration from an AI assistant
April 19, 2026
🌍 Earth's Last Letter
April 20, 2026