Documentation Index
Fetch the complete documentation index at: https://agenticadvertisingorg-changeset-release-main.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Status: Request for Comments
Last Updated: April 19, 2026
Two words, not three
AdCP conformance has two load-bearing terms. A third (one you’ll hear in the wild) is a trap.
- Conformant — the agent meets the normative rules. Defined by the storyboards this document indexes.
- Verified — AAO has tested the agent recently and issued a signed attestation. Gated on active membership and a live heartbeat. The AAO Verified badge carries one of two qualifiers: (Spec) for storyboard-conformance against a test deployment or dev endpoint, (Sandbox) for storyboard-conformance against the seller’s real production endpoint under
account.sandbox: true flagging. An agent can earn either or both.
- “Compliant” — self-attested, unverified, no external check. Don’t claim it; don’t design for it. This document uses conformant and verified exclusively.
Put differently:
- Conformance is a property of the agent’s wire behavior.
- Verification is a time-bounded third-party attestation. (Spec) attests wire-format conformance against any registered endpoint; (Sandbox) attests the same storyboard suite passes against the seller’s real production endpoint under sandbox-flagged traffic. Same storyboards, different attestation surface.
- The two axes are independent: a seller without a separate test deployment can earn (Sandbox) directly on production; a test agent that can never serve real impressions earns (Spec) as a complete claim.
Storyboard conformance vs. AAO Verified
This page indexes storyboard conformance — the property an agent’s wire behavior has when it matches the spec, verified by storyboards running against seeded test data. Storyboard passing earns the AAO Verified (Spec) or AAO Verified (Sandbox) qualifier (or both) on an agent’s badge, depending on where the runner targeted.
A second axis — AAO Verified (Sandbox) — verifies the seller’s real production endpoint correctly handles the full storyboard suite under account.sandbox: true flagging. (Sandbox) is the stronger claim: a seller can pass (Spec) on a test deployment while their production stack has a broken sandbox gate (real-world side effects under flagged traffic, missing account-mode verification, etc.) — (Sandbox) closes that gap.
The two qualifiers share one brand mark — AAO Verified — and an agent can earn either or both. (Spec) and (Sandbox) are independent: each independently demonstrates conformance through different evidence. (Spec) attests wire-format conformance against any registered endpoint; (Sandbox) attests the production code path correctly tolerates sandbox-flagged traffic. See AAO Verified for the qualifier model and the Sandbox framing verdict; the rest of this page indexes the storyboards that back both qualifiers.
Test surfaces and the storyboard loop
Every seller exposes a test surface — the mechanism that lets a storyboard runner exercise the seller’s tools deterministically without triggering real-world side effects. The test surface is what (Spec) is graded against. How a seller stands up that surface depends on where their state-of-record lives; the implementation differs, the goal does not:
| Where state-of-record lives | How the test loop closes |
|---|
| Local DB only (typically SSPs, creative agents) | The storyboard runner writes fixtures via comply_test_controller.seed_*; the seller’s read handlers consume the same store. The seed → read loop closes naturally. |
| Upstream system the seller does not control (DSPs proxying to platforms, retail-media networks reading retailer catalogs, signals brokers) | Seeded writes are dead to the read handler. The TypeScript SDK ships a TestControllerBridge that runs the real adapter call first (so a broken upstream call still fails the gate), then merges seeded fixtures into the response. |
| Mixed (some tools local, some upstream) | Both, per tool. |
Both paths earn (Spec) — both prove the seller’s wire format matches the storyboards. The bridge is one implementation of the test-surface pattern, not a separate seller category. A state-local seller without wired seeds and an upstream-proxy seller without a wired bridge are in the same position: storyboards cannot run end-to-end against them. Neither category is what (Sandbox) attests; (Sandbox) is the separate axis covering whether the seller’s production stack honors account.sandbox: true without real-world side effects.
Distinguishing fixture-merged from upstream-derived responses
When a response passes through the SDK’s TestControllerBridge, the SDK stamps a _bridge: { callback, tool, merged_count } marker on the response. Marker presence on a step means the response content was merged from a seeded fixture after the seller’s handler returned; marker absence means the response came from the seller’s adapter end-to-end (or from a local DB the runner seeded directly). The marker is advisory metadata for runners and downstream leaderboards — it is not part of the wire contract. Sellers MUST NOT emit it, and conformance checks ignore it. The leading underscore marks the field as SDK/runner-stamped metadata reserved for testing tooling; future fields with the same prefix follow the same rule.
Marker design: adcp-client#1775. Shipped: adcp-client#1786. Leaderboard policy that consumes the marker: adcp-client#1782.
Three signals — don’t conflate them
Adopters often read these three controls as the same thing. They answer different questions:
| Signal | Question it answers |
|---|
Test controller availability (comply_test_controller in tools/list) | “Has the seller exposed deterministic-mode forces?” |
Sandbox flag (account.sandbox on requests) | “Is the targeted account a sandbox account, with no real-world side effects?” |
Bridge participation (_bridge marker on a response) | “Did this response come from the adapter’s upstream call, or from a fixture the SDK merged in?” |
These are runtime controls on individual storyboard steps — distinct from the (Spec) and (Sandbox) verification qualifiers, which describe what a storyboard pass attests over time. A storyboard pass can carry any combination of the three signals.
Storyboards are the truth
Rather than restate every MUST in prose — which would inevitably drift from the executable suite — the storyboards ARE the conformance specification. This document is a navigational index to them, grouped by the declaration that obligates the storyboard to run.
Every normative rule in the suite has exactly one home: the storyboard YAML at /compliance/latest/. Changes to what “conformant” means happen there, in a versioned release, tested against real agents. If a rule isn’t in a storyboard, it’s not part of conformance.
This is deliberate. A separate prose spec that restates storyboard rules creates two sources of truth. Two sources of truth drift. We pick one: the suite.
The @adcp/sdk package also ships TypeScript files under testing/scenarios/ that pre-date storyboard-driven comply(). They are not the conformance spec — see Storyboards vs. scenarios for which is which.
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the referenced storyboards and prose sections below are to be interpreted as described in RFC 2119.
Every agent satisfies the universal layer. Each supported_protocols claim adds a protocol baseline. Each specialisms claim adds a specialism baseline.
| Layer | Obligation | Path |
|---|
| Universal | Every AdCP agent | /compliance/latest/universal/ |
| Protocol | Agent claiming a supported_protocols value | /compliance/latest/protocols/{protocol}/ |
| Specialism | Agent claiming a specialisms value | /compliance/latest/specialisms/{id}/ |
Agents MUST NOT declare a capability whose storyboards they do not pass. See the Compliance Catalog for the full taxonomy and Validate Your Agent for how to run the suite locally.
Every agent MUST pass every storyboard below.
| Storyboard | What it verifies |
|---|
capability_discovery | get_adcp_capabilities shape, protocol/specialism declarations, version advertising |
schema_validation | Request and response schema conformance, ISO 8601 timestamps, temporal invariants |
schema_validation_signals | Response schema compliance for signals — required fields on every signal; gated on get_signals |
v3_envelope_integrity | v3 protocol envelopes MUST NOT carry the v2 legacy task_status or response_status fields — status is the single canonical lifecycle field in v3 |
error_compliance | Structured error shape, published error codes, transport binding, no existence leaks across tenants |
error_compliance_signals | Error handling for signals protocol — nonexistent signal IDs, missing fields, VERSION_UNSUPPORTED, transport binding; gated on get_signals + activate_signal |
idempotency | idempotency_key scoping, replay semantics, IDEMPOTENCY_CONFLICT, replayed: true, declared TTL |
security_baseline | Unauth rejection, API key enforcement, OAuth discovery + RFC 9728 audience binding |
webhook_emission | Outbound webhook conformance — stable idempotency_key across retries, RFC 9421 webhook signing (or opt-in HMAC fallback) on every delivery. Runs for any agent accepting push_notification_config. |
notification_config_event_scope | sync_accounts.accounts[].notification_configs[] semantic validation — account-level subscribers reject media-buy-anchored notification types even though those values are valid in the shared enum |
pagination_integrity | cursor ↔ has_more invariant on paginated list_creatives responses, walked from a continuation page through to a terminal page |
get_signals_pagination_integrity | cursor ↔ has_more invariant on paginated get_signals responses under a broad query, with first-page non-terminal assertion against any non-trivial signal set |
pagination_integrity_list_accounts | cursor ↔ has_more invariant on paginated list_accounts responses; storyboard bootstraps three accounts via sync_accounts and walks from a continuation page to a terminal page |
pagination_integrity_creative_formats | cursor ↔ has_more invariant on paginated list_creative_formats responses; storyboard seeds two creative formats via seed_creative_format and walks from a continuation page to a terminal page |
get_media_buys_pagination_integrity | cursor ↔ has_more invariant on paginated get_media_buys responses; storyboard seeds three media buys via seed_media_buy and walks from a continuation page to a terminal page |
pagination_integrity_content_standards | cursor ↔ has_more invariant on paginated list_content_standards responses; storyboard bootstraps three content standards configurations via create_content_standards and walks from a continuation page to a terminal page |
pagination_integrity_collection_lists | cursor ↔ has_more invariant on paginated list_collection_lists responses; storyboard bootstraps three collection lists via create_collection_list and walks from a continuation page to a terminal page |
pagination_integrity_property_lists | cursor ↔ has_more invariant on paginated list_property_lists responses; storyboard bootstraps three property lists via create_property_list and walks from a continuation page to a terminal page |
deterministic_testing | comply_test_controller state machine — skipped if capabilities.compliance_testing.supported: false |
signed_requests | RFC 9421 transport-layer request-signing verification — skipped if request_signing.supported: false. |
billing_gate_dispatch | Two-gate dispatch on sync_accounts.billing rejection: seller-wide capability gate (BILLING_NOT_SUPPORTED with error.details.scope) vs per-buyer-agent commercial-relationship gate (BILLING_NOT_PERMITTED_FOR_AGENT with the clamped rejected_billing + optional suggested_billing shape). Capability phase skipped when the seller supports all three billing values; per-agent phases skipped when the test kit does not declare commercial_relationship: passthrough_only. |
Agents that declare capabilities.compliance_testing.supported: true MUST implement the full test controller; a partial controller is non-conformant, so declare false rather than ship one.
Agents that declare request_signing.supported: true MUST implement the full RFC 9421 verifier per the request-signing profile; a partial verifier is non-conformant, so declare false rather than ship one.
A supported_protocols claim obligates the protocol’s baseline storyboard.
A specialisms claim obligates the specialism’s storyboard in addition to its parent protocol baseline. The catalog lives at /compliance/latest/index.json; the human-readable index is the Compliance Catalog.
Specialisms carry a status — stable (verified pass/fail), preview (storyboard not yet defined; runner emits passed: null), deprecated (scheduled for removal). Agents MAY claim preview specialisms, but preview claims do not yield a pass/fail verdict.
Outside the wire
Some requirements can’t be verified by a storyboard because they’re operator-level, not wire-level. They remain part of running a conformant agent, but the suite can’t attest to them. Operators MUST self-assess against these; third-party frameworks (SOC 2, ISO 27001) are the usual attestation path.
- Secret storage — credentials SHOULD live in a KMS or equivalent. The wire shows only whether auth succeeds, not where the key was stored.
- Credential rotation and revocation — the operator MUST have a documented path to revoke a compromised credential in under an hour. The wire can’t observe the runbook.
- Personnel and physical security — who can touch production, break-glass custody, employee offboarding. Entirely outside the protocol.
- Governance agent due diligence — when the operator relies on a third-party governance agent, the buyer SHOULD treat it as a processor with multi-customer blast radius and assess its posture. The storyboards verify correct JWS handling by the seller but cannot vouch for the governance agent itself.
- LLM subprocessor posture — if the agent uses an LLM provider, the DPA with that provider governs whether prompts, brand assets, or creative metadata may be retained. The protocol can’t see upstream DPA terms.
- Incident response — AdCP emits the signals worth watching (
IDEMPOTENCY_CONFLICT spikes, failed governance verifications, SSRF rejections); detection, alert routing, and response are operator concerns.
- Data residency configuration — whether and how EU / UK data is kept in-region is typically declared in the agent’s capabilities or contract; the wire records the declaration, not the underlying infrastructure.
Full operator checklist: Security Model § What to verify before going live.
Conformance is wire-level correctness. SOC 2, ISO 27001, and NIST CSF are operational assurance. They answer different questions and neither substitutes for the other.
| External control area | Storyboard evidence | Gap to external assurance |
|---|
| Access control (SOC 2 CC6, ISO 27001 A.5.15) | security_baseline (identity) + isolation checks in protocol storyboards | Personnel access reviews, least-privilege admin, offboarding |
| Change management (SOC 2 CC8) | idempotency proves duplicate state changes are prevented on the wire | Deployment approvals, release gates, rollback procedures |
| System monitoring (SOC 2 CC7, ISO 27001 A.8.16) | Error taxonomy produces a monitorable surface | Detection engineering, alert routing, on-call runbooks |
| Cryptography (ISO 27001 A.8.24) | TLS, RFC 9421 signing, JWS governance tokens | KMS selection, rotation cadence, cert lifecycle |
| Audit logging (SOC 2 CC7) | Governance storyboards verify signed-record issuance | Log retention, legal hold, integrity monitoring |
| Data handling (SOC 2 Privacy, GDPR, ISO 27701) | TMP two-call separation, audience hashing, signal access control | Data subject rights, DPA management, cross-border transfer |
| Vendor and subprocessor risk (SOC 2 CC9) | adagents.json / brand.json discovery, JWKS publication | Third-party risk assessment, LLM provider review |
| Incident response (SOC 2 CC7, NIST CSF RS) | Signals observable; response not mandated | Runbooks, tabletop exercises, breach notification |
| Business continuity (ISO 27001 A.5.30) | Cross-instance state storyboard checks | RPO/RTO targets, DR testing |
Two practical consequences:
- Storyboard pass evidence MAY support specific external control objectives. It is not a substitute for an audit.
- External certification does not imply AdCP conformance. SOC 2 Type II says nothing about whether
create_media_buy responses validate.
- Declare
supported_protocols and specialisms in get_adcp_capabilities.
- Pass every storyboard the declaration obligates — universal + protocol baselines + specialism baselines — at a specific AdCP major version.
- Keep declaration and behavior in sync. An undeclared capability the suite happens to test is separate from a declared capability that fails. Both are non-conformant.
Conformance is per-version; the suite is per-version. A 3.0-conformant agent is not thereby 3.1-conformant.
For third-party attestation, run the heartbeat against AAO and earn an AAO Verified badge. The badge is a signed claim that AAO tested the agent recently and the pass still holds. Buyers filtering on verified get a smaller set than conformant — fewer agents, fresher attestation, a named party on the hook.
What this document does not do
- Define individual MUSTs. The storyboards do. If a rule isn’t in a storyboard, it isn’t part of conformance.
- Grant or revoke certification. The AgenticAdvertising.org certification program runs on top of this; conformance is necessary but not sufficient.
- Publish reference test vectors beyond those already in the suite. The Reference Test Vectors index catalogs the vector sets that ship today; broader task-level corpus lands incrementally between 3.0 GA and 3.1, scoped in #2383.
When a storyboard fails
When a failure surfaces a disagreement between the spec, the mock, and an SDK, the section below gives the triage order. For symptom-to-cause lookup, see the links at the end of this section.
Mock-server authority and failure triage
The adcp mock-server is the reference wire implementation for stable surfaces. Use this triage order when a storyboard failure implicates the mock or an SDK:
Triage order: spec → mock → SDK. The storyboards (and the schemas they reference) are canonical. The mock interprets the storyboards. The SDK consumes the protocol via the mock.
| Condition | Default verdict | Next step |
|---|
| SDK wire shape differs from the mock’s | SDK is wrong | File a bug against the SDK |
| SDK wire shape matches the mock’s, but a storyboard still fails | Mock is wrong | File an issue against adcontextprotocol/adcp to fix the mock |
| Storyboard assertion conflicts with an otherwise-passing wire shape | Storyboard is wrong | File an issue against adcontextprotocol/adcp to fix the storyboard |
| Spec text (storyboard prose or schema) explicitly contradicts the mock | Spec wins; mock is the bug | File an issue against adcontextprotocol/adcp to fix the mock |
Scope. This triage order applies to stable surfaces only. Experimental surfaces (see Experimental Status) are under active revision; mock behavior there is not yet authoritative.
Spec ambiguity vs. spec silence. When spec text exists but is ambiguous, the mock’s behavior pins the authoritative interpretation — that pinning is normative even if the prose has not yet been tightened. When the spec is entirely silent on a point and the mock has no behavior for it, the chain breaks; open a known-ambiguities issue instead of treating the mock as authoritative.
Further reading