AEP-0009: Assessment (Evaluation Results and Human Feedback)
A new event category, assessment, and its members carry a judgment about an agent's work back onto the event stream:
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-0009-assessment.md, which is the normative text.
| Field | Value |
|---|---|
| AEP | 0009 |
| Title | Assessment: Evaluation Results and Human Feedback |
| Type | Standards Track — Core |
| Status | Accepted (2026-07-23: normative text, schemas, fixtures, and prototype landed in one change per GOVERNANCE.md §2) |
| Sponsor | AEP maintainers (per GOVERNANCE.md §2) |
| Created | 2026-07-23 |
| Requires | AEP-0001 (envelope, fleet-observer test, unknown-type tolerance), AEP-0002 (category set, taxonomy, usage precedent), AEP-0003 (capture levels and redaction) |
| Supersedes / Superseded-by | n/a (additive: a new category and three experimental optional types) |
Abstract
A new event category, assessment, and its members carry a
judgment about an agent's work back onto the event stream:
assessment.evaluation.recorded: an automated or LLM-judge (or code) evaluation result, namely a named metric with a numeric score and/or a categorical label, an optional rationale, and the evaluator's identity. Its field names mirror the de-jure GenAI evaluation convention verbatim.assessment.feedback.received: a human or end-user feedback signal, namely a numeric rating and/or categorical label, an optional free-text comment, an optional correction, and the feedback's source.assessment.guardrail.recorded: an automated content-safety verdict already taken, namely a guardrail / safety-filter / content-moderation check that fired on an input or an output, with its verdict, the violated categories, an optional per-category score, the detector, and an optional rationale. De-jure whitespace (the observability track carries no guardrail attribute), so named natively via aguardrailcommon object.
An assessment targets the run or output it judges through the envelope
(run, session, and cause pointing at the assessed event), so no payload
carries a target id. All three types are emitter-asserted and land
experimental (advertised under capabilities.experimental, AEP-0003 §4);
adding the category is a Standards-Track change to the closed category set
(AEP-0002 §3). No relay behavior changes.
Motivation
The taxonomy (AEP-0002) records what an agent did (runs, tools, progress, retrievals) but has no way to express a judgment about that work. Four concrete cases the fleet cannot currently express:
- An automated evaluator scored a run. An LLM-judge or a code metric rates
an answer's relevance/faithfulness/correctness. Today an emitter can only
bury this in a vendor
x.*type or an unrelatedprogress.status, so a fleet observer watching for low-scoring outputs across a fleet has nothing uniform to match on. - A human gave feedback. A thumbs-down, a star rating, a written comment, or a corrected answer arrives, often out-of-band and after the run finished. There is no core type for it; the signal that most directly tells an operator "this output was bad" is unrepresentable.
- A consumer wants to correlate quality with behavior. Because neither signal is a first-class event, a consumer cannot join "this run scored 0.2 and got a thumbs-down" to the run's tool calls and usage without vendor-specific glue.
- A guardrail blocked or flagged content. An automated safety filter /
moderation model / guard model scored an input or an output and took a
verdict (allowed it, flagged it, blocked it, or rewrote it) against one or
more policy categories. Today an emitter can only bury this in a vendor
x.*type, so a fleet observer watching "N sessions hit a jailbreak block this hour" has nothing uniform to match on. This isassessment.guardrail.recorded(§6), grounded in the cross-producer convergence.
These pass the fleet-observer test (AEP-0001 §3.2): a fleet observer acts on "an output scored below threshold", on "a human flagged this output", and on "a guardrail blocked this content", and these drive dashboards, alerts, and triage. They are distinct moments (an automated score and a human signal are produced by different actors, carry different fields, and are reacted to differently), which is why the category has separate members rather than one discriminated type.
The evaluation half is standardized de-jure: the GenAI observability track
defines an evaluation-result event with a metric name, a score value, a score
label, and an explanation. AEP mirrors those names verbatim, the same posture
usage takes toward the token-count names (AEP-0002 §5.2).
The human-feedback half is de-jure whitespace (no surveyed convention defines a feedback event), with vendor precedent (annotation/score APIs that unify automated and human signals under one object with a producer discriminator). AEP names the feedback shape natively and neutrally, grounded in the cross-vendor field tokens (a numeric magnitude, a categorical label, a free-text comment, a correction) without adopting any one vendor's schema.
Specification
RFC 2119/8174 keywords. The normative payload summary also appears in AEP-0002 §5.4; this section is authoritative for the three types.
1. The category
assessment is added to the closed category set (AEP-0002 §3), scope
session. An assessment.* type's envelope MUST satisfy the session-scoped
requirements of AEP-0001 §5.2 (a session, a seq). Adding the category is a
Standards-Track change to schemas/registry/categories.json and to the
envelope type pattern (schemas/aep-event.schema.json).
2. Targeting (normative)
An assessment MUST target the work it judges through the envelope, not a payload field:
- the assessed run and session are named by the envelope's
runandsession; - the specific assessed event (e.g. a
run.finished, atool.completed, amessage.agent.replied) SHOULD be named by the envelope'scause.
A payload MUST NOT introduce a separate response/target id: the envelope is the
link, the same rule usage and cost follow (AEP-0002 §5.2).
3. assessment.evaluation.recorded
An automated, LLM-judge, or code evaluation result. All fields OPTIONAL; the payload schema is OPEN (AEP-0002 §5.1). Field names mirror the de-jure GenAI evaluation convention verbatim:
gen_ai.evaluation.name, string [metadata]: the evaluation metric's name.gen_ai.evaluation.score.value, number [metadata]: the numeric score. It is emitter-asserted and unbounded, and the evaluator states its own scale. A consumer MUST NOT assume a fixed range.gen_ai.evaluation.score.label, string [metadata]: the categorical verdict (e.g.pass,fail,relevant).gen_ai.evaluation.explanation, string [redacted]: the evaluator's free-text rationale. It MAY contain sensitive content, so it routes through AEP-0003 §9 redaction and drops at ametadataceiling.evaluator, string [metadata]: a native token identifying the judge or check that produced the result (an LLM-judge model id or a code-check name).
The score kind is carried structurally, as a numeric score.value, a string
score.label, or both, not by a data-type discriminator field.
4. assessment.feedback.received
A human or end-user feedback signal. All fields OPTIONAL; the schema is OPEN. De-jure whitespace, so named natively:
rating, number [metadata]: a numeric feedback magnitude (a thumbs±1, a 1-5 star). Emitter-asserted and unbounded, like the evaluation score.label, string [metadata]: a categorical verdict (e.g.thumbs_up).comment, string [redacted]: free-text feedback. Content-bearing, so gated through AEP-0003 §9.correction, string [redacted]: a corrected or ground-truth output the human supplied. Content-bearing, so gated.source, string [metadata]: where the feedback came from (e.g.human,end_user). This is the feedback's author, which the envelope's emitter identity (the relay or adapter that forwarded it) does not carry.
5. Capture and redaction (normative)
The content-bearing fields are classed redacted (AEP-0003 §9):
assessment.evaluation.recorded's gen_ai.evaluation.explanation,
assessment.feedback.received's comment and correction, and
assessment.guardrail.recorded's guardrail.explanation (§6). At a metadata
capture ceiling they drop mechanically, and the scores, labels, metric name,
evaluator, rating, source, and the guardrail verdict/categories/detector
survive: a metadata-only consumer keeps the fact and magnitude of the
assessment and loses the sensitive text. All other fields are metadata.
6. assessment.guardrail.recorded
An automated content-safety verdict already taken: a guardrail / safety-filter
/ content-moderation check that fired on an input or an output. All fields
OPTIONAL; the payload schema is OPEN. De-jure whitespace (the observability
track carries no guardrail/moderation attribute, and the producer names
diverge), so named natively via one guardrail common object (AEP-0002 §5.2):
guardrail.stage, enum(input|output) [metadata]: what was scored, a prompt/input or a produced output.guardrail.verdict, enum(allowed|flagged|blocked|modified) [metadata]: the convergent union across the surveyed producer vocabularies.allowed(nothing fired),flagged(a soft warn, not a hard stop),blocked(a hard stop / refusal),modified(the guard rewrote or redacted the content).guardrail.categories, array [metadata] of{ name: string [metadata], score?: number [metadata] }: the violated / evaluated policy categories.nameis a free vendor-taxonomy string, deliberately NOT a closed enum: the producer taxonomies diverge, so closing it would bless one vendor or force a lossy mapping (injection / jailbreak is one such category name, not its own type).scoreis the emitter's per-category score, emitter-asserted and unbounded; the emitter states its own scale.guardrail.detector,{ name?: string [metadata], version?: string [metadata] }[metadata]: the guard model / filter / rule engine that produced the verdict, with its version companion.guardrail.explanation, string [redacted]: a free-text rationale. It MAY quote the offending content, so it routes through AEP-0003 §9 redaction and drops at ametadataceiling.
A guardrail outcome is a judgment about content-safety, an automated
assessment produced by a guard model or rule engine, so it is a sibling of
assessment.evaluation.recorded, not a phase of the work. It targets the scored
work through the envelope (§2): the scored run and session are the
envelope's run/session, and the specific scored event (a run.finished, a
tool.requested, a produced answer) SHOULD be the envelope's cause; no
payload carries a target id.
Conformance fixtures
Landing in the same change (GOVERNANCE.md §2, the SEP rule):
conformance/fixtures/golden/golden.jsonlgains an assessment session: anassessment.evaluation.recorded(a named metric with a numeric score, afaillabel, a redacted explanation, and an evaluator) and anassessment.feedback.received(a-1rating, athumbs_downlabel, a redacted comment and correction, and ahumansource), bothcause-linked to the assessed run's terminal. The runners assert both are envelope-valid and payload-valid, and the CloudEvents round-trip is identity-preserving.conformance/fixtures/downlevel/cases.jsongains DL14 and DL15, pinning the per-field content gating: at ametadataceiling the redacted fields (explanation;comment/correction) drop while the metadata provenance (name/score/label/evaluator; rating/label/source) survives.
The guardrail member (§6) extends the same fixtures:
golden.jsonlgains anassessment.guardrail.recordedon the same assessment session (ablockedoutputverdict over a violated category with a score, a generic detector, and a redacted explanation),cause-linked to the same assessed run's terminal; the runners assert it envelope- and payload-valid and CE-identity-preserving.cases.jsongains DL18: at ametadataceiling the redactedguardrail.explanationdrops while the verdict/stage/categories/detector survive.
Prototype
The spec-derived conformance runner (conformance/run.py) validates the new
golden vectors against the new schemas and regenerates the CloudEvents pins;
the reference stack's Node runner (conformance/run.js, run over the vendored
copy) exercises the same corpus through the reference validator and the
capture-gating projection (DL14/DL15/DL18). The generated type models
(schemas/gen/) add AssessmentEvaluationRecordedData,
AssessmentFeedbackReceivedData, and AssessmentGuardrailRecordedData, and the
SDKs regenerate from the same schemas.
No reference-relay behavior changes: an assessment event ingests, matches, and replays as any other session event. No adapter emits assessment events, so the adapter smokes are unaffected (verified green).
Rationale
Why a new category, not an existing one. An assessment is a judgment about
work, not a phase of it. It is not run/tool (the work's own lifecycle), not
progress (intermediate status produced by the worker; an assessment is
produced by an evaluator or a human, often after the fact and out-of-band), and
not error (a low score is not a fault). No existing category fits, so, per
AEP-0002 §3, a Standards-Track category addition.
Why two types, not one discriminated type. The dominant vendor precedent is a single object with a producer discriminator. AEP splits instead because the fleet-observer test separates the two moments and their payloads differ: the automated half mirrors a shipped de-jure convention verbatim; the human half is native whitespace and carries a correction the eval half never does.
One discriminated type would force one schema to carry both an OTel-style
mirror and a native-feedback shape, muddying both. Two focused three-segment
types match the taxonomy idiom (resource.retrieval.*, delegation.subagent.*).
Why the envelope is the link. Every surveyed vendor points a score back to
its target by an id. AEP already has that link natively (run, session, and
cause), so a payload target id would duplicate the envelope, exactly the
reasoning that keeps usage/cost free of a run id (AEP-0002 §5.2).
Why no score-kind enum. Only one vendor names a data-type discriminator;
the others encode kind structurally (a numeric score vs a string label). AEP
follows the structural convention, a score.value and/or a score.label, so
the shape stays open and a boolean/categorical/numeric result needs no closed
enum. Rejected: a dataType field.
Why mirror the eval names verbatim but not the feedback names. Directive:
where a de-jure name exists, mirror it verbatim (the usage posture); where it
does not, name natively and neutrally. The evaluation half has a shipped
convention (name/score.value/score.label/explanation), so it is mirrored. The
feedback half has none, so it is named natively
(rating/label/comment/correction/source),
grounded in the cross-vendor tokens without adopting a vendor schema.
Why a guardrail outcome is a third assessment type, not folded into
evaluation and not a new category. A guardrail verdict is a judgment about
work, an automated assessment of content-safety produced by a guard model or
rule engine, often after the fact, so it belongs to assessment, not a new
category (the same test the category itself passes).
It is not the evaluation type: an evaluation is a quality metric (a name + a numeric/label score), a guardrail is a safety verdict (allowed/flagged/blocked/modified) over violated policy categories, a different actor, vocabulary, and reaction (a fleet observer acts on "a jailbreak block", not "a low relevance score"). Hence a third focused three-segment type rather than a widened evaluation schema.
Its names are native and neutral (de-jure whitespace: no observability-track
guardrail attribute, and the producer names diverge): the verdict enum is the
convergent union across the producers, and categories[].name is deliberately
an open string so no vendor taxonomy is blessed (injection/jailbreak is a
category name, not its own type).
It is distinct from the shipped interactive approval gate
(attention.*/control.*, where a human is ASKED, in-band), from
tool.denied (a TOOL policy deny; a guardrail scores content), and from
error.raised (a block is a successful policy action). Choice A of the decision
card: the existing assessment category, no new category, no envelope change,
no SDK-validator lockstep.
Backward Compatibility
Purely additive within the 0.1 major (AEP-0001 §11, GOVERNANCE.md §4): a new
category and three OPTIONAL experimental types
(assessment.evaluation.recorded, assessment.feedback.received, and
assessment.guardrail.recorded, §6) with their OPEN payload schemas. No
existing type, category, attribute, or capability is repurposed or removed.
A new optional type in the already-open assessment category is
additive-minor, with no category, envelope, or SDK-validator change (the
assessment prefix is already admitted by the envelope type pattern and
the SDK type grammar).
- Emitters that do not produce assessments are unaffected; nothing becomes required.
- Consumers predating this AEP already tolerate unregistered members in a
known category (AEP-0001 §6), and a consumer that predates the category
treats
assessment.*exactly as it treats any unknown type: the envelope is well-formed and the event passes through. The updated envelopetypepattern only widens the accepted set. - Stored streams are unchanged; no prior event is reinterpreted.
Because the types are experimental, the payload shapes MAY change before they
graduate (extension → experimental core → core, AEP-0002 §6). Graduation to
stable is itself a superseding AEP. Consumers SHOULD gate on
capabilities.experimental (AEP-0003 §4) before relying on the shape.
Security considerations
Assessments carry potentially sensitive content, handled by the existing capture model (AEP-0003 §9), not a new mechanism:
The rationale (
gen_ai.evaluation.explanation), the feedbackcommentandcorrection, and the guardrailguardrail.explanationareredacted-classed. An emitter at ametadatacapture ceiling MUST drop them; the redaction pipeline applies as to anyredactedfield. A metadata-only consumer keeps the assessment's fact and magnitude and never sees the text. This is enforced mechanically by the per-fieldx-aep-captureannotations and pinned by DL14/DL15/DL18.The guardrail
explanationis a specific hazard: it can quote the offending content the guardrail fired on (a jailbreak prompt, a disallowed output), so routing it through redaction is load-bearing. The verdict/categories/detector are the fact worth keeping atmetadata.Scores, labels, ratings, verdicts, categories, and the
evaluator/source/detectortokens aremetadata; emitters SHOULD keep free-text or identifying content out of them (put it in the gated fields), the same discipline other metadata tokens follow.No control authorization (AEP-0004), identity, or bridge-capture (AEP-0005 §3.3) surface changes: an assessment is an ordinary session event on the bus, subject to the same token auth and capture enforcement as any other.
Open questions
- Graduation criteria. What adopter evidence promotes
assessment.*fromexperimentalto core: a threshold of emitters, or a settled feedback shape? Owner: AEP maintainers; resolve before any 0.x → 1.0 freeze. - Dataset / offline-evaluation linkage. Some vendors link a score to a dataset run or a comparative experiment (an offline-eval concept). This AEP deliberately scopes to the live fleet stream and omits it; revisit only if an adopter shows a concrete live-stream need. Owner: AEP maintainers.
- A rerank/aggregate assessment. A roll-up of several evaluations into one verdict is unmodeled; the natural follow-up card if demand shows. Owner: AEP maintainers.
References
- AEP-0001, Core and Envelope (§3.2 fleet-observer test, §5.2 session-scoped requirements, §6 unknown-type tolerance, §11 additive evolution).
- AEP-0002, Taxonomy and Types (§3 category set, §4.2 optional types, §5.1
open-schema/capture rules, §5.2
usage/cost/common-object precedent, §5.4 the normative payload summary, §6 the promotion path). - AEP-0003, Bindings and Lifecycle (§4
capabilities.experimental, §9 capture levels and redaction). - GOVERNANCE.md §2 (the SEP rule), §4 (additive versioning).