Capture & redaction
What the four capture levels mean for what leaves the machine, and how the redaction pipeline turns raw agent content into something safe to emit.
Why capture is a level, not a toggle
An agent's raw activity includes things you never want leaving the host by
default: file contents, shell command output, prompts that might quote a
secret. But an observer with nothing at all can't tell two tool calls apart,
route an alert, or show a human what's being asked of them. AEP resolves this
with a declared-per-event capture level rather than a single on/off privacy
switch: an emitter chooses, event by event, how much content is worth the
exposure. The four levels, and what an event's data may honor at each, are
AEP-0001 §8.2:
none: envelope only. No payload content at all; you get that something happened and its routing attributes, nothing else.metadata: structural facts: names, ids, counts, durations, statuses. No free text. This is the default emitter posture; content is opt-in, not opt-out.redacted: free text is present, but it has passed the redaction pipeline described below first.full: verbatim content, unmodified.
Because capture travels on the envelope, any downstream hop (a relay, a
bridge, a subscription with a capture ceiling) can tell at a glance what a
given event is allowed to carry. It can then strip that content down further
(down-level) without needing to know what the fields mean.
It cannot do the reverse. Up-leveling isn't something a downstream party can ever do honestly, since it doesn't have the original content.
Per-field gating, not just per-event
The level on the envelope is a ceiling; individual fields inside data
declare their own minimum level, so a tool.completed event at capture: metadata can still omit result (gated full) while carrying
result_digest (gated metadata), a fingerprint for correlation without
the content itself. This per-field annotation is the mechanical part of
down-leveling: drop everything above the new ceiling, rewrite capture, done.
One boundary is deliberate: redacted is a provenance claim (the text
passed the redaction pipeline below), and dropping fields can't establish
that claim. A mechanical hop asked for redacted from a full event lands
on metadata instead; only a hop that runs the pipeline itself may write
redacted. See AEP-0002 §5.1 for
the annotation mechanism and its rules, and AEP-0001 §8.2(e) for the boundary.
Digest before redaction
A *_digest field exists so two parties can confirm they're talking about
the same content without either of them holding that content: a stable hash
computed over the original, pre-redaction value. Order matters here:
digesting after redaction would make two different secrets that both got
replaced with [REDACTED:secret] hash identically, defeating the point of a
digest. The rule is normative in
AEP-0003 §9.3.
The redaction pipeline
For content gated redacted, an adapter runs the raw text through a fixed
pipeline before it ever leaves the process. The normative floor is
AEP-0003 §9.4: the minimum
every adapter must apply, in order: secrets/credentials, then
operator-configured names, then home-path scrubbing, then PII.
The reference implementation, impl/shared/redact.js, goes beyond that
floor: the spec explicitly allows redacting more than the minimum. An
adversarial security pass found and fixed 13 real bypasses in the original
pattern set:
- quoted credential assignments
- lowercase
bearer - well-known bare token shapes, like GitHub/Slack/OpenAI keys
- home paths for users other than the operator
- credential-named object keys whose value shape wouldn't otherwise match
See the adversarial corpus in conformance/fixtures/redaction/.
Hardening the pipeline further is always in scope; loosening it below the §9.4 floor is a spec change, not a code change.
At capture: metadata (the default), a field gated higher than metadata
isn't just dropped; where the event needs something usable in its place,
that something is synthesized from structural metadata alone (never from the
gated content). See
AEP-0003 §9.2 for the rule
and its rationale.
The pipeline end to end
graph TD
A[Raw agent data] --> B{Above ceiling?}
B -- yes --> C[Drop or synthesize\nfrom structural metadata]
B -- no, redacted-gated text --> D[Redaction pipeline\nsecrets -> configured names\n-> home paths -> PII]
B -- no, digest field --> E[Digest original content\nbefore redaction]
D --> F[Gated event: capture\nrewritten to level honored]
E --> F
C --> F
F --> G[Emitted event]
Every hop after emission can only move an event's content toward none
(never back toward full), which is why a subscription's capture ceiling
(AEP-0003 §6.4) is enough to
guarantee what a given consumer will ever see, regardless of what the
original emitter captured.
See also
- The envelope & identity: where
capturelives on the envelope. - Taxonomy tour: which payload fields are gated at what level.
- The control profile: free-text control answers are redaction-gated the same way.
- Normative source: AEP-0002 §5.1, AEP-0003 §9.