Releases: adcontextprotocol/adcp
v3.0.8
Patch Changes
-
8f82d46: fix(compliance): UUID-aliased idempotency_keys across remaining storyboard scenarios
Extends the #4218 precedent (
measurement_terms_rejected) to the rest of the suite. 15 storyboard steps across 9 scenarios still shipped hardcodedidempotency_keyliterals on state-mutating tasks (create_media_buy,sync_creatives,sync_plans,update_media_buy). The runner shifts dynamicstart_timesubstitutions forward to keep buys future-dated, so against a long-running seller deployment those static keys collide cross-run with the same key + a different canonical body, arming the spec-mandatedIDEMPOTENCY_CONFLICT(or, when the seller's emit shape changed between runs, replaying a now-spec-non-compliant cached payload — the production failure mode that surfaced this).Switch every remaining literal to
$generate:uuid_v4#<scenario>_<step>so each storyboard run mints fresh keys and never collides with stale cached state. Affected scenarios:creative_fate_after_cancellation(5),governance_approved,governance_conditions,governance_denied,governance_denied_recovery(3),invalid_transitions,inventory_list_no_match,inventory_list_targeting,pending_creatives_to_start.Closes #4230.
v3.0.7
Patch Changes
-
866abe2: docs(creative): tighten type column in the
list_creativesfiltering options table to matchcore/creative-filters.json.accountsnow showsAccountRef[](wasarray),format_idsshowsFormatID[](wasformat_id[], matching the casing used inlist_creative_formats,get_products, andcreate_media_buy), andstatuseslinks toCreativeStatusrather than the under-specifiedstring[]. Docs only — no schema or wire-format change. Patch-eligible per the non-normative-docs rule in.agents/playbook.md. -
b2f7a3d: fix(compliance):
measurement_terms_rejected— UUID-aliased idempotency_keys + spec-aligned narrativeThe
media_buy_seller/measurement_terms_rejectedstoryboard shipped hardcodedidempotency_keyliterals on bothcreate_media_buysteps. Combined with runner-side dynamicstart_timesubstitution (the runner shifts stale dates forward to keep the buy future-dated), this produced same key + different body on every run against a long-running seller deployment, arming the spec-mandatedIDEMPOTENCY_CONFLICTon the seller side. Switch to$generate:uuid_v4#…aliases so each run mints fresh keys (matches the established pattern across the storyboard suite).Also rewrites the narrative, which previously told implementers the buyer "retries the same
create_media_buyidempotency_keywith an adjusted payload" — a direct spec violation — to describe minting a fresh key for the retry.Closes #4219. Refs adcontextprotocol/adcp-client#1586.
v3.0.6
Patch Changes
-
91b6e2c: spec(errors): wire-placement guidance for
GOVERNANCE_DENIEDandGOVERNANCE_UNAVAILABLEerror-code.jsondefined the codes' semantics but didn't say WHERE in the response they appear. Different storyboards interpreted differently — issue #3914 surfaced one mismatch where the brand-rights compliance storyboard expectedexpect_error: code: GOVERNANCE_DENIEDeven thoughacquire_rightsalready has a first-classAcquireRightsRejecteddiscriminated arm withreason. Adopters returning the spec-correct Rejected shape were failing the storyboard.The
enumDescriptionsfor both codes now state placement explicitly:GOVERNANCE_DENIED— structured business outcome, not a system error. When the task response defines a structured rejection arm (e.g.,AcquireRightsRejected), that arm is the canonical denial shape — populatestatus: "rejected"+reason, do NOT additionally emit the code inerrors[]oradcp_error, and do NOT flip transport-level failure markers. When the task has no rejection arm (e.g.,create_media_buyreturns theErrorarm), populateerrors[].codeANDadcp_error.codeper the two-layer model and DO flip transport markers.GOVERNANCE_UNAVAILABLE— system error, governance call failed at all. Always populate both layers with the code and flip transport markers. Sellers MUST NOT use a structured rejection arm for unavailability even when the task offers one — the buyer's recovery semantics differ (retry-with-backoff vs. restructure-or-escalate).
The contrast resolves the question the storyboard mismatch surfaced: thrown adcp_error is reserved for governance-call failure modes (parallel to
GOVERNANCE_UNAVAILABLE), not for adopter-controlled denials.The MUST NOT against dual-emission isn't a behavior change —
AcquireRightsRejectedandCreativeRejectedalready declarenot: { required: [errors] }at the schema layer, so emittingerrors[]alongside a rejection arm was already a schema violation. The doc-comment makes the rule discoverable from the error code without changing what conformant senders produce.Also adds a parallel storyboard-authoring note in
error-handling.mdx: when the task response has a discriminated rejection arm, assertions should usecheck: field_value, path: "status", value: "rejected"rather thancheck: error_code. The existingerror_codeguidance is correct for tasks without a rejection arm; the new note covers the rejection-arm path that surfaced via #3914.Closes the doc-comment item on #3918; companion to #3914 (storyboard fix is separate work).
-
91b6e2c: spec(conventions): reserve
ctx_metadataas adapter-internal round-trip keyReserves the top-level key
ctx_metadataon AdCP resource objects (Product, MediaBuy, Package, Creative, AudienceSegment, Signal, RightsGrant) as a publisher-to-SDK round-trip cache for adapter-internal state. SDKs MUST strip the key before wire egress and MUST emit a warning-level log entry when stripping, so operators can detect accidental collisions with existing adapter code. Buyers never see this field.The convention is non-binding at the wire level — these resources already declare
additionalProperties: trueso existing payloads remain valid. The reservation locks the keyword name before two SDKs converge on it accidentally and ship divergent semantics. PropertyList and CollectionList are out of scope (additionalProperties: false) until a follow-up PR widens those schemas.Closes #3640.
-
e4af188: docs(skill): document the four implementation-dependent
issues[]fields callers may seeskills/call-adcp-agent/SKILL.mdalready documents the three requiredissues[]fields (pointer,keyword,variants) that every conformant validator surfaces. Adds the four optional fields a calling agent will encounter when the seller's validator opts into them —discriminator,schemaId,allowedValues,hint— with a one-line preface clarifying these are implementation-dependent (not every validator emits them) and an updated recovery order: readhintfirst when present, thendiscriminator, then walkvariants.Two new rows added to the symptom-fix lookup table for the same fields.
No wire-format change. Pure documentation: shipping these fields is already a valid validator extension; this just gives callers a curated path through them.
Surfaced from the @adcp/sdk side after PR #1283 / #1309 added the fields and PR #1268 / #1361 hit recurring drift between the local SDK skill copy (which already documented them) and the upstream bundle (which didn't). With this merged, the SDK's
npm run sync-schemasno longer rewrites the file out from under contributors.
v3.0.5
What's in 3.0.5
Three additive 3.0.x changes plus a CI plumbing fix. Wire format unchanged for any 3.0 agent that doesn't claim a new optional surface.
For adopters:
- Adopting
identity.brand_json_urlfrom #3690 on 3.0? Bump to 3.0.5. 3.0.4 and earlier rejected the field at validation; 3.0.5'sidentity.additionalProperties: trueaccepts it. Mirrors whatmainshipped post-#3690. - Running brand-rights conformance? Spec-compliant agents that return
rights_id(peracquire-rights-response.json) now passrights_acquisitionand stop cascade-skippingrights_enforcement. Storyboard YAML was reading the wrong field name. Closes #3892. - Authoring multi-agent storyboards? New optional top-level
default_agent: <key>field lets you encode topology intent in YAML once instead of re-asserting it on every CI invocation. Closes #3894. - Maintaining the release pipeline? Forward-merge auto-resolution chain is now complete — every Version Packages cut auto-creates the forward-merge PR without manual intervention.
For full context, migration guidance, and the security model around the relaxed identity validator, see Release Notes § 3.0.5.
---### Patch Changes
-
a4bd513: spec(capabilities): relax
identity.additionalPropertiestotrueonget-adcp-capabilities-responseForward-compat fix for 3.0.x. The
identityobject was schema-closed (additionalProperties: false), so any operator that adopted a forward-compatible field — notablyidentity.brand_json_urlfrom #3690, which was always intended to be readable by 3.0-pinned implementers without a schema bump — would have its capabilities response rejected by strict 3.0 validators (e.g.,@adcp/sdk'screateAdcpServerdefault).Mirrors the
additionalProperties: truealready shipped onmainpost-#3690. Strictly additive: the closed property list (per_principal_key_isolation,key_origins,compromise_notification) is unchanged; receivers that ignore unknown fields keep working; receivers that look for new identity fields gain forward-compat without waiting for a 3.x bump.The forward-compat narrative in
security.mdx("3.0-pinned implementers can adopt the field today without bumping") depends on this relaxation being live in shipped schemas — without it, the spec advice contradicts the schema. -
d98c9e4: spec(storyboard-schema): add optional storyboard-level
default_agentfieldCloses #3894. Adds an optional top-level
default_agent: <key>field to the storyboard authoring schema (static/compliance/source/universal/storyboard-schema.yaml).default_agentis the logical name (sales,governance,creative, etc.) the multi-agent runner falls back to when a step has nostep.agentoverride and the tool has no unique specialism claimant in the runtime agents map. Resolved against theagentsoption passed torunStoryboard({ agents: {…} })— see adcp-client#1066 and adcp-client#1355.The runner already accepts
default_agentvia run-options. This change lets storyboard authors encode the topology intent in YAML once, rather than re-asserting--default-agent saleson every CI invocation. Cross-domain tools (sync_creatives,list_creative_formats,comply_test_controller) become deterministic without per-stepagent:overrides.Strictly additive and backward-compatible:
- Single-agent runs ignore the field (precedent:
requires_scenarios,controller_seeding). - Existing 3.0.x storyboards keep working unchanged.
- Pre-existing run-options
default_agentkeeps the lower-precedence fallback slot.
Resolution order (runner contract):
- Step-level
agent:override. - Unique specialism claimant in the runtime agents map.
- Storyboard-level
default_agent(this field). - Run-options
default_agent. - Fail-fast (
unrouted_step).
Mirrors the
provides_state_forprecedent (#3775) for adding optional storyboard-schema fields on 3.0.x — small, additive authoring affordances that adopters need today and that don't bind 3.0 wire shape. - Single-agent runs ignore the field (precedent:
v3.0.4
Patch Changes
-
78b1dc4: spec(errors): tighten
AUTH_REQUIREDprose to warn on retry storms (3.0.x prose-only backport of #3739)AUTH_REQUIREDconflates two operationally distinct cases — credentials missing (genuinely correctable) and credentials presented but rejected (terminal — needs human rotation). A buyer agent treating both ascorrectablewill retry-loop on revoked tokens, hammering seller SSO endpoints in a pattern indistinguishable from a brute-force probe.The 3.1 line splits this into
AUTH_MISSINGandAUTH_INVALID(#3739). 3.0.x cannot adopt the split — adding new enum values violates the maintenance line's semver rules. This change is the prose-only backport: the wire code staysAUTH_REQUIREDwithrecovery: correctable, but the description andenumMetadata.suggestionnow spell out the two sub-cases and the SHOULD-NOT-auto-retry rule for the rejected-credential case. SDKs running against 3.0.x sellers can apply the operational distinction at the application layer.Updates:
static/schemas/source/enums/error-code.json—enumDescriptions.AUTH_REQUIREDandenumMetadata.AUTH_REQUIRED.suggestionrewritten to call out both sub-cases and the retry-storm risk; cross-references the 3.1 split.docs/building/implementation/error-handling.mdx— adds anAUTH_REQUIRED sub-casescallout under the Authentication and Access table; updates the example switch to branch on whether credentials were attached.
Wire format unchanged. No new enum values. No recovery classification change at the structured level. Senders that already emit
AUTH_REQUIREDkeep working; receivers gain the documented sub-case discipline.Closes the 3.0.x portion of #3730. The full split lands in 3.1.0 via #3739.
-
78b1dc4: spec(error): standardize VALIDATION_ERROR
issues[]as a normative field oncore/error.jsonCloses #3059. Adds an optional top-level
issuesarray to the standard error envelope, normalizing what@adcp/client(and prospectivelyadcp-go/adcp-client-python/ hand-rolled sellers) already need for multi-field validation rejections.Why minor: new optional field on a published schema (
core/error.json). Existing senders/receivers stay conformant — the field is additive. Receivers that ignore unknown fields keep working; receivers that look for it gain a richer pointer map without parsingmessagetext.Shape: each entry is
{ pointer (RFC 6901), message, keyword, schemaPath? }.schemaPathMAY be omitted in production to avoid fingerprintingoneOfbranch selection on adversarial payloads.Backward compatibility with
field(singular): when both are present, sellers SHOULD setfieldtoissues[0].pointer. Pre-3.1 consumers reading onlyfieldget the first failure; 3.1+ consumers prefer the top-levelissues.details.issuesmirror: sellers MAY mirrorissues[]intodetails.issuesfor backward compat with consumers reading fromdetails. New consumers should prefer top-level.Updates:
static/schemas/source/core/error.json— addsissuesproperty with item shapedocs/building/implementation/error-handling.mdx— addsissuesto the error-envelope field table; clarifiesfield/issuesinteraction
-
78b1dc4: spec(manifest): publish
manifest.json+ structuredenumMetadatato stop SDK drift (adcp#3725) — 3.0.x backportHand-cherry-picked from #3738 onto 3.0.x. The original
enumMetadatablock onmainreferences three error codes (SCOPE_INSUFFICIENT,READ_ONLY_SCOPE,FIELD_NOT_PERMITTED) that don't exist in 3.0.x's enum; this version trims those entries so the structured metadata covers exactly the 45 codes 3.0.x ships. The build-time lint enforces that coverage invariant — there is no way to silently driftenumMetadataaway from the publishedenum.Patch-bump rationale: pure additive metadata block on a published schema, plus a new buildable artifact. No new wire fields, no enum value additions, no breaking changes for any conformant 3.0 agent.
Adds two additive artifacts to every released schema bundle:
enums/error-code.jsongains anenumMetadatablock. Every error code now carries structuredrecovery(correctable | transient | terminal) andsuggestionfields. SDKs MUST consume this block instead of parsingRecovery: Xprose out ofenumDescriptions. A build-time lint rejects any drift between the structured value and the prose. Root cause for adcp-client#1135 (17 missing codes, 3 wrong recovery classifications shipped in TS SDK for over a year).manifest.jsonat/schemas/{version}/manifest.json(and/schemas/latest/manifest.jsonfor nightly codegen). Single canonical artifact listing every tool (withprotocol,mutating,request_schema,response_schema,async_response_schemas,specialisms), every error code (withrecovery,description,suggestion), anerror_code_policyblock (definingdefault_unknown_recoveryso SDKs handle non-spec codes from non-conforming sellers correctly), and every storyboard specialism (withprotocol,entry_point_tools,exercised_tools). Validates against/schemas/{version}/manifest.schema.json. Generated deterministically from existing source — no new authored content. Lets SDKs derive their internal tool/error tables from one place at codegen time instead of hand-transcribing the spec.
mutatingis derived using the same classifier the idempotency-key lint enforces (single source of truth — manifest and lint can never disagree). The read-only verb pattern was tightened in the process: it now anchors at the start so tools likecreate-collection-listanddelete-property-listare no longer mis-classified as read-only because they happen to contain-list-mid-name.search-was added as a read-only verb.Specialisms expose two distinct tool sets per #3725 review feedback:
entry_point_tools(the curated minimal contract fromindex.yaml.required_tools— what the spec asserts implementers MUST ship) andexercised_tools(the full surface — union of own phases and every linked scenario, derived by walkingphases[].steps[].taskand resolvingrequires_scenarios). SDK authors should size their tool registration againstexercised_toolsto ensure they handle every call the conformance kit will make.Migration: SDKs targeting 3.0.x continue to work unchanged —
enumDescriptionsand the existingindex.jsonare retained verbatim. SDKs targeting 3.1+ should switch toenumMetadatafor error recovery andmanifest.jsonfor tool/specialism enumeration. The prose "Recovery: X" sentence embedded in eachenumDescriptionsvalue is stripped from the manifest's per-codedescriptionto avoid double-encoding; it remains inenumDescriptionsfor the human-readable narrative until a future minor formally deprecates it. Until then, the lint guarantees both surfaces stay synchronized. -
78b1dc4: spec(url-asset): add SHOULD on
url_type, role-based fallback, and mechanism-vs-purpose clarification (#2986 step 2)url_typewas optional with no fallback rule, so a conformant URL asset that omitted it left receivers guessing — buyers would either pick a default mechanism (with bad blast-radius if a clickthrough fired as a pixel) or refuse to render. Two parallel vocabularies (url-asset-typemechanism: 3 values;url-asset-requirements.rolepurpose: 6 values) compounded the confusion because the docs treated them as the same thing.This change:
- Adds a top-level description on
url-assetstating senders SHOULD includeurl_typeon every URL asset, and defining the receiver fallback: whenurl_typeis absent, receivers SHOULD fall back to the format'surl-asset-requirements.role(clickthrough/landing_page →clickthroughmechanism; *_tracker roles →tracker_pixel); when neither is present, receivers MAY reject rather than guess. - Updates the
url_typeproperty description to frame it explicitly as the receiver's invocation mechanism, and points at the role fallback for senders that omit it. - Updates
url-asset-requirements.roledescription to call out the mechanism-vs-purpose distinction (aclick_trackerslot validly accepts atracker_pixelURL). - Rewrites
docs/creative/asset-types.mdxURL Asset section, replacing the old "you only need to supply theurlvalue" guidance and the incorrect enum list (impression_tracker/video_tracker/landing_page— those were the requirement-siderolevalues, noturl_typevalues) with the actualclickthrough/tracker_pixel/tracker_scriptenum, the SHOULD note, and the role fallback table.
Wire format unchanged. Existing senders that already include
url_typeare unaffected. Senders that omiturl_typecontinue to validate but now have explicit receiver semantics; in 4.0 we plan to makeurl_typerequired (separate change). Closes step 2 of the rollout proposed on adcp#2986. - Adds a top-level description on
v3.0.3
Patch Changes
-
a83a2aa: docs(creative-channels): replace invalid
"url_type": "tracker"with"url_type": "tracker_pixel"in display, audio, carousels, and DOOH channel docs to match theurl-asset-type.jsonenum (clickthrough/tracker_pixel/tracker_script). Addresses adcp#2986 step 1 (3.0.x docs cleanup). Wire format unchanged — the published schema enum already excluded"tracker", so the channel docs were emitting an invalid value sellers could not validate against. -
dabd223: Add optional
provides_state_for: <step_id> | <step_id>[]field to the storyboard step schema, declaring that a stateful step's pass establishes equivalent state for the named peer step(s) in the same phase. Pairs with the cascade-skip mechanism in@adcp/sdk6.5.0+: when a peer step would otherwise grademissing_toolormissing_test_controller, the substitute waives the cascade and the runner grades the peer with skip reasonpeer_substituted(new inrunner-output-contract.yaml).Storyboard schema (
static/compliance/source/universal/storyboard-schema.yaml): documents the field next tocontributes_to, including the all-of array semantics, same-phase-only constraint, target-stateful / substitute-stateful requirement, and acyclic-peer-graph rule.Runner output contract (
static/compliance/source/universal/runner-output-contract.yaml): adds thepeer_substitutedskip reason toskip_result.reasonswith detail format"<this_step_id> state provided by <peer_phase_id>.<peer_step_id>". Kept distinct frompeer_branch_taken(branch-set routing) andnot_applicable(coverage gap).Specialism YAML (
static/compliance/source/specialisms/sales-social/index.yaml): declaresprovides_state_for: sync_accountson thelist_accountsstep inaccount_setup. Lets explicit-mode social platforms (Snap, Meta, TikTok) — which intentionally pre-provision advertiser accounts out-of-band and expose onlylist_accounts— graduate from1/9/0to9/10on thesales_socialstoryboard once the SDK cache refreshes against this version.Build-time validation (
scripts/lint-storyboard-provides-state-for.cjs,tests/lint-storyboard-provides-state-for.test.cjs): new lint rule wired intobuild-compliance.cjscovering shape, self-reference, unknown target, cross-phase reference, target-stateful, substitute-stateful, and direct-cycle violations. Source tree passes with the one new declaration above.Pure additive change; existing storyboards without the field keep their current cascade behavior. Backports to the 3.0.x line per #3734.
Closes #3734.
v3.0.2
Patch Changes
- 9dcf7aa: Add
envelope_field_presentcheck type to the storyboard schema and updatev3-envelope-integrity.yamlto use it for thestatuspresence assertion. The new check type walksprotocol-envelope.jsonrather than the step'sresponse_schema_ref, eliminating the static-analysisVERIFIER_UNREACHABLEgap in adcp-client's storyboard-drift verifier. Requires adcp-client#1045. - 9dcf7aa: Promote the shared asset-variant
oneOfunion to a canonicalcore/assets/asset-union.jsonschema. Bothcreative-asset.jsonandcreative-manifest.jsonnow reference this single file instead of inlining identicaloneOfarrays. This eliminates theVASTAsset1,DAASTAsset1,BriefAsset1, andCatalogAsset1codegen artifacts emitted byjson-schema-to-typescriptwhen the same union is encountered through multiple parent schemas. Wire format and validation semantics are unchanged.
v3.0.1
3.0.1 is a stable-surface no-op for 3.0-conformant agents. No changes required.
📖 Curated release notes: https://adcontextprotocol.org/docs/reference/release-notes#version-301
TL;DR
- Stable wire surface unchanged. No new fields, no renamed fields, no new enum values, no deprecations on stable schemas.
- Skills now bundle in
/protocol/3.0.1.tgz— the original driver. Re-cutting at 3.0.0 would have invalidated cosign attestations bound to the original 3.0.0 SHA-256. - Spec polish (no wire change):
acquire_rightsvalidation MUSTs (#2680, #2681),get_signalspagination precedence, URL canonicalization on brand.json agent URLs, v3 envelope integrity schema constraint. - Experimental surfaces (governance
mode, TMPseller_agent) gain small additive fields per the experimental-status contract. - Conformance harness gains
force_task_completionandseed_creative_formatscenarios — sandbox-only. - One docs-level deprecation:
get_signalstop-levelmax_results(still works in 3.x; removed in 4.0).
Adopter action
| Audience | Action |
|---|---|
| 3.0-conformant production agent | Nothing. |
| SDK consumer | Bump ADCP_VERSION from 3.0.0 to 3.0.1. |
| Governance / TMP implementer | Review the additive fields above. |
get_signals caller using top-level max_results |
Migrate to pagination.max_results. |
Detailed change list
See CHANGELOG.md § 3.0.1 for the per-PR detail (18 patch changes).
Verification
- Protocol tarball:
https://adcontextprotocol.org/protocol/3.0.1.tgz(2.15 MB, cosign-signed) - Schemas:
https://adcontextprotocol.org/schemas/3.0.1/ - Compliance:
https://adcontextprotocol.org/compliance/3.0.1/ - Docs snapshot:
https://adcontextprotocol.org/docs/3.0/now serves the 3.0.1 frozen content.
AdCP v3.0.0
AdCP 3.0 is the first stable release of the Ad Context Protocol. The headline change is a trust-surface overhaul: mandatory idempotency keys, RFC 9421 request signing, signed governance contexts, compliance-gated test vectors, and GDPR/EU AI Act invariants baked into the schema.
See Migration from rc.3, What's new in v3, or the full release notes.
Protocol tarball — 3.0.0.tgz below is signed with Sigstore cosign (keyless, bound to the Release workflow on main). To verify:
cosign verify-blob 3.0.0.tgz \
--certificate 3.0.0.tgz.crt \
--signature 3.0.0.tgz.sig \
--certificate-identity-regexp 'https://github.com/adcontextprotocol/adcp/' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com'Expected SHA-256: 04481e277089bebe551d3dc1294faab56aa876a7c08e0f010a8ca6ba41a06af4
See release notes for migration guidance, or prerelease upgrade notes for rc.3 adopters.
Breaking Changes — trust surface
-
43586d6, c1d2ff1: Require
idempotency_keyon all mutating requests; formalize seller declaration as discriminated oneOf (#2315, #2436, #2447). Every mutating task now requires anidempotency_keyin the request envelope, matching^[A-Za-z0-9_.:-]{16,255}$; AdCP Verified additionally requires a cryptographically-random UUID v4. Fresh key per logical operation; reuse only to retry a failed request with the identical payload.Sellers declare dedup semantics on
get_adcp_capabilitiesasadcp.idempotency = { supported: true, replay_ttl_seconds: <1h–7d, 24h recommended> }OR{ supported: false }. Whensupported: true, sellers respondreplayed: trueon exact replay,IDEMPOTENCY_CONFLICTwhen the same key accompanies a different payload, andIDEMPOTENCY_EXPIREDafter the declared TTL. Whensupported: false, sending anidempotency_keyis a no-op — the seller will NOT return conflict/expired errors, and a naive retry WILL double-process. Buyers must use natural-key checks (e.g.,get_media_buysbybuyer_ref) before retrying spend-committing operations against non-supporting sellers. Clients MUST NOT assume a default — a seller without this block is non-compliant.Since
supported: trueis a trust-bearing claim, buyers and conformance runners SHOULD probe by replaying with a deliberately-mutated payload — a conformant seller MUST returnIDEMPOTENCY_CONFLICT. Sellers declaringsupported: trueMUST pass this probe in the baseline compliance storyboard before the declaration is considered verified. -
aaace06: Model IO approval at the task layer, not as a media-buy status (#2270, #2351).
MediaBuy.pending_approvalis removed. Approvals are now modeled as explicit approval tasks with their own lifecycle, state, and audit trail — decoupled from the media-buy state machine. Enablessales-guaranteedsellers to implement human-in-the-loop approval without overloading media-buy status semantics. -
e6dd73a: GDPR Art 22 / EU AI Act Annex III enforced as JSON Schema invariants (#2310, #2338).
budget.authority_levelenum is removed and replaced by two orthogonal fields:budget.reallocation_threshold(number ≥ 0, orreallocation_unlimited: true) for budget autonomy, andplan.human_review_required(boolean) for per-decision review under Art 22. Cross-fieldif/thenrejectshuman_review_required: falsewhenpolicy_categoriescontainsfair_housing,fair_lending,fair_employment, orpharmaceutical_advertising, or when any resolved policy carriesrequires_human_review: true.revisionHistoryis append-only; downgradinghuman_review_requiredrequires ahuman_overrideartifact (≥20-char reason, email approver, 24h-freshapproved_at).eu_ai_act_annex_iiiseeded as a registry regulation.data_subject_contestationonbrand.json(and inline onbrand-ref.json) satisfies Art 22(3) discovery. -
ec06d47, 31aab3a: Specialism taxonomy finalized (#2332, #2336).
inventory-listsspecialism renamed toproperty-lists. Newcollection-listsspecialism split out as a sibling undergovernance. Account migration on specialism declarations complete — agents declare specialism ownership via the account surface.audience-syncalready reclassified fromgovernancetomedia-buyin #2300. -
84b322c: Rename compliance taxonomy
domains→protocols(#2300)./compliance/{version}/domains/becomes/compliance/{version}/protocols/.supported_protocolsvalue maps to compliance path via snake_case → kebab-case (e.g.media_buy→protocols/media-buy/).audience-syncreclassified fromgovernancetomedia-buyto match its tool family. Compliance runner path resolution, index.json structure, and catalog documentation all reflect the rename.
Breaking Changes
-
80ecf76: Simplify capabilities model for 3.0 (#2143). Remove redundant boolean gates — object presence is the signal. Make table-stakes fields required.
Removed fields:
media_buy.reporting(product-levelreporting_capabilitiesis source of truth)features.content_standards/features.audience_targeting/features.conversion_tracking(object presence replaces booleans)content_standards_detail→ renamed tocontent_standardsbrand.identity(implied by brand protocol)trusted_match.supported(object presence)targeting.device_platform/targeting.device_type(implied by media_buy)targeting.audience_include/targeting.audience_exclude(implied by audience_targeting)
Required fields:
reporting_capabilitieson every product (seeproduct.json)
-
a90700f: Revert geo capability flattening (#2157). Restore
geo_countriesandgeo_regions(booleans) andgeo_metrosandgeo_postal_areas(typed objects withadditionalProperties: false) as primary capability fields. Remove flat array alternatives (supported_geo_levels,supported_metro_systems,supported_postal_systems) introduced in #2143. -
95f1174: Media buy status lifecycle (#2034). Rename
pending_activation→pending_start. Addpending_creativesstatus for approved buys with no creatives assigned. Add top-levelcompliance_testing: { scenarios: [...] }capability block (not asupported_protocolsvalue) for declaringcomply_test_controllersupport. -
100b740: Move storyboards into the protocol as
/compliance/{version}/(#2176). Addspecialismsfield toget_adcp_capabilitieswith 21 specialisms across 6 domains (media-buy, creative, signals, governance, brand, sponsored_intelligence). Promotesponsored_intelligencefrom specialism to full protocol insupported_protocols. Renamebroadcast-platform→sales-broadcast-tv,social-platform→sales-social. Mergeproperty-governance+collection-governanceintoinventory-lists. Addstatus: previewmarker for 3.1 archetypes (sales-streaming-tv,sales-exchange,sales-retail-media,measurement-verification). Publish per-version protocol tarball at/protocol/{version}.tgzfor bulk sync. Newenums/specialism.jsonandenums/adcp-domain.json. -
07d82dd: Require
accountonupdate_media_buyfor governance and account resolution parity withcreate_media_buy(#2179). Flattenpreview_creativeunion schema into single object withrequest_typediscriminant. -
b674082: Add
GOVERNANCE_DENIEDto standard error codes with correctable recovery (#2194). Makesignal_idrequired onget-signals-responsesignal items. Addcontextandextfields to all request/response schemas (governance, collection, property, sponsored-intelligence, content-standards). -
60f2a9e: Generalize governance to all purchase types (#2014). Remove
media_buy_idfrom governance schemas —governance_contextis the sole lifecycle correlator. Addpurchase_typefield oncheck_governanceandreport_plan_outcome. Add budget allocations on plans for per-type budget partitioning. Audit logs group bygovernance_contextinstead ofmedia_buy_id.
Minor Changes — trust surface
-
9e1b0eb: RFC 9421 request signing profile (optional in 3.0, mandatory under AdCP Verified) (#2323). Agents MAY sign mutating requests using RFC 9421 HTTP Message Signatures with Ed25519 over a canonicalized covered-component list (including method, target URI,
content-digest, and protocol-level fields). Published test vectors (request-signing/positive/*,request-signing/negative/*) and a 15-step verification checklist (alg allowlist,keyidcap-before-crypto, JWKS resolution via SSRF-validated fetch, replay dedup viajti). sf-binary encoding pinned (#2341) and URL canonicalization tightened (#2343) so independent implementations produce bit-identical canonical inputs. Verifier guidance atdocs/building/implementation/security.mdx; test vectors atstatic/compliance/source/test-vectors/request-signing/. -
2e3ec71: Signed JWS
governance_context(#2316).governance_contextis a signed JWS produced by the governance agent and echoed by the buyer in the media-buy envelope. Sellers verify the signature using the governance agent's JWKS (resolved viasync_governance) and bind decisions to a specific buyer, plan, phase, and time. Replaces the opaque-string carrier from earlier 3.0 drafts. Enables sellers to reject stale or forged governance decisions without round-tripping to the governance agent. Fields:alg,typ,iss,sub,aud,phase,exp,iat,jti, plus governance-specific claims. -
f2918f4: Signed-requests runner harness contract (#2350, #2353). Compliance runner declares a
signed_requestsharness profile: given a seller endpoint and a signing keypair, the runner...
AdCP v3.0.0-rc.2
AdCP 3.0.0-rc.2
Second release candidate for AdCP v3.
Highlights
- Brand Protocol Rights Lifecycle:
get_rights,acquire_rights, andupdate_rightsfor brand licensing - Structured
visual_guidelinesonbrand.jsonfor generative creative systems - Shows and episodes as first-class content dimensions on products
ai_mediachannel for AI platform advertising- Property governance integration via optional
property_listfiltering - Campaign governance and policy registry:
sync_plans,check_governance,report_plan_outcome, andget_plan_audit_logsfor plan-level governance and shared policies - Simplified account model with
require_operator_authdetermining auth/account behavior
Breaking changes since rc.1
See the full release notes and v3 overview for migration details.
Schemas
Available in dist/schemas/3.0.0-rc.2/.
Full changelog: https://github.com/adcontextprotocol/adcp/blob/main/CHANGELOG.md
Release notes: https://docs.adcontextprotocol.org/docs/reference/release-notes#version-300-rc2
What's new in v3: https://docs.adcontextprotocol.org/docs/reference/whats-new-in-v3