AEP-0001: Purpose, Architecture, and Event Envelope
This document defines the purpose, scope, layered architecture, and event envelope of the Agent Events Protocol (AEP: working title; all identifiers using the AEP / dev.aep. / @agenteventprotocol/* roots are placeholders frozen at the naming decision).
Draft: the AEP suite is pre-v0.1; each document's status lives in its header table. This page is rendered from the canonical spec/AEP-0001-core-and-envelope.md, which is the normative text.
| Field | Value |
|---|---|
| AEP | 0001 |
| Title | Purpose, Architecture, and Event Envelope |
| Type | Standards Track — Core |
| Status | Draft |
| Sponsor | AEP maintainers |
| Created | 2026-07-03 |
| Requires | n/a |
| Supersedes / Superseded-by | n/a |
Provenance (non-normative): this document consolidates the wire format, connection & lifecycle model, and envelope & taxonomy into one normative contract. It states only the resulting contract, not the design arguments behind it.
Abstract
This document defines the purpose, scope, layered architecture, and event envelope
of the Agent Events Protocol (AEP: working title; all identifiers using the
AEP / dev.aep. / @agenteventprotocol/* roots are placeholders frozen at the naming decision).
AEP is an open, vendor-neutral protocol for agent activity events and control: any
agent emits lifecycle, progress, tool, resource, error, and attention events once
(over stdio, HTTP, SSE, or WebSocket), and any monitor, history store, notifier,
automation, or other agent consumes them once, for every agent.
This document establishes the event unit, its context attributes, the correlation and replay model, severity and capture semantics, per-layer conformance, and the AEP evolution process. The event-type dictionary is defined in AEP-0002; transport bindings in AEP-0003; the control profile in AEP-0004; the CloudEvents, OTLP, and OCSF bridge annexes in AEP-0005.
1. Motivation
Agents increasingly run concurrently and autonomously, yet there is no common way to observe their activity, retain portable history, notify humans at the moments that need them, or drive automation across vendors. Each runtime ships bespoke hooks with convergent vocabularies but divergent spellings, and each integration re-implements the same "an agent did X" signal. AEP standardizes that signal, and the return path for acting on it. Non-goals are normative (§3.2).
2. Terminology
The key words MUST, MUST NOT, REQUIRED, SHALL, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL are to be interpreted as described in RFC 2119 and RFC 8174.
- Event: one AEP envelope instance (§5): a single self-describing JSON object describing one unit of agent activity, complete and meaningful in isolation.
- Emitter: a party that produces Events: an agent runtime, or an adapter translating a runtime's native hooks into Events.
- Consumer: a party that receives Events: dashboard, channel sink, history store, bridge, actioner, or another agent.
- Endpoint: any party terminating an AEP binding (AEP-0003); a party MAY be emitter and consumer simultaneously.
- Relay (broker): an OPTIONAL intermediary that ingests, routes, fans out, and MAY keep a bounded replay buffer. AEP works without one.
- Session: the unit of agent conversation/work an emitter groups Events under.
- Run: one activation within a session (a turn, task, or job).
- Step: an optional sub-run grouping (an agentic-loop phase).
- Control Event: an Event delivered to an emitter to influence behavior (AEP-0004).
- Attention request: an Event signaling that an agent needs a human (or a policy delegate) to act.
3. Scope
3.1 In scope
The activity-event vocabulary and envelope; correlation, ordering, and replay metadata; transport bindings and connection lifecycle; the consumer subscription and filter model; the control profile; capture (content-privacy) semantics; conformance; bridges to CloudEvents and OpenTelemetry; the AEP governance process.
3.2 Non-goals (normative)
AEP owns exactly one axis: agent → humans & automations, fleet scope, durable, bidirectional. AEP MUST NOT be construed as, and this specification's evolution MUST NOT grow into, any of the following:
- agent-to-agent delegation and task exchange (A2A's plane);
- frontend/UI rendering and generative UI (AG-UI's and A2UI's planes);
- tool and context provisioning (MCP's plane);
- editor-agent driving (ACP's plane);
- distributed tracing and APM (OpenTelemetry's plane; AEP bridges to it, AEP-0005);
- token-stream transport in the core (sub-profiles only);
- a required broker, or any normative channel/dashboard product (consumers are never specification surface);
- per-vendor payload quirks in the core namespace (
x.*extensions exist for this).
The fleet-observer test is the scope court for every future addition: a core event type or attribute MUST carry meaning for an observer watching many sessions they did not initiate. Anything meaningful only inside one rendering surface belongs to a neighbor protocol or an optional AEP sub-profile.
4. Architecture
4.1 Layers
AEP is specified in layers; conformance is claimed per layer (§10).
| Layer | Name | Contents | Where |
|---|---|---|---|
| L0 | Envelope | the Event unit and its context attributes | this document |
| L1 | Taxonomy | categories, registered types, payload schemas | AEP-0002 |
| L2 | Transports | JSONL, HTTP, SSE, WebSocket bindings; connection lifecycle; subscriptions | AEP-0003 |
| L3 | Control | bidirectional command profile (experimental in 0.1) |
AEP-0004 |
| L4 | Extensions | vendor types, extension attributes, experimental capabilities | §11, AEP-0002 §6 |
Bridges (AEP-0005) are normative annexes of the specification, versioned and released with it.
4.2 Topologies and the connection-optional principle
Direct (emitter → consumer) and relayed (emitter → relay → consumers) topologies are
both first-class. An Event's meaning and validity MUST NOT depend on topology,
transport, or the existence of any connection: the same JSON object is a valid Event
on stdout, in an append-only file, in an HTTP POST body, in an SSE data: field, and
in a WebSocket text frame. A relay MUST NOT alter core context attributes of
Events it forwards; it MAY add extension attributes (§5.4).
5. The Event envelope
An Event is a single JSON object (RFC 8259; UTF-8) consisting of sixteen context
attributes plus an optional data payload. Attributes 1 to 16 are the routing
surface: relays operate on them and MUST NOT require parsing data. Filters
address the filterable subset AEP-0003 §6.2 names. data is never filterable, and
four context attributes (aep, time, seq, traceparent) are carried, not
filtered.
5.1 Context attributes
| # | Attribute | Type | Requirement | Semantics |
|---|---|---|---|---|
| 1 | aep |
string | REQUIRED | Protocol version of this Event's envelope, e.g. "0.1". Doubles as the format marker for sniffing JSONL lines |
| 2 | id |
string | REQUIRED | Unique per emitter (per source); the idempotency key: consumers MUST dedupe on (source, id) (§7). ULID RECOMMENDED (time-sortable) |
| 3 | type |
string | REQUIRED | Bare AEP type, {category}.{rest} (§6); vendor extensions x.{vendor}.{category}.{rest} |
| 4 | subject |
string | OPTIONAL | The acted-upon entity: tool name, file, task id, attention-request id |
| 5 | time |
string | REQUIRED | RFC 3339 timestamp with timezone. Display/join metadata only; ordering authority is seq (§7), never time |
| 6 | source |
URI string | REQUIRED | Identifies the emitting agent/session. RECOMMENDED form aep://{host}/agent/{agent}/session/{session}. Kept verbatim by the CE bridge |
| 7 | agent |
string | REQUIRED | Stable logical identity of the emitting agent (e.g. claude-code) |
| 8 | session |
string | Conditional (§5.2) | Session grouping key, unique within the emitting agent, never globally (§5.2) |
| 9 | run |
string | OPTIONAL | Run/turn grouping within the session |
| 10 | step |
string | OPTIONAL | Sub-run grouping (agentic-loop phase) |
| 11 | seq |
integer >= 0 | Conditional (§5.2) | Per-session monotonic counter assigned emitter-side; ordering, replay, and resume basis (§7) |
| 12 | epoch |
integer >= 0 | OPTIONAL (default 0) |
Restart generation of the emitter-side counter (§7) |
| 13 | cause |
string | OPTIONAL | id of the immediately causing Event; the causal DAG edge |
| 14 | traceparent |
string | OPTIONAL | W3C Trace Context header value, name kept verbatim (OTel interop) |
| 15 | severity |
enum | OPTIONAL (default info) |
debug < info < notice < warning < error < critical (§8.1) |
| 16 | capture |
enum | OPTIONAL (default metadata) |
Content-capture level: none, metadata, redacted, full (§8.2) |
| 17 | data |
object | OPTIONAL | Type-specific payload (schemas: AEP-0002); see the gen_ai.* mirror rule below |
Absent OPTIONAL attributes MUST be omitted, not set to null. Consumers MUST
apply the stated defaults for epoch, severity, and capture when absent.
Where a data payload field has a stable OpenTelemetry gen_ai.* equivalent, its
name mirrors that equivalent verbatim, pinned per AEP version.
5.2 Session-scoped and agent-scoped Events
Events are session-scoped unless their category is agent (AEP-0002 §3).
Session-scoped Events MUST carry session and seq. Agent-scoped Events
(agent.*: presence, health, heartbeat) describe the emitter itself, not a session;
they MUST omit session, run, step, and seq, and are ordered by time
only.
One deliberate exception exists: foreign-emitter session Events. An
Event addressed to or about a session whose sequence counter its emitter does not
own (inbound control.* commands, AEP-0004 §2.2; consumer-emitted
attention.routed, AEP-0002 §7.3) carries session but MUST omit seq. Such
Events are ordered within the session view by time and by their cause links;
only the session owner's stream carries (epoch, seq) positions.
Session identity is scoped exactly like Event identity (§5.1 #2): a session
value is unique within its emitting agent, never globally. Every session has
exactly ONE owning emitter, the party that assigns its (epoch, seq) positions
(§7.1). Distinct emitters carrying the same session string are distinct
sessions that happen to share a name, not one session. Consumers that aggregate
streams from more than one emitter therefore key per-session state by
(source, session), and the stream validators do the same.
Two surfaces still address a session by bare session in 0.1: control-command
routing (AEP-0004 §2.2, with the relay obligation of §4.5) and resume tokens
(§7.6). Both presume a unique live claimant at the point of use. The residual
ambiguity of a colliding name at those points is stated where it applies rather
than papered over.
5.3 Worked example (non-normative)
{
"aep": "0.1",
"id": "01JX9YB3P4T9",
"type": "tool.completed",
"subject": "Bash",
"time": "2026-07-03T10:15:04.221Z",
"source": "aep://host-a/agent/claude-code/session/s_8f2c",
"agent": "claude-code",
"session": "s_8f2c",
"run": "r_0042",
"step": "turn-3",
"seq": 187,
"epoch": 0,
"cause": "01JX9YB2Z1QK",
"severity": "info",
"capture": "metadata",
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"data": {
"tool": { "name": "Bash", "call_id": "t_91" },
"status": "success",
"duration_ms": 1240,
"gen_ai.usage.input_tokens": 142,
"gen_ai.usage.output_tokens": 87
}
}5.4 Extension attributes
Producers MAY add envelope attributes beyond §5.1. Extension attribute names MUST
match [a-z0-9]{1,20} (lowercase alphanumeric; deliberately the CloudEvents
extension-attribute constraint, so the AEP-0005 bridge passes them through verbatim),
MUST NOT collide with core attribute names, SHOULD begin with the vendor's
name, and MUST carry JSON string, integer, or boolean values only. Consumers
MUST ignore unknown envelope attributes without failure; relays MUST preserve
them. Core attributes are never reinterpreted by extensions.
An emitting library MUST refuse an extension attribute that would violate this section: a name colliding with a core attribute (§5.1), an ill-formed name, or a non-scalar value. It surfaces the error to its caller rather than emitting the non-conformant envelope.
The collision case is why this rule binds the producing boundary. On the wire, a core attribute overwritten by an "extension" is indistinguishable from the attribute itself, so silent last-write-wins merging cannot be detected downstream, only refused at the source.
6. Type naming and categories
An AEP type is a lowercase, dot-separated string {category}.{rest} where
category is one of the thirteen registered categories (AEP-0002 §3) and rest is
one or more [a-z0-9_]+ tokens (e.g. tool.completed, run.step.started). In
vendor extension types the {vendor} token additionally allows -
(e.g. x.claude-code.session.config_change). Verbs are past-tense for facts; imperative
forms appear only in control.* (AEP-0004).
Types are bare on the wire: no reverse-DNS prefix inside an AEP stream. The
frozen reverse-DNS root (dev.aep. placeholder) is applied only at the CE and OTLP
bridges (AEP-0005) and at naming time.
Vendor extension types MUST use x.{vendor}.{category}.{rest} and MUST NOT
occupy the core namespace. Consumers MUST tolerate unknown types without failure
(unknown-type tolerance is a conformance fixture class).
7. Ordering, replay, and the (epoch, seq) contract
seqis a per-session monotonic counter assigned by the emitter side (the agent or its adapter, the party that owns session order), monotonically increasing within oneepoch.Gaps are legal; regressions are not. Consumers MUST tolerate gaps (dropped
debugevents, crashed adapter).Emitter-side: within one
epochan emitter MUST NOT assign aseqat or below one it already assigned, and MUST NOT assign one(epoch, seq)position to two different Events. That position-uniqueness invariant is what replay and resume rest on. Emitters MUST incrementepochon restart of a non-durable counter and MUST NOT reuse an earlierepochwithin a session, which takes durable epoch memory or a monotonic seed such as a startup timestamp. An emitter that can guarantee neither MUST start a new session instead: without epoch monotonicity, resume tokens (rule 6) are ambiguous.Consumer-side: a below-high-water position is one of exactly two things. It is redelivery of an already-assigned Event (legal: dedupe on
(source, id), rule 4), or it is backfill, a not-yet-seen position delivered late (a second relay, a buffered replay). Consumers MUST order backfill by(epoch, seq)like any Event and MUST NOT infer a new epoch from it; a new epoch is only ever declared by the emitter via theepochattribute. Two different Events claiming one position is an emitter fault consumers SHOULD surface rather than silently reorder.The pair
(epoch, seq)totally orders Events within a session, lexicographically.timeMUST NOT be used as ordering authority.Delivery on all bindings is at-least-once; consumers MUST dedupe on
(source, id):idis unique per emitter (§5.1 #2), never globally, so two emitters may legally mint the sameidand a bare-iddedupe key silently drops one of them. Bare-idreferences (cause; the attention lifecycle'ssubject, AEP-0002 §7.1) resolve within one session's view, where every sequenced Event shares one emitter; their residual ambiguity against a colliding foreign-emitter Event'sidis accepted in 0.1.Replay obligations split: a live endpoint MAY keep a bounded replay buffer and MUST advertise its depth when it does (AEP-0003 §5); complete-history replay is a history consumer's product surface, not a relay duty. The specification guarantees reconstructability (emitter orders, the envelope makes every Event self-contained, a history consumer stores), not any single component's retention.
Resume tokens are
(session, epoch, seq)triples; binding-specific carriage is defined in AEP-0003 (SSELast-Event-ID, WSsubscribe.from).
8. Severity and capture
8.1 Severity
Six levels, totally ordered, aligned to MCP/syslog practice:
debug < info < notice < warning < error < critical. Filters MAY compare severities
by this order (AEP-0003 §6). Endpoints under backpressure MAY drop debug/info
Events toward a slow consumer but MUST NOT silently drop notice and above
(AEP-0003 §8.4).
8.2 Capture
capture declares how much operation content the Event carries, and is enforced at
the source:
| Level | Meaning |
|---|---|
none |
envelope only; no payload content |
metadata |
structural metadata (names, ids, counts, durations, statuses); no free text |
redacted |
free text present with secrets/PII redacted per AEP-0003 §9 |
full |
verbatim content |
Rules:
(a) An Event's data MUST honor its declared capture level; payload schemas mark
each field's minimum level (AEP-0002 §5).
(b) Any party re-emitting or fanning out an Event MAY down-level content (strip
fields to a lower level, rewriting capture accordingly) and MUST NOT up-level.
(c) Subscription capture ceilings (AEP-0003 §6) are enforced by fan-out.
(d) The default emitter posture is metadata; content is opt-in.
(e) redacted is a provenance claim: it asserts the Event's free text passed
the redaction pipeline of AEP-0003 §9.4, and down-leveling can never mint that
claim mechanically.
A hop enforcing a redacted ceiling on a full Event MUST rewrite to
metadata (or lower) instead, unless the hop itself applies the §9.4 pipeline
to every redacted-gated field it keeps. Such a hop is a redacting
re-emitter, carrying the same incident-grade responsibility as an emitting
adapter. A redacted-source Event passes a redacted ceiling unchanged,
because its claim was minted at the source.
9. Emit paths
Programmatic (runtime/hook-driven) and LLM-fired (model-invoked, e.g. via an MCP
emit_event tool) emit paths MUST produce identical envelopes; consumers MUST
NOT rely on distinguishing them. Emitters SHOULD NOT use the LLM-fired path for
Events derivable programmatically.
10. Conformance
Conformance is claimed per layer and per role; layers above one's declared tier are never required.
An emitter is AEP-0.1 conformant if:
- every Event it produces validates against the envelope schema;
- every
typeis a registered core type or a legalx.{vendor}.*extension;seqis monotonic per session within anepoch;- content honors the Event's declared
capturelevel;- it emits at most one terminal Event per run and at most one
session.endedper session, and closes pending attention requests beforesession.ended(AEP-0002 §2 convention 5, §7.2).A consumer is conformant if it deduplicates on
(source, id), tolerates unknown types and attributes without failure, and, on bindings it supports, implementsattr-matchsubscription and(session, epoch, seq)resume as specified in AEP-0003.A control-capable party is additionally conformant only if it declares
control.acceptsathello, nacks unknown or unauthorized commands, and acknowledges within the negotiated window (AEP-0004).
The conformance suite (golden fixtures + aep validate + protocol harness) is
normative for the badge; every accepted specification change MUST land with
conformance fixtures. Bridge conformance (CE round-trip identity) is defined in
AEP-0005 §5.
11. Versioning and evolution
- Envelope version: every Event carries
aep(§5.1 #1) so connectionless bindings need no negotiation. Connection-level version negotiation is defined in AEP-0003 §4 (hello; one version per connection). - Evolution bias (additive only within a major): new event types, new OPTIONAL envelope attributes, new capabilities. Core attributes and registered types are never repurposed or removed within a major version. A breaking change requires a major version and a superseding Standards-Track AEP.
- Extension surfaces: vendor types (§6), extension attributes (§5.4), and
capabilities.experimental(AEP-0003 §4) are the three sanctioned extension points. The promotion path is extension → experimental core → core, via the AEP process (§13).
12. Security considerations
Content privacy: default
capture: metadata; content is opt-in, enforced at source (§8.2), down-levelable at every hop, and enforced again at the OTLP exporter (AEP-0005 §3.3).Identity: producer naming (
agent,source) is REQUIRED; binding authentication is REQUIRED for off-host transports and unconditionally for control (RECOMMENDED on localhost; AEP-0003 §8); optional signed identity documents (JWS, A2A AgentCard shape) are specified asexperimental(AEP-0003 §8.3). Identity is not authorization: who may command whom is deployment policy, not protocol surface, in 0.1.Control is privileged: authenticated duplex bindings only, capability-gated, acknowledged, idempotent, audit-visible by construction (AEP-0004).
Transport security: TLS REQUIRED for anything off-host (AEP-0003 §8).
Event signing for audit-grade history is deferred (revisit before any multi-tenant relay).
Identity is asserted, not proven, in 0.1:
agentandsourceare producer-supplied names. Binding authentication (AEP-0003 §8.1) establishes that a producer may emit at all, not that its claimed identity is true: an authenticated but misbehaving emitter can emit under another agent's name. Verifying claimed identity is a consumer policy (AEP-0003 §8.2); the signed identity document (AEP-0003 §8.3) is theexperimentalstrengthening path.Duplicates and replay: delivery is at-least-once and consumers dedupe on
(source, id)(§7), which bounds redelivery of the same Event. Re-emission of old content under freshids is indistinguishable from new activity at the protocol layer; the boundary against it is emit-side authentication (AEP-0003 §8.1), and audit-grade provenance awaits event signing (above).Metadata still discloses: even at
capture: metadata(and in the envelope atnone), Events reveal structure: tool names,subjectvalues such as file or task identifiers, session cadence, and timing. Operators for whom that surface is sensitive havecapture: noneand the subscription ceiling (AEP-0003 §6.4); emitters keepsubjectto identifiers rather than content by construction (§5.1).Extension attributes are untrusted input: they are producer-controlled scalars that relays preserve (§5.4) and bridges forward (AEP-0005). Consumers that render them, template them into queries, or key automation on them are consuming unvalidated producer data and treat it with the same care as payload content.
Correlation identifiers are untrusted input too:
session,run,step, andsubjectare producer-supplied strings with no charset or length guarantee. Adapters pass vendor ids through verbatim, and at least one adopted source's session ids are contractually arbitrary. The schema constrains them only to non-empty strings by design, since rejection at the envelope would break conformant sources; consumers that use them as filesystem paths, URL segments, or query fragments encode or sanitize first (AEP-0003 §9.6).They are also not proof of identity: any authenticated emitter can claim any
sessionstring. That is why session identity is emitter-scoped (§5.2), why cross-emitter aggregation keys on(source, session), and why a relay never routes a command on an ambiguous claim (AEP-0004 §4.5). A claimed name can deny control, surfaced at the sender, but never divert it.
13. Governance: the AEP process
AEP-numbered documents (AEP-0001 onward) carry types Standards Track — Core /
Binding / Annex, Informational, or Process, and statuses
Draft → Review → Accepted → Final (or Rejected / Withdrawn). Requirements
adopted from MCP's SEP process: motivation/specification/rationale/backward-compat
sections; a sponsor once co-maintainers exist; prototype and conformance fixtures
required before Accepted. Breaking changes to the core namespace require a major
version and a superseding Standards-Track AEP.
Governance firewall (normative): no behavior ships in aep-relay or any
reference artifact before the corresponding specification change is Accepted. The
relay's feature ceiling (ingest, attr-match, fan-out, bounded replay, token auth;
nothing else) is fixed by the governance process.
Licenses: Apache-2.0 for code, SDKs, and schemas; CC-BY 4.0 for specification prose.
14. References
- RFC 2119, RFC 8174.
- RFC 8259 (JSON).
- RFC 3339 (timestamps).
- W3C Trace Context.
- CloudEvents 1.0 (bridge target, AEP-0005).
- OpenTelemetry Logs Data Model and GenAI semantic conventions (bridge target, AEP-0005).
- JSON Schema 2020-12 (normative schema language).
- MCP 2025-11-25 (lifecycle and governance patterns).
- ULID spec.