# AdCP — Advertising Context Protocol

> What the Advertising Context Protocol (AdCP) is, what changed in 3.1, and how to implement it — domains, signals, governance, and a 3.0→3.1 checklist.

- Canonical: https://nofluffadvisory.com/standards/adcp/
- Standards last validated: 2026-09-17

---

*Standards & Protocols*

Reference

A practical guide to the open protocol layer for agentic advertising workflows: discovery, planning, buying, creative, signals, governance, accounts, and measurement.

AdCP gives advertising agents a shared task and schema layer. It helps buyers, sellers, platforms, data providers, and creative systems communicate through standardized advertising actions rather than bespoke dashboard workflows and one-off integrations.

*Figure: AdCP sits over MCP / A2A transport: a task layer above execution surfaces, with a governance rail.*

AdCP is not a replacement for OpenRTB, clean rooms, or human judgment. It is a protocol layer for making advertising work discoverable, executable, governable, and auditable by agents.

**Standard readiness (validate before build)**

- **AdCP 3.1** — GA · v3.1.23 · Sep 2026 [status: ga]
- **AdCP 3.2** — rc.3 · dev & staging only · Sep 14, 2026 [status: rc]
- **AdCP 3.0** — prior line · wire-compatible [status: ga]
- **v2** — deprecated Aug 1, 2026 [status: deprecating]
- **Sponsored Intelligence** — experimental [status: rc] 

Part of [AdCP on No Fluff Advisory](/adcp/) — the spec explainer

## Fast read

- **What it is:** An open agentic advertising protocol that defines domain-specific tasks and schemas for advertising agents.
- **What it does:** Helps agents discover inventory, set up accounts, buy media, manage creative, activate signals, apply governance, and report results through standardized calls.
- **What it is not:** Not a media exchange, identity graph, DSP, SSP, clean room, or replacement for OpenRTB.
- **Why it matters:** Agentic workflows need repeatable, machine-readable actions. Without a shared protocol, every agent has to learn every platform separately.
- **Current state:** AdCP 3.1 remains the general-availability line and the production recommendation; the latest stable tag is v3.1.23 (GitHub, September 14, 2026), whose #7406 backports the <code>required_tools</code> OR-gate fixes to 3.1.x: <code>canonical_format_validate_input</code> drops <code>comply_test_controller</code> (filed as #7404; #7405 on main), and four storyboards drop <code>get_adcp_capabilities</code> (the applicable subset of #6774). #7451 corrects the v3.1.22 release record to name the request-aware cache partitioning that shipped without changelog coverage. The 3.2 line is at v3.2.0-rc.3 (September 14, 2026), which the official versions page marks development and staging only — pin "3.2-rc.3" solely against peers that advertise it, and keep production on wire pin "3.1". The versions page still says no SDK embeds rc.3; that lapsed on September 15, 2026, when @adcp/sdk 14.0.0-rc.37 and Python adcp 8.0.0b15 both shipped declaring ADCP_VERSION 3.2.0-rc.3. Only Go adcp/v3.2.1 remains on rc.1. The docs are explicit that patch components are never sent. 3.1 is additive over 3.0 and supported patches do not change stable wire surfaces, so a 3.0 integration keeps working with no code change; v3.1.22 did change the explicitly experimental TMP contract, under the emergency exception to the normal notice process. v3.1.3 was withdrawn days after shipping (see the version-watch section below). Validate implementation details against current official docs.
- **Best next step:** Understand the domains, then decide which workflow your company should expose or consume first.

*Definition*

## What AdCP is.

AdCP is a shared advertising task layer for AI agents. It defines what agents can ask for, what systems should return, and how actions move through the advertising workflow.

| Layer | Job | Example |
| --- | --- | --- |
| Transport | Carries messages | `MCP / A2A` |
| AdCP | Defines advertising tasks and schemas | `get_products, create_media_buy, get_signals, activate_signal` |
| Execution system | Performs the action | `publisher, SSP, DSP, creative system, data provider` |
| Governance | Controls authority and audit | `approvals, signatures, idempotency, audit logs` |
| Existing ad standards | Power underlying objects and transactions | `OpenRTB, AdCOM, OpenDirect, Deals API` |

*Rationale*

## Why AdCP exists.

- **Fragmented workflows** — Media buying, creative, data activation, accounts, and reporting still live across disconnected systems and dashboards.
- **Agents need actions, not screens** — An agent cannot scale by clicking through every platform UI. It needs task-level interfaces.
- **Common schemas reduce ambiguity** — Natural-language briefs need to resolve into structured, auditable requests.
- **Human oversight needs architecture** — Agentic buying requires approvals, limits, audit logs, and accountability built into the flow.
- **Platform participation needs standards** — Publishers, data providers, creative systems, and ad platforms need a shared way to expose what agents are allowed to do.

*Version watch*

## What’s new in 3.1 — and what 3.2 changes.

AdCP 3.1 is now the current general-availability line (source: AdCP — GitHub tags v3.1.0 (June 18, 2026) through v3.1.23 (September 14, 2026), with v3.1.3 (July 13) withdrawn days later for a versioning-contract violation (PR #5887); v3.2.0-rc.3 published September 14, 2026 as a prerelease that docs/reference/versions.mdx restricts to development and staging; per-patch detail from the repo CHANGELOG.md, since every release body is version-only) (latest stable tag v3.1.23, with the 3.2 line now at rc.3 for development and staging only), additive over 3.0. The 3.2 line has been in release candidate since September 3, 2026 and moved three times in eleven days, most recently to v3.2.0-rc.3 on September 14 — which the official versions page restricts to development and staging. Separate what shipped from the obligations adoption brings from what 3.2 is about to change.

**(GA · v3.1.23 — additive over 3.0 · next line at v3.2.0-rc.3)**

**Confirmed — AdCP 3.1 (GA · v3.1.23):**

- AdCP 3.1 is the current general-availability line — GA at GitHub tag v3.1.0 (June 18, 2026), patched through v3.1.2 (June 30 – July 8, 2026; protocol-only fixes and spec clarifications). v3.1.3 (July 13) was withdrawn days later — official notice: it added a stable protocol schema field in a patch release, violating the 3.1.x versioning contract, plus a publisher-domain filter bug accepting a plural selector shape the schema rejects; the docs still route implementers around it to v3.1.2. Patches then ran from v3.1.4 (July 19) to v3.1.23 (September 14, 2026, the latest stable tag). v3.1.21 (September 9) was a single change, #7384 (the 3.1.x backport of #7383): guaranteed idempotency replay scoped to state-mutating requests, an optional idempotency_key on the get_products request schema, read wrappers tolerating the key without claiming read replay, and the read-tool-idempotency storyboard relaxed to match — withdrawing the 3.1-era plan to make reads reject a missing key at 3.2. The v3.1.22 changelog lists two: legacy format asset declarations aligned with the canonical asset union, guarding individual and repeatable-group variants against drift (#7423), and a Trusted Match privacy correction restricting Context Match embeddings derived from non-public single-user content while requiring privacy reduction for free-form context signals (#7424 — the 3.1.x backport of #7396, which this site’s author filed as #7393). Treat that changelog as accurate but not complete: the tag also carries #7425 (commit 251df51), which backports the request-aware cache partitioning from #7397 to 3.1.x and carried no changeset, so the changelog has no line for it. #7451 merged on September 13, 2026 to correct the v3.1.22 record, and it landed the next day in v3.1.23 as commit 8a933df. Every 3.1.x release body on GitHub except the withdrawn v3.1.3’s is version-only — literally the string "AdCP 3.1.20" — so per-patch detail lives in the repo changelog, not the release notes. The 3.2 line is now at v3.2.0-rc.3 (September 14, 2026), the current signed protocol checkpoint, restricted to development and staging. The SDKs caught up within a day: @adcp/sdk 14.0.0-rc.37 (September 15, 02:39Z) and its successor rc.38 declare ADCP_VERSION 3.2.0-rc.3 and bundle the rc.3 compliance cache and schemas, Python adcp 8.0.0b15 (02:33Z the same morning) ships ADCP_VERSION 3.2.0-rc.3, and only Go adcp/v3.2.1 still embeds rc.1. The versions page on main still names TypeScript RC.35, Python beta.14 and Go 3.2.1 as all embedding rc.1 and says no SDK embeds rc.3 — held there on purpose rather than merely stale: with Go on rc.1 there is no pin common to all three SDKs, so the maintainers are waiting to align the doc once against rc.3 instead of twice, and the Go catch-up is tracked in adcp-go#536. The rendered docs site has published no rc.3 snapshot at all. The wire-negotiation pin is the string "3.1"; SDKs normalize "3.1.x" → "3.1", and the docs forbid sending patch components. v2 is fully deprecated on August 1, 2026 (UTC).
- Additive over 3.0 at the wire level: no required field was removed and no shape broke, so a 3.0-conformant integration keeps working with no code change.
- A production-hardening release: release-precision version negotiation (supported_versions[]), distributed and cryptographically signed brand trust (self-published brand.json + signed verify_brand_claim), canonical creative formats plus a transformers catalog, and vendor-attested measurement goals.
- Operational guarantees: idempotency_key required on every state-mutating request (v3.1.21 walked back the every-request rule — reads keep the key optional and wrappers must tolerate it); dependency-impact / media-buy health signals, buyer-side webhook observability, and reporting finality + reach-window semantics.
- Feature detail is sourced from the official "What’s New in 3.1" and 3.0→3.1 migration docs plus the SDK notes — the GitHub release records only the version and date.

**Obligations when you claim 3.1:**

- Advertise supported_versions in get_adcp_capabilities and echo the served version at the envelope root; transports must tolerate unknown envelope-root fields.
- Brand agents implementing verify_brand_claim(s) must return a signed (JWS) response.
- Move creative metadata to canonical format_kind + list_transformers, and pass the 3.1 compliance storyboard bundle to earn the 3.1 badge.
- Schema tightening can surface as errors: trademarks[].status is now a typed enum and trademarks[].countries must be ISO 3166-1 alpha-2 (former free-text values fail); cache_scope is schema-required on get_products / get_signals.
- Authentication hardens: RFC 9421 request signing — recommended in 3.0 — becomes REQUIRED for mutating and financial operations in 3.1+, with static bearer/Basic credentials prohibited there (still permitted for read/discovery). Until you land on 3.1, bearer-over-TLS remains the effective floor for spend operations — the spec says to ship 9421 ahead of the cutover.
- The Go SDK (adcp-go) has breaking type changes — plan the upgrade; it is not a drop-in.

**In release candidate — AdCP 3.2 (v3.2.0-rc.3):**

- The 3.2 line has been in release candidate since September 3, 2026 and moved three times in eleven days — rc.1 on September 5, rc.2 on September 13, rc.3 on September 14. The docs call rc.3 the current signed protocol checkpoint and restrict it to development and staging — pin "3.2-rc.3" only against peers that advertise it and keep production on wire pin "3.1". The SDKs caught up on September 15: @adcp/sdk 14.0.0-rc.37 and rc.38 declare ADCP_VERSION 3.2.0-rc.3, Python adcp 8.0.0b15 embeds it too, and only Go adcp/v3.2.1 still embeds rc.1. The versions page has not, and says so on purpose: with Go still on rc.1 there is no pin common to all three SDKs, so it aligns once when Go lands (adcp-go#536).
- Reliable Reporting becomes a discoverable capability rather than an assumption: a seller advertises it, so a buyer can tell before spending whether the reporting contract is one it can hold the seller to.
- Vendor measurement gets a closed vendor_relationship enum — first_party / affiliated / third_party — so a seller has to declare when it is its own measurement vendor. Absence means undeclared, not independent.
- Delivery and reach semantics tighten: cross-buy delivery aggregates are deprecated in favour of media-buy-level currency, and deduplicated cross-buy reach is disambiguated from summed reach so the two stop being reported as the same number.
- The scheduled removal lands here — legacy top-level media-buy status moves to media_buy_status — and typed validation and precedence for pixel-ratio registry metadata begins in 3.2, where 3.1 SDKs only preserve it.

**Watch next (4.0 and beyond):**

- A 4.0 deprecation set: Format.pricing_options, legacy SignalId / flat signal targeting, inline brands[], data_provider_signals.
- Flagged experimental in 3.1, not yet stable: the measurement-vendor catalog (measurement.core) and the responsive_creative / sponsored_placement / agent_placement format kinds.
- A proposed pre-GA rename of body-level status discriminators (e.g. check_governance) was discussed (#4897) but is unconfirmed in the final tag — validate before relying on it.
- AdCP Verified independent auditing, signals-protocol maturity, registry adoption, SDKs, and reference implementations.

### Migrating 3.0 → 3.1 — the checklist

A 3.0 integration keeps working untouched — 3.1 is additive at the wire. “Migrating” means *claiming* 3.1, and each step below is a real obligation (per the 3.0→3.1 migration guide (source: AdCP official 3.0→3.1 migration guide + adcp-go SDK release notes)), not optional polish. Backward compatibility is “mostly”: 3.0 clients are not broken, but adoption plus the Go SDK upgrade impose real changes — plan it.

- **Advertise versions —** Return supported_versions[] from get_adcp_capabilities and echo the served version at the envelope root; make transports tolerate unknown envelope-root fields (this replaces prior reject-on-unknown validation).
- **Sign brand verification —** If you implement verify_brand_claim(s), return a signed (JWS) response bound to the task, resolved tenant, agent URL, and freshness window.
- **Adopt canonical creative —** Move creative metadata to the canonical format_kind set and discover build units through the new list_transformers catalog; format-attached pricing moves to the transformer.
- **Fix typed fields —** trademarks[].status must be a typed enum and trademarks[].countries ISO 3166-1 alpha-2 — former free-text values now error; add the now-required cache_scope on get_products and get_signals.
- **Require idempotency —** Send idempotency_key on every state-mutating request (sellers may reject missing keys there; reads keep it optional as of v3.1.21); treat IDEMPOTENCY_IN_FLIGHT as transient rather than minting a fresh key.
- **Upgrade the SDK, then certify —** The Go SDK (adcp-go) has breaking type changes — re-decode against the new shapes; it is not a drop-in. Then pass the 3.1 compliance storyboard bundle to earn the 3.1 badge.

*From the implementer seat*

## Contributions to the protocol.

This page is written from inside the work: No Fluff Advisory builds and operates a [live AdCP signals agent](https://nofluffadvisory.com/building/adcp-signals-adaptor/) (listed in the AAO registry) with all-pass conformance runs across the AdCP 3.0 and 3.1 GA suites (57/57 scenarios on the current 3.1.20 line), and co-leads the Signals & Measurement working group. For the live state of the registry itself — every registered agent, its actual tool catalog, and real request/response captures — see the [AdCP Ecosystem Tracker](https://nofluffadvisory.com/adcp-registry/). For the buy side of the same protocol run end to end — discovery, audience targeting, brief, media buy, creatives, the human gate, delivery reporting — with every call copy-pasteable against a live seller agent, see the [AdCP Buyer’s Guide](https://nofluffadvisory.com/adcp-buyers-guide/).

### Merged into the protocol & tooling

- **last_updated on signal-definition** — schema field for verifiable signal-record freshness ([#5248](https://github.com/adcontextprotocol/adcp/issues/5248) → [PR #5249](https://github.com/adcontextprotocol/adcp/pull/5249), in the 3.1.0 line since rc.7).
- **Root-cause diagnostics for the conformance runner** — a schema-invalid `get_adcp_capabilities` response used to surface as N unrelated track failures with nothing linking them; reported it ([#6254](https://github.com/adcontextprotocol/adcp/issues/6254)) and wrote the protocol-side contract, which now defines the `capabilities_response_schema_invalid` notice and an RFC 6901 `capability_pointer` field so one cause is reported once, ahead of the results it explains ([PR #6256](https://github.com/adcontextprotocol/adcp/pull/6256), merged August 8, 2026).
- **Runtime signal-quality attestations** — our RFC for verifier-signed signal-quality evidence on check_governance ([#5418](https://github.com/adcontextprotocol/adcp/issues/5418)) landed in the protocol's 3.2 line: `runtime_attestations[]` consuming the shared attestation primitive ([#4529](https://github.com/adcontextprotocol/adcp/issues/4529)), scoped to signal activation with GDPR/CCPA deactivation exempt, with response-side evaluations and binding digests ([PR #6218](https://github.com/adcontextprotocol/adcp/pull/6218), merged August 6, 2026).
- **Compliance-grader fix** — all-pass single-protocol runs rendered “Degraded” by a rollup regression; root-caused to the introducing commit, filed ([#5429](https://github.com/adcontextprotocol/adcp/issues/5429), triaged P0) and fixed ([PR #5444](https://github.com/adcontextprotocol/adcp/pull/5444), merged).
- **RFC 9421 webhook-signing default** — the inventory ([#4270](https://github.com/adcontextprotocol/adcp/issues/4270)) and draft PRs ([#4273](https://github.com/adcontextprotocol/adcp/pull/4273)/ [#4275](https://github.com/adcontextprotocol/adcp/pull/4275), closed in favor of the triage-generated PR the maintainer merged) that drove the 3.0.9 realignment away from the deprecated HMAC framing. The migration tracker ([#4205](https://github.com/adcontextprotocol/adcp/issues/4205)) closed completed on August 13, 2026: reframed as an on-ramp problem rather than an adoption threshold, with the docs and signing guide leading with RFC 9421 and no separate DRI left to assign.
- **A dense vector on the rung that means “don’t share the content”** — `context_signals.embedding` is the one field on Trusted Match's classified-output tier that can be partially inverted back to a user's own words, and on an `ai_assistant` property the “content environment” is one person's conversation turn. Filed against v3.1.21 with the inversion literature and two additive text edits ([#7393](https://github.com/adcontextprotocol/adcp/issues/7393)); shipped in [#7396](https://github.com/adcontextprotocol/adcp/pull/7396), which took the stricter route — a flat prohibition rather than the demonstrate-on-request carve-out I proposed — and added policy-filtering rules on `keywords` and `summary` that the issue had not asked for.
- **Context Match over-caching** — split out of the embedding issue at the triage's request, since it carried no privacy dependency: the recommended cache key was placement-only while responses vary with artifact, classified signals and geo, so a router could serve one session's decision against another's context ([#7414](https://github.com/adcontextprotocol/adcp/issues/7414)). The collision was fixed in [#7397](https://github.com/adcontextprotocol/adcp/pull/7397), which replaced the key with `{provider_id, context_hash}`, a SHA-256 over the forwarded request minus `$schema` and `request_id`. That PR was not a response to #7414. It closes [#7395](https://github.com/adcontextprotocol/adcp/issues/7395), which was filed under the maintainer’s account from the same #7393 review. Both were opened on September 10, 2026, more than 18 hours before I filed #7414. A bot-triage note marked #7414 blocked on #7397 four minutes after I filed it, and the issue was closed as not planned on September 13 with no comment. The `cache_ttl: 0` line did ship, by another route: the #7395 bot triage listed it, my September 10 review of #7397 flagged it as missing, and it was added on September 11. It went in as a hit-rate note (geo or per-session signals produce many distinct hashes), not the correctness SHOULD #7414 proposed, and the 3.1.x backport ([#7425](https://github.com/adcontextprotocol/adcp/pull/7425)) carried the same sentence into v3.1.22. The docs release-notes page goes further. Its Version 3.1.22 section, added by #7451 and first tagged in v3.1.23 (September 14, 2026), says Context Match router operators “affected by unsafe response caching MUST bypass or disable that caching until the router implements both request-aware partitioning and a trusted namespace for every result-affecting security and provider-configuration context.” Main [#7446](https://github.com/adcontextprotocol/adcp/pull/7446) would add that namespace as `cache_namespace`, 3.2-only, with October 25, 2026 as the earliest date its enforcement can publish, and is still open as of September 16, 2026.
- **Radio & static-OOH measurement parity** — scoped the two channels the delivery contract had no shape for ([#6138](https://github.com/adcontextprotocol/adcp/issues/6138), with Chris Williams), then filed the asks that came out of it: radio delivery-currency, meaning row-level `measurement_source` plus `nielsen_audio` notation ([#6139](https://github.com/adcontextprotocol/adcp/issues/6139)), and spot-level as-run for linear ([#5682](https://github.com/adcontextprotocol/adcp/issues/5682)). Every ratified decision is merged — `measurement_source` on delivery rows ([PR #6241](https://github.com/adcontextprotocol/adcp/pull/6241)), `nielsen_audio` with notation-vs-provider language and the radio reconciliation guide ([PR #6836](https://github.com/adcontextprotocol/adcp/pull/6836), field-name correction [PR #6856](https://github.com/adcontextprotocol/adcp/pull/6856)), reporting cadence extended to measured channels and then promoted to a normative MUST ([PR #6240](https://github.com/adcontextprotocol/adcp/pull/6240), [PR #6860](https://github.com/adcontextprotocol/adcp/pull/6860)), and spot-level as-run reporting ([PR #6574](https://github.com/adcontextprotocol/adcp/pull/6574)). Taxonomy graduation criteria split out to [#6261](https://github.com/adcontextprotocol/adcp/issues/6261) and closed when media channels went stable ([PR #6542](https://github.com/adcontextprotocol/adcp/pull/6542)). Implementations were maintainer-authored.

### Conformance suite, hardened

- Signals-only agents now skip non-applicable media-buy gating and gained dedicated error-handling / schema-validation storyboards ([#2916](https://github.com/adcontextprotocol/adcp/issues/2916), [#3350](https://github.com/adcontextprotocol/adcp/issues/3350), [#4009](https://github.com/adcontextprotocol/adcp/issues/4009) — fixed in the 3.1.0 suite; earlier [#2535](https://github.com/adcontextprotocol/adcp/issues/2535), [#3999](https://github.com/adcontextprotocol/adcp/issues/3999), [#4065](https://github.com/adcontextprotocol/adcp/issues/4065)).
- **An assertion no signals-only agent can satisfy** — `webhook_emission` 's synthetic `assert_contribution` step grades a branch set whose only contributors require `get_products`; a signals-only agent's contributors correctly skip as `missing_tool`, and the assertion then fails on the empty set as a `[core]` failure nothing on the agent side can clear. The storyboard's own `grading.pass_criteria` says those steps grade not-applicable, and a sibling storyboard already guards its assertion phase with `skip_if` ([adcp-client#2862](https://github.com/adcontextprotocol/adcp-client/issues/2862), filed with the runner's machine-readable failure record — `expected: [synchronous_completion_handled], actual: []` — as the reproduction). Fixed September 14, 2026 in [#7504](https://github.com/adcontextprotocol/adcp/pull/7504), which gated all three phases of the synchronous webhook-emission branch family on `media_buy.buying_modes` carrying `wholesale` and added a regression asserting that a signals-only agent grades the whole branch family `not_applicable` — the grading contract the filing argued from. Note where it landed: the runner's `assert_contribution` behaviour is preserved and the storyboard was gated instead, so the fix rides the spec repo rather than the SDK.
- **Reviewed with wire data** — the signal-definition epistemic / provenance layer ([#5017](https://github.com/adcontextprotocol/adcp/pull/5017), opened under the maintainer account): backed a progressive-disclosure concern that another reviewer had already raised, with three things: wire sizes from our signals agent (88,590 bytes for 5 signals against the 64 KB probe ceiling, pretty-printed — an estimated 60 KB compact — and carrying our own `x_*` extension blocks, most of each signal’s bytes by our posted breakdown, but none of #5017’s new fields), an estimate that those fields would add 3–5 KB per signal, and three ways to split discovery from lookup. Before the merge, the maintainer account added compact-by-default guidance and a `fields` selector on `get_signals`. Our field-level schema notes followed about an hour after the merge; the follow-up ([#5190](https://github.com/adcontextprotocol/adcp/pull/5190), merged May 30, 2026) addressed them, not always as proposed. Neither the pre-merge commits nor #5190 cites our comments, though the maintainer account introduced the selector commit as a follow-up “based on the progressive-disclosure discussion”, which our comment was part of.
- **A shared reference primitive that stayed a draft** — the signal epistemic-model RFC, opened under the maintainer account ([#4616](https://github.com/adcontextprotocol/adcp/issues/4616)), listed three decisions for the working group to make once. The first: should one reference primitive be reused across markets, ID graphs, taxonomies, measurement currencies and panel frames, or should each get its own per-dimension type? I filed a draft PR for the shared option, described in its own text as a discussion artifact rather than a merge bid. It proposed one `{system, value, version?, name?}` reference for values defined in external identity, taxonomy, geographic and measurement systems, plus a per-deployment fidelity enum and a conversion descriptor ([#4622](https://github.com/adcontextprotocol/adcp/pull/4622), opened May 16, 2026). One reviewer approved its second revision round the same day, after I folded in their suggestions; five more rounds followed. Review comments under the maintainer account on May 25, 2026 questioned the premise: calling these “systems” is confusing, “Not clear to me how this generalized system helps us”, and the conversion is not per-signal but happens at activation, across graphs held by several parties, with no one knowing how many times. One comment’s stated main point was to separate “what is this signal” from how it is connected to the delivery surface. The same day I narrowed the descriptions in a seventh round and offered to drop the conversion descriptor, or to close the PR if the rows it targeted turned out to need one dominant system each. The next comment under the maintainer account was the closing one, on May 30, 2026. It called the PR a discussion artifact rather than a merge candidate, said the system-reference idea “remains relevant” for concrete row-level work and should come back as a fresh, narrow PR once one of those rows is ready to adopt it, and said it “was not closed by #5017”, which had handled signal-definition enrichment without adopting these primitives. It was never merged, and none of its three schemas is on `main` as of September 16, 2026. Separately, on May 28 and 29, I had written on #5017 that “the per-dimension shape vs. shared-primitive question is resolved” and that its per-dimension direction was “the right one”. #4616 was closed on August 16, 2026 as completed, with a comment calling it superseded framing and saying the actionable signal epistemic decisions are now owned by concrete signal RFCs and implementation issues. Its text has marked the third decision “decided for 3.2” since August 4, 2026, and has never marked the reference-shape question decided.
- **Wholesale cache-scope isolation** — found that conditional-fetch tokens pass the suite even when a global token leaks across `cache_scope` layers; filed ([#5739](https://github.com/adcontextprotocol/adcp/issues/5739), bot-triaged ready-to-implement and milestoned 3.2.0) and implemented the fix — scope-isolation storyboards for signals and products, the schema MUST-NOTs, and the reference-agent correction ([PR #5748](https://github.com/adcontextprotocol/adcp/pull/5748), merged August 3, 2026).
- **Grader reliability** — evaluate_agent_quality returning identical scores across four runs including a force_refresh pass; filed with live wire evidence ([#6206](https://github.com/adcontextprotocol/adcp/issues/6206), bot-triaged same day: the silently-dropped `force_refresh` parameter confirmed as a real grader bug; the score-staleness root cause resolved agent-side, follow-up scoping in [#6233](https://github.com/adcontextprotocol/adcp/issues/6233)).
- **Storyboard-runner account resolution** — advertising `list_accounts` silently switches the runner into discovery mode, which then hard-fails as “ambiguous” on any multi-tenant roster instead of falling back to the natural-key path that exists a few lines above ([#6242](https://github.com/adcontextprotocol/adcp/issues/6242), triaged P0 and fixed — schema-default account routing and agency-operated brand matching shipped in `@adcp/sdk` 13.0.0-rc.11 via [adcp-client#2488](https://github.com/adcontextprotocol/adcp-client/issues/2488), with runner guidance in [#6289](https://github.com/adcontextprotocol/adcp/issues/6289); two implementers hit it independently), and the amplification pattern behind it — one schema-invalid capabilities response surfacing as N unrelated track failures ([#6254](https://github.com/adcontextprotocol/adcp/issues/6254); I first filed the link between the two as a separate issue by mistake, [#6255](https://github.com/adcontextprotocol/adcp/issues/6255), and closed it 98 seconds later on August 6, 2026 in favour of [a comment on #6242](https://github.com/adcontextprotocol/adcp/issues/6242#issuecomment-5209202619)).
- **3.1.11 harness regression** — the dynamic creative-asset directive shipped without its expansion step ordered ahead of the runner's own outbound validation, so conformant sellers were graded down on requests their agents never received ([#6267](https://github.com/adcontextprotocol/adcp/issues/6267), fixed; the affected track returned to a full pass on the first post-deploy regrade). Filed alongside the contract gap behind it — unbuildable asset slots were charged to the agent, and the storyboard contract contradicted itself on whether to fail the step or skip it — which resolved in the seller's favour: runner-owned coverage gaps now grade not-applicable rather than counting as failures, with the fixture set widened and slot-content guessing prohibited ([#6269](https://github.com/adcontextprotocol/adcp/issues/6269), fixed). Registry card rendering a stale tool count fixed alongside ([#6268](https://github.com/adcontextprotocol/adcp/issues/6268)).
- **Compliance reporting that hides its own verdict** — the badge is gated on storyboard-level results, but the API returned the summary count with an empty breakdown ([#6291](https://github.com/adcontextprotocol/adcp/issues/6291)) and a track could display every scenario passing while the verdict that actually gates the badge disagreed ([#6292](https://github.com/adcontextprotocol/adcp/issues/6292)) — both fixed and shipped together. Found while diagnosing why a live agent sat at 132/138 scenarios and no badge. Once the breakdown shipped it showed the card reporting a declared specialism as *failing* while the underlying record read untested with zero steps attempted and zero failures ([#6302](https://github.com/adcontextprotocol/adcp/issues/6302)) — a storyboard that had never run once being displayed as one that ran and failed.
- **A badge panel that names the wrong blocker** — the AAO Verified panel tells a seller to “fix the failing storyboards in this card” over a record reading 13 passing, 4 partial, 18 untested, and zero failing: every non-passing state renders as “failing” ([#6363](https://github.com/adcontextprotocol/adcp/issues/6363), bot-triaged as a classification bug, then fixed by a maintainer PR — the panel now names the actual blocking state).
- **Registry-migration QA — five filings in one morning** — probing the agenticadvertising.org migration surfaced: verified media-buy agents rendering “Not Verified” badges ([#6376](https://github.com/adcontextprotocol/adcp/issues/6376) — our hyphen/underscore hypothesis was superseded by the bot triage citing migration 502, which does bulk-revoke every 3.1 badge pending GA — the real cause, a migration that bulk-revoked every 3.1 badge pending GA); an unstructured badge-role error and an OpenAPI description still advertising roles that don’t exist, `sales` included ([#6377](https://github.com/adcontextprotocol/adcp/issues/6377), corrected mid-flight — the 400 does carry a body; our first probe read only the status code); the 200-plus-grey embed contract for unverified agents ([#6378](https://github.com/adcontextprotocol/adcp/issues/6378), resolved documented-intentional, with the `onerror` embed pattern to be deprecated in favour of the gate-on-verification pattern this site already ships); the hosted grader still running a superseded spec line hours after release — the operational sibling of #6321 ([#6379](https://github.com/adcontextprotocol/adcp/issues/6379)); and the CLI producing silent mixed-line runs, kit from 3.1.13 while storyboards resolve from bundled 3.1.11 with no consistency check ([#6380](https://github.com/adcontextprotocol/adcp/issues/6380), reproduced as a two-run diff that cost a full grading pass). A sixth followed the same afternoon when a requeue ran the 3.0.18 cache against this 3.1-only agent and flipped the public card to failing before any scenario executed: sellers migrating 3.0 → 3.1 have no self-serve way to update the compliance target, with the proposed fix of resolving it from advertised `supported_versions` on every health check ([#6383](https://github.com/adcontextprotocol/adcp/issues/6383)). All six closed within a day: the badge trio via [PR #6387](https://github.com/adcontextprotocol/adcp/pull/6387), the grader deployment after a version-manifest root-cause (#6379), the mixed-line CLI defect with a fail-closed line-inference fix ([adcp-client#2518](https://github.com/adcontextprotocol/adcp-client/pull/2518)), and the compliance-target trap with owner re-detection plus registry safeguards that refuse verdicts against untrusted fallback targets (#6422/#6426, closing #6383).
- **One runner deployment, six defects — attributed by controlled experiment** — a grader failure that would not reproduce locally was run to ground with a differential wire test: the same `get_products` call against the same database in the same minute returns the correct USD-pruned result with `filters.pricing_currencies` present and reproduces the grader's failure byte for byte without it, so the deployed runner is dropping the filter ([#6439](https://github.com/adcontextprotocol/adcp/issues/6439), carrying the runner-half question #6379's closure left open). The same stripping family surfaced `brand` sent on `list_accounts` while the published request schema defines no such field — the registry noticing agents for omitting a field the spec never told them exists ([#6437](https://github.com/adcontextprotocol/adcp/issues/6437)) — and the SDK validating capabilities against a 3.1.0-beta.7 enum that rejects scenario names its own 3.1.13 storyboards gate on ([adcp-client#2524](https://github.com/adcontextprotocol/adcp-client/issues/2524)). A dropped `sandbox` flag rounded out the family: the same account identity hashed to a second, configless account, root-caused by recomputing the tenancy-triple hash for field-subset variants and closed agent-side by seeding the triple from the resolved principal. Four runner defects, one deliberate decline, zero unattributed failures on the card.
- **SDK test-fixture bug** — the @adcp/sdk scenario suite's sync_creatives fixture fails the SDK's own request validation ([adcp-client#2443](https://github.com/adcontextprotocol/adcp-client/issues/2443), bot-triaged with a corrected fix and regression-test ask, both shipped in adcp-client#2463/#2473; blast radius scoped to the local scenario suite in [#6233](https://github.com/adcontextprotocol/adcp/issues/6233)).
- **Conformance steps no seller can pass** — three findings from taking one live agent from 147 to 240 passing steps. The storyboards mark validations `severity: advisory` and the spec says an advisory failure does not fail the step, but the runner implements none of that contract, so every validation on the stale-cache step is advisory and the step is unpassable by construction ([#6320](https://github.com/adcontextprotocol/adcp/issues/6320), triaged P0); a second instance of the same skip-graded-as-failure pattern turns up in the idempotency rate-limit step, which is doubly unreachable because its test kit is sandbox-scoped while the graded URL is production ([#6344](https://github.com/adcontextprotocol/adcp/issues/6344)). And a seller who declares `supported_billing: ['operator']` is asked for an error code that means the opposite of what is true — `BILLING_NOT_PERMITTED_FOR_AGENT` implies the mode exists and this agent may not use it, where the honest answer is that the mode is not offered at all ([#6343](https://github.com/adcontextprotocol/adcp/issues/6343)) — the same shape as the specialism gap below.
- **Grades sellers cannot reproduce** — the hosted grader ran compliance cache `3.1.12` while no published SDK carried it: `latest` shipped 3.1.5, the release candidate 3.1.11, and a step that passed locally failed on the grader with no way to see the storyboard that failed it ([#6321](https://github.com/adcontextprotocol/adcp/issues/6321), triaged P0; the merged fix gated the version resolver on published bundles). Found alongside a registry state machine that locks honest sellers out of grading entirely: a completed run rewrites the requested compliance target to whatever it just ran, so an agent that narrows its advertised `supported_versions` to the one version it actually supports then fails pre-flight against the older cache and is graded on nothing at all. Narrowing was the honest move and it took the public card from *degraded* to *failing*.
- **A storyboard that fails the path the spec prescribes** — a seller with no task layer is told by the spec to allocate the media buy id at commit and return synchronous success with `confirmed_at: null`, then the async storyboard grades that seller on a submitted-task envelope it was never meant to emit ([#6345](https://github.com/adcontextprotocol/adcp/issues/6345)). Triage first assumed omitting the controller scenario made the storyboard grade not-applicable; a live reproduction showed the force step grades not-applicable while the dependent step runs anyway and fails. Fixed: the storyboard now gates on the forcing scenario's advertisement and skips before any phase executes ([PR #6368](https://github.com/adcontextprotocol/adcp/pull/6368), merged), with the skip-misclassification the review surfaced corrected downstream in the SDK ([adcp-client#2511](https://github.com/adcontextprotocol/adcp-client/issues/2511)).
- **One filing withdrawn** — an argument that the audit-observation contract forced sellers to relay a verifier's verdict they never obtained ([#6322](https://github.com/adcontextprotocol/adcp/issues/6322)). The premise was wrong: the schema already separates the two, carrying what a submission *claimed* in one field and what a verifier *observed* in others, and the only permitted code says `CLAIMED`. Retracted with the correct reading ([#6323](https://github.com/adcontextprotocol/adcp/issues/6323)) and the feature built the honest way instead — recording the claim, attributing the observation to this agent, and leaving every verdict field empty.
- **53 of 62 failing steps on two public cards were ungradable** — the hosted grader admits a storyboard when *any* one of its `required_tools` is present, while the suite selector then required all of them, so `canonical_format_validate_input` was selected for agents with no `validate_input` and failed all 17 of its steps on each card. Separately, steps the SDK marks `not_applicable` were graded as failures on the hosted runner but skipped locally. Filed with both runner source lines and a local reproduction ([#7404](https://github.com/adcontextprotocol/adcp/issues/7404), bot-triaged P0); this was the second time the OR gate was fixed. The first was [#6773](https://github.com/adcontextprotocol/adcp/issues/6773) in August — `billing_gate_dispatch` listing `get_adcp_capabilities` beside `sync_accounts`, which every conformant agent satisfies, so signals-only agents were admitted and failed the first step instead of skipping. [#6774](https://github.com/adcontextprotocol/adcp/pull/6774) merged inside fourteen hours and review widened the one-line deletion to 17 storyboards. It landed on main only: the 3.1.x cherry-pick its own PR body called warranted was never made, so the storyboards kept mis-selecting on the 3.1.20 line the hosted grader actually runs. The September fix is that backport finally arriving — the storyboard half merged on September 14, 2026, [#7405](https://github.com/adcontextprotocol/adcp/pull/7405) on main and the 3.1.x backport [#7406](https://github.com/adcontextprotocol/adcp/pull/7406) twenty-one seconds later, this one written from here rather than upstream — and shipped the same afternoon in v3.1.23, whose changelog names the filing: agents without `validate_input` now take a coverage-gap skip. The second half has since moved. [#7454](https://github.com/adcontextprotocol/adcp/pull/7454), merged September 13, 2026 and linked in the thread that day, grades `fixture_seed_unsupported` and similar skip reasons as not applicable. On the signals card the two storyboards filed under this half, `deterministic_testing` and `idempotency`, have read `untested` at 0/0 since September 14. They are no longer failures, though not the passes the local SDK reports either. Those runs also report `sdk_version` 14.0.0-rc.35, while #7454 was built against rc.33, so the shift cannot be credited to #7454 alone. A follow-up on September 15 missed that and argued the public feed could not represent a skipped step at all. The feed already could, and [a correction on September 16](https://github.com/adcontextprotocol/adcp/issues/7404#issuecomment-5695786953) says so. The issue was retitled at 10:15 UTC on September 16, 2026, three minutes after that correction, to “Hosted grader: 11 failing steps remain on two cards after #7454/#7405/#7406 (sales 10, signals 1); budget-truncated runs still published as complete grades”. The count matches both cards’ latest runs; how much of the drop those three PRs caused is less clear. Both cards still grade on the 3.1.20 bundle, published September 2, before #7405 and #7406 merged, and the one signals failure, in `billing_gate_dispatch`, is still there, as it was when this thread counted it on September 13. None of the ten sales failures is in a storyboard the filing named, and the 17 `canonical_format_validate_input` failures on the sales card cleared because this agent now implements `validate_input`. On truncation, the filing’s third report: the sales card’s two short runs on September 9 and 10, at 130 and 124 scenarios against 193 in a full run, still read `complete` and authoritative in the public history feed. [PR #7453](https://github.com/adcontextprotocol/adcp/pull/7453), merged September 13, 2026, stops runs the SDK marks `timed_out` from replacing the public grade; [PR #7506](https://github.com/adcontextprotocol/adcp/pull/7506), which would do the same for runs that report no completeness at all, is still an unmerged draft.
- **Grades that cannot be attributed** — two heartbeats of the same agent build, with no deploy between them, disagreed by a scenario. Nothing in the public compliance feed identified the grader that ran them, so a runner that changed under you and a runner that is simply non-deterministic looked identical from outside. Asked for one field on each history entry ([#7429](https://github.com/adcontextprotocol/adcp/issues/7429)). It arrived by another route. [#7454](https://github.com/adcontextprotocol/adcp/pull/7454), merged September 13, 2026, writes a provenance block on each new history entry, including the exact SDK version, the compliance bundle and a grading-policy version. Runs graded before it was deployed carry none. #7429 is still open, and [#7433](https://github.com/adcontextprotocol/adcp/pull/7433), a separate PR to persist the runner version, is still an unmerged draft.
- **A control that reports success and leaves no trace** — an owner requeue on September 7 produced no run and no history row, and the feed’s newest `owner_test` entry predated the click by 24 days. Filed as a two-way fork, silent no-op or ran-and-discarded-as-unchanged ([#7428](https://github.com/adcontextprotocol/adcp/issues/7428), bot-triaged bug and P1 eight minutes after filing). Closed as verified on September 15, 2026 with a third answer. *Requeue comply* only schedules the next heartbeat, by design; the click fell inside a 19.4-day window, August 19 to September 8, in which the registry graded the agent not at all, and on September 16, 2026 the feed still showed those 465.6 hours with no rows; and a fresh click with devtools open put three runs through admission to completion on September 13, which the maintainer confirmed end-to-end. The original click left no retained HTTP evidence, so its cause is unrecoverable, and the confirmation fixes triage scoped, a `last_rechecked_at` on the card and a flash that does not auto-dismiss, did not ship with the closure. One thing this filing should not claim: the requeue semantics were not a discovery. They were written down in [#4265](https://github.com/adcontextprotocol/adcp/pull/4265)’s body in May 2026 — the fix our own [#4253](https://github.com/adcontextprotocol/adcp/issues/4253) was closed against — where the endpoint is described as clearing `last_checked_at` so the agent is eligible on the next tick. We filed four months later against behaviour already documented in a thread we opened.
- **One gate, two meanings** — `required_tools` is read by two code paths that disagree: the suite selector excludes a storyboard when any listed tool is missing, the per-storyboard runner admits it when any listed tool is present. A storyboard naming two tools against an agent holding one is therefore skipped by the first and admitted-then-failed by the second. Filed after the same defect recurred on a line an earlier data fix had not reached — [adcp-client#2652](https://github.com/adcontextprotocol/adcp-client/issues/2652) was closed on the strength of a storyboard-side change, and `billing_gate_dispatch` mis-selected again four weeks later on 3.1.20 ([adcp-client#2882](https://github.com/adcontextprotocol/adcp-client/issues/2882), bot-triaged bug / conformance / ready-for-human). The bot triage confirmed the divergence against published 13.0.2 and the convergence already written in `comply.ts`, and put the choice of semantic to the maintainer, who shipped any-of rather than all-of, which is only safe because the storyboard-side fixes strip the universal capability tool from `required_tools` first. It shipped in 13.0.4 on September 14, 2026 (`comply.js:600` now reads `required.some(…)`) and the issue closed the same day. Against the sales agent the change is measurable: 305 storyboards selected on 13.0.2 became 348 on 13.0.4 with byte-identical caches, so the delta is the selector alone, and four of the newly admitted storyboards fail.
- **A grader that disagrees with itself between two of its own commands** — since `@adcp/sdk` 13.0.3, `storyboard run` grades every `response_schema` check on a `comply_test_controller` step as failed with `no_schema_registered`, while `storyboard step` passes the identical step seconds later on the same SDK with the schema id resolved. The agent's response is conformant either way — the controller arms and echoes the forced task id ([adcp-client#2867](https://github.com/adcontextprotocol/adcp-client/issues/2867)). It was the reason both of our agents stayed pinned to 13.0.2 rather than tracking `latest` — the newer build could not grade its own controller surface. Root-caused by the bot triage to `isExternalResponseSchemaAuthoritative` treating a test-harness tool like a protocol tool, fixed in adcp-client#2894 on the 13.x line, released in 13.0.4 on September 14 and closed the same day. Both agents now track 13.0.4.
- **A heartbeat that had not run in four days, and the question that stayed open** — the dashboard advertised a recheck cadence it was not keeping: no scheduled run against the signals agent in four days while a manual evaluation of the same agent passed 30 of 30 ([#4253](https://github.com/adcontextprotocol/adcp/issues/4253)). [#4265](https://github.com/adcontextprotocol/adcp/pull/4265) shipped three causes the next day — `last_checked_at` was stamped before `comply()` ran, so a crash inside the window silenced the agent for up to 12 hours a cycle; every heartbeat row was written `dry_run: true` and so never reached the dashboard; and manual runs wrote only to a table the dashboard does not read. Two asks did not ship: the last-automated versus last-manual distinction, and an answer to why the tick itself had not fired. The closing comment carved that second one out as a known follow-up — a scheduler concurrency limit of five against an unbounded wait queue, where five hung jobs block the heartbeat indefinitely — deferred until production diagnostics existed. By September 15, 2026 a stall of that shape showed fleet-wide: across all 35 registered agents, heartbeat runs went from 25–36 a day over September 8–13 to six on the 14th and one on the 15th, with no heartbeat anywhere in the registry for fourteen hours and 30 of the 31 agents with a heartbeat on record past a day since their last. Filed with the fleet numbers as [#7546](https://github.com/adcontextprotocol/adcp/issues/7546), pointing at the follow-up rather than asserting it. The filed sweep missed one of the 35 feeds, so the issue shows five and 29 of 30. Bot-triaged seven minutes later as a bug, `priority:P0`, P0 Bugs milestone, ready-to-implement. Its code-reviewer read `scheduler.ts` as confirming the mechanism, with `releaseSlot()` in a `finally` that does not run until the job’s promise settles: “Five hung jobs = five permanently occupied slots = everything else waits forever.” The fix it named is a `Promise.race` timeout in `runJob`, with a queue-depth cap as secondary hardening; the triage’s other expert recommended pulling `/internal/jobs` first to identify the stuck slots. The fix merged at 17:09 UTC on September 16, 2026 as [#7556](https://github.com/adcontextprotocol/adcp/pull/7556), opened under the maintainer account, and #7546 closed as completed one second later. It is the `Promise.race` timeout the triage named, made opt-in: a scheduled job can set `executionTimeoutMs`, and when that expires the scheduler signals the run to stop through an `AbortSignal` and stops waiting on it, so the `finally` holding `releaseSlot()` runs even if the job never settles. Only the compliance heartbeat opts in, at two hours against a documented worst case of about 115 minutes; it passes the signal into the SDK run, checks it before each agent, and, when an aborted run throws, stops before recording a failure against the agent it was testing. The job status behind `/internal/jobs` now reports `activeJobs`, `queuedJobs` and `maxConcurrency`; neither this PR nor its 3.1.x backport adds the queue-depth cap. The repository’s Deploy workflow reports a successful Fly.io deploy of the merge commit, completed at 17:38 UTC, and two more of `main` that include it, completed at 17:55 and 21:05 UTC. The 3.1.x backport, [#7557](https://github.com/adcontextprotocol/adcp/pull/7557), merged at 19:05 UTC the same day and carries over the guard `main` already had against a job overlapping its own previous run. The 35 public compliance feeds list only complete, authoritative runs, and since [#7453](https://github.com/adcontextprotocol/adcp/pull/7453) a timed-out run is kept as audit evidence without changing the public grade; the heartbeat also tests crawler-discovered agents outside the public listing. So the feeds bound the heartbeats that finished on these 35 agents, not the ones attempted or the ones run on other agents. In them, after one heartbeat on September 15, two appear on the 16th, at 18:19 and 18:23 UTC, on two agents, neither of them mine, and none after those through 12:46 UTC on September 17; the feeds do not show whether those two runs owe anything to the fix. Of the 31 agents with a heartbeat on record, 29 are more than two days past their last one. In those feeds my two agents have no heartbeat since the merge: their last were at 20:03 UTC on September 14 (signals) and 02:43 UTC on September 13 (sales), and their newest runs are owner-triggered, at 09:52 UTC on September 16 and 11:41 UTC on September 17. A follow-up on #7546 at 11:01 UTC on September 17, 2026 set out these public numbers with the same caveat and asked what the jobs status endpoint shows.
- **A field the 3.1 schema requires and two governance storyboards never send** — on the 3.1 line, `governance_approved` and `governance_conditions` register a governance agent on the account, then call `create_media_buy` without `plan_id`, which the request schema from 3.1.20 through v3.1.23 says is “Required when the account has `governance_agents` ”. The seller has no other key for the approval call: the 3.1 `check_governance` requires `plan_id` and tells governance agents to reject a sibling `account` field ([#7547](https://github.com/adcontextprotocol/adcp/issues/7547), filed September 15, 2026). The sales agent shipped delegated governance that day — `sync_governance`, a `check_governance` call before commit, `governance_aware: true` — and a registration on the shared sandbox test account is permanent, so every `create_media_buy` on that account started to require `plan_id`. Six storyboards went red: the two named here; the base `media_buy_seller` storyboard, which registers an agent in its own setup phase and then buys without `plan_id`; and three that never ask for governance and only reuse the account. The full local suite (`@adcp/sdk` 13.0.4, bundle 3.1.20) read 246 steps passed and 8 failed, with Reporting & Delivery down to 7 of 17 scenarios. The filing argues that an agent declaring `governance_aware` cannot accept such a buy and skip the call. About an hour and a half after shipping, this one stopped declaring it. One constant, `GOVERNANCE_DELEGATION_ENABLED = false`, turns off the call and the tool: `sync_governance` is off `tools/list` and refused with `UNSUPPORTED_FEATURE`. A test fails if `governance_aware`, now `false`, disagrees with the constant. A buy on the registered account now goes through without `plan_id` and without calling the agent, then waits for human approval like every buy on this agent. The suite went to 259 passed and 2 failed (`post_sivt` and `sync_creatives_contradicted`, both intentional). Bot-triaged P0 on September 15, at first with two options put to the maintainer: A, add `plan_id: "$context.plan_id"` to both storyboards; B, move `main` ’s deprecation of `plan_id`, in favour of `governance_context`, into the next 3.1.x patch. Our follow-up, under an hour after the switch-off, checked A against the shipped 3.1.20 bundle. Each file there has one `context_outputs` block, owned by `get_products_brief`, so `$context.plan_id` is undefined. Each also has a `sync_plans` step, a governance-agent task, without the `requires: [multi_agent]`, `default_agent: sales` and per-step `agent:` routing that `governance_denied` and `governance_denied_recovery` carry. So `sync_plans` is routed to the seller, and a seller-only agent skips the plan-setup phase as a missing tool. Both findings are about the 3.1 line. That follow-up, at 01:07 UTC on September 16, did not say so, and a second one at 10:21 UTC the same day did. On `main`, both storyboards have routed `sync_plans` to a governance agent and exported its `plan_id` since August 8, 2026 ([PR #6277](https://github.com/adcontextprotocol/adcp/pull/6277), [PR #6280](https://github.com/adcontextprotocol/adcp/pull/6280)), and they send `governance_context` where the released 3.1 files send neither field — there `$context.plan_id` is defined, as the triage said. When that second follow-up went up, none of that had reached the 3.1.x branch or v3.1.23, the hosted card graded on bundle 3.1.20, and a 3.1 seller needed the fixes from #6277 and #6280 on 3.1.x under either option. At 10:26 UTC on September 16, 2026 the bot rewrote that triage. It now says the A-or-B framing rested on the 3.1.20 bundle alone, names a backport of #6277 and #6280 as the fix, and leaves the deprecation as a separate policy call. As of 11:25 UTC on September 17, 2026, nobody else has commented on #7547. At 17:09 UTC on September 16, 2026 [PR #7555](https://github.com/adcontextprotocol/adcp/pull/7555) merged into the 3.1.x branch. It marks the two 3.1 governance storyboards `requires: [multi_agent]` with `default_agent: sales`, routes `sync_plans` to the governance agent and every other step to the seller, gives `sync_plans` a `context_outputs` block that captures `plans[0].plan_id`, sends that as `plan_id: "$context.plan_id"` on `create_media_buy`, and adds a test for the routing and the hand-off. It does not take #6277 and #6280 whole: its description says doing so would also import 3.2-only response fields such as `check_type` and `consultation_context`, which the 3.1 schema-path lints reject, so it carries only the routing and `plan_id` fixes. The 3.1.x `create_media_buy` request schema defines no `governance_context` field, and neither patched request sends one. The description says “Closes #7547”, but GitHub acts on that keyword only when a PR merges into the default branch, `main`, and as of 10:48 UTC on September 17, 2026, #7547 is still open. Nor is the fix released: there is no v3.1.24 tag, the 3.1.x branch is three commits past v3.1.23, and the open release PR ([PR #7559](https://github.com/adcontextprotocol/adcp/pull/7559)) lists the change under `adcontextprotocol@3.1.24`. The newest public run on the hosted card, an owner refresh at 09:55 UTC on September 16, 2026, before the merge, graded bundle 3.1.20. Of the storyboards, #7555 touches only `governance_approved` and `governance_conditions`. The other four that failed are unchanged on 3.1.x since v3.1.20, and each still calls `create_media_buy` for the brand and operator the governance storyboards register, without `plan_id`. Three of them, `delivery_reporting`, `measurement_accountability` and `vendor_metric_accountability`, register no agent and only reuse the account. The fourth, the base `media_buy_seller` storyboard, registers one in its own `governance_setup` phase, with no multi-agent requirement, and then buys without `plan_id`: the shape this filing reported, in a storyboard it did not name. On `main` its copy has the same shape and sends no `governance_context`, which `main` requires once governance applies to the account. #7555 changes none of the four: turning the constant back on would again have the agent refuse those buys for lack of `plan_id`, as it did in the local suite before the switch-off — the three while the registration on the shared account stands, and `media_buy_seller` on every run, since its own setup phase registers the agent again. The local suite cannot run the patched storyboards yet: it runs bundle 3.1.20 from `@adcp/sdk` 13.0.4, which carries no later 3.1 bundle. The constant stays off. A follow-up on #7547 at 12:18 UTC on September 17, 2026 raised the base storyboard there, marked as outside that issue’s scope, with the evidence for both branches, and offered to file it separately. The maintainer account answered on September 18, 2026 to file it separately — the base storyboard is a different file, carries none of the `plan_id` infrastructure the backport relies on, and has three plausible fix shapes of differing blast radius, so it should not absorb into a P0 thread otherwise ready to close. It is [#7585](https://github.com/adcontextprotocol/adcp/issues/7585), filed the same day with the per-branch line references: on 3.1.x the file has zero occurrences of `plan_id`, `sync_plans`, `multi_agent` or `default_agent`, and on `main` zero of `governance_context`. The filing concedes what the defect is not: on both branches the obligation is prose in the field description rather than a machine-enforced conditional — top-level `required` is the same five fields on each line, and neither schema carries an `if/then` or `dependentRequired` touching either field — so a schema-validation pass over the storyboard is clean, and it fails only against a seller that enforces the documented requirement. The timing matters because #7559’s `dist/compliance/3.1.24` copy is the identical blob, so 3.1.24 ships the storyboard unchanged unless the decision lands first.
- **A conformance failure you cannot act on** — `capability_discovery` failures reported the scenario name and nothing else: no request, no response, no pointer, no expected against actual ([#2352](https://github.com/adcontextprotocol/adcp/issues/2352), with the Signals track reported separately as [#2356](https://github.com/adcontextprotocol/adcp/issues/2356) when a declared `signals` protocol was told the track was not applicable). The maintainer wrote the protocol-side runner-output contract in response — [#2364](https://github.com/adcontextprotocol/adcp/pull/2364) mandates the exact request and response, an RFC 6901 `json_pointer`, machine-readable expected and actual, a fetchable `schema_url` and six canonical skip reasons — and [#2365](https://github.com/adcontextprotocol/adcp/pull/2365) populated the signals baseline, which had shipped as a placeholder with no phases, so there had been nothing to run. Both merged the same day. Worth recording what the same thread established about us: the filing argued our agent was correctly implemented, and two of the failures were real non-conformances on our side, a missing `adcp.idempotency` block and no `context.correlation_id` echo. We fixed those. The contribution is the report and the reproduction; the implementation was the maintainer’s.
- **A second filing withdrawn** — an argument that npm-published compliance caches omit the sibling `schemas/` directory the resolver needs, leaving an earlier fix inert for anyone on a plain `npm install` ([#6650](https://github.com/adcontextprotocol/adcp/issues/6650), re-filed correctly as [adcp-client#2587](https://github.com/adcontextprotocol/adcp-client/issues/2587)). The maintainer unpacked the exact tarball and showed the resolver falling through to the package’s own bundled schemas, no sibling required. Retracted the same afternoon. The advisory that prompted it had a different cause entirely — a second, 3.0-shaped validation from the new mixed-version compatibility check — filed separately and fixed within the hour. Two things this one is worth remembering for: the issue still reads *completed* in the API, because an author self-close with no reason renders that way, and the automated triage posted a confirmed-and-ready-to-implement verdict at P1 four minutes *after* the issue was closed and under an hour before the human maintainer disproved it. Triage labels on this repository are a bot’s opinion, not a maintainer’s endorsement.
- **A storyboard that asks for a value the schema rejects, still shipping on 3.1** — the version-negotiation steps in `universal/error-compliance.yaml` and `error-compliance-signals.yaml` tell a seller to answer `VERSION_UNSUPPORTED` with `recovery: fatal`, and list the vocabulary as “correctable, transient, or fatal”. `core/error.json` types `recovery` as `["transient", "correctable", "terminal"]`, so `fatal` is not a legal value, and `enums/error-code.json` classes this code `correctable`: re-pin to a supported release and retry. Someone else had already found it and filed it ([#7375](https://github.com/adcontextprotocol/adcp/issues/7375), September 8, 2026); [PR #7376](https://github.com/adcontextprotocol/adcp/pull/7376) corrected both lines on `main` the same day and the issue closed. What had not happened was the backport. On September 17, 2026 the 3.1.x source still carried the old prose at lines 302 and 359, and v3.1.23 — published on September 14, six days after the fix landed on `main` — shipped it in `dist/compliance/3.1.23/`. That is the line the hosted grader runs, on bundle 3.1.20. A comment on the closed issue that day set out the two branch states, the release timeline and the enum, and noted the grade is unaffected either way, because nothing in the SDK parses the `expected:` prose — only the `validations:` entries decide pass or fail. Both of this site’s agents had the defect the prose would have caused, in opposite directions: the sales agent answered an unsupported pin with `recovery: "terminal"`, which on 3.1 means the buyer needs a human, and the signals adaptor sent no `recovery` at all, where 3.1 says senders SHOULD populate it on every error. Both now answer `correctable`, verified live. Seven minutes after that comment, [PR #7572](https://github.com/adcontextprotocol/adcp/pull/7572) was opened against `3.1.x` carrying the same two-line change plus a changeset, described as ready for the 3.1.24 window. Like the other triages on this page it is bot-drafted under the maintainer account, so it still has to pass review and catch the release. The audit that followed on this side found the defect was a class rather than an instance: the sales agent’s `ToolError` constructor defaults `recovery` to `terminal`, and its own doc comment named only two of the three legal values, so 16 sites across seven codes inherited the most severe classification for errors a buyer could have fixed — a wrong media buy id, a malformed request, a governance denial explained as “over budget”. Each was re-judged against what its call site actually does, and three were kept `terminal` on the evidence: one internal invariant on an id the buyer never supplies, and two admin-console paths where the field never reaches the wire. Those three are now pinned explicitly rather than inherited. The denial case also now forwards the governance agent’s `findings`, which `check-governance-response` requires when the verdict is denied: calling an error correctable while dropping the reason leaves the buyer guessing what to change.
- **A filing that was right about the symptom and wrong about the cause** — the signals agent’s hosted card showed `error_handling` at 10 of 11 scenarios. The failure was not an error-handling defect at all: `billing_gate_dispatch` asserts `field_present: account.supported_billing` in an ungated first phase, and that field is `required` with `minItems: 1`, so there is no honest value for an agent with no account management. Its own description says buyers pass one of those values in `sync_accounts` — a tool this agent does not expose. Declaring it to pass would have been the `governance_aware` mistake again. Filed as [#7573](https://github.com/adcontextprotocol/adcp/issues/7573) on September 18, 2026, bot-triaged P1 within eight minutes with a primary fix in the SDK and a defensive one in the storyboard. Two corrections followed, both ours. One line of the filing said the divergence only appeared when a track was forced; that was true of SDK 13.0.2 and false of the pinned 13.0.4, carried forward without re-checking. The larger one: the triage’s primary fix was a no-op. The runner already enforced `required_tools` in every mode — at `comply.js:600` for capability-driven selection and again at `runner.js:1420` at load time — as an *any-of* gate, which the bundled storyboard schema documents as deliberate and pairs with a strict `required_any_of_tools` form that almost nothing uses. Both storyboards were admitted on one matching tool: `get_adcp_capabilities`, which every agent has, and `comply_test_controller`. Searching only this protocol’s repository before filing had also missed two earlier filings of ours in the client repository, making this the third occurrence — and the any-of convergence that admits these storyboards shipped in 13.0.4 because we asked for it. The fix that landed, [PR #7581](https://github.com/adcontextprotocol/adcp/pull/7581), took the defensive route on September 18, 2026: `optional: true` plus `requires_capability: { path: account, present: true }`, with a runner test. It is on `main` only. The finding that mattered came afterwards. The `required_tools` corrections had already shipped upstream — across storyboards on August 23 and for the other file on September 14 — and are in the released v3.1.23 bundle. Running the SDK’s own `resolveStoryboardsForCapabilities` and `partitionStoryboardsByRequiredTools` against each bundle in turn: on 3.1.20 both storyboards are runnable, on 3.1.23 both are excluded for missing `sync_accounts` and `validate_input` respectively — 19 runnable storyboards and 171 steps down to 17 and 149, with nothing newly selected. So the storyboard defect had largely been fixed weeks earlier, and what remains is that the hosted grader is pinned to bundle 3.1.20. That is a registry-side pin, not a protocol matter, and it was raised there rather than on the issue. Excluded is not passed: those storyboards leave the denominator as not-applicable rather than becoming passing steps.
- **An idempotency key that dies with the row it protects** — the recovery audit left one item out of scope: `buyResponse` answers a missed read-back with `MEDIA_BUY_NOT_FOUND`, on an id every caller derives server-side, so there is nothing in the request for the buyer to verify. The trigger is a console delete landing between the caller’s own read and that one. D1 has no interactive transactions and the purge’s `batch()` is atomic only with itself, so nothing serialises the two. Three interleavings reproduce. The narrowest is the create path, since a fresh buy is written `pending_approval`, which sits in neither delete guard and so needs a decide-then-purge pair inside the window; the widest is `get_media_buys`, where one purged row fails the entire list and the sandbox sweep in the promotion cron carries no status guard at all. The first fix answered `CONFLICT` with `recovery: transient` and was wrong. `core/error.json` defines `transient` as “retry after delay”, the purge takes the row’s `UNIQUE` `idempotency_key` with it, and a buyer following that instruction writes a second buy instead of replaying the first. Checked against the running implementation rather than argued: the same key after a purge returns a new `media_buy_id`. Create now answers `terminal` on both of its call sites, and the read paths stay `transient`, where a retry does converge. The half the spec owns went upstream ([#7575](https://github.com/adcontextprotocol/adcp/issues/7575), filed September 17, 2026): `replay_ttl_seconds` scopes the replay window purely in time, minimum 3600, and enumerates three outcomes, being the cached response, `IDEMPOTENCY_CONFLICT` and `IDEMPOTENCY_EXPIRED`. None of them is the fourth that any seller keying idempotency to the resource row will produce, where the key dies with the resource and a replay inside the advertised window creates a second one and returns success. `CONFLICT` is no better a fit: the schema scopes it to revision mismatch, and `error-details/conflict.json` carries `expected_version` and `current_version`, neither of which a deleted row has.
- **A test-scenario report that was out of date when filed** — reported on April 27, 2026 that the SDK’s signals test scenario (`scenarios/signals.js`) called `activate_signal` with `signal_id`, carrying a `SignalID` object, where the schema requires a `signal_agent_segment_id` string ([#3349](https://github.com/adcontextprotocol/adcp/issues/3349), filed in the protocol repository under a header that already named `adcp-client` as its subproject, and re-filed there three minutes later as [adcp-client#1033](https://github.com/adcontextprotocol/adcp-client/issues/1033)). The field name had been corrected on March 21, 2026 and released that day in `@adcp/client` 4.13.0, five weeks before the filing. The object half was never true: even before that fix, the value passed was a string. The two bot triages disagreed: the one on #3349 accepted the premise, and the one on adcp-client#1033, fifteen minutes later, found the report false against the then-current 5.21.1. The client-repo copy was closed on April 30, 2026 as already fixed. This one was closed as not planned on May 19, 2026, with a comment that the spec storyboards already use the correct fields and the report belongs to `adcp-client`. Two merged PRs came out of the bot triages, and neither is the fix the filing asked for: the #3349 triage, taking the report at its word, drafted the removal of training-agent aliases that still accepted the old field names, with sharper schema descriptions ([PR #3356](https://github.com/adcontextprotocol/adcp/pull/3356), merged May 14, 2026), and the adcp-client#1033 triage drafted a fix for a separate bug it found in the same scenario, a governance advisory check that never fired ([adcp-client#1036](https://github.com/adcontextprotocol/adcp-client/pull/1036), merged April 28, 2026).

### Open proposals

- **Geo cell interoperability** — conversion ([#6013](https://github.com/adcontextprotocol/adcp/issues/6013)) and cell-grain delivery reporting ([#6014](https://github.com/adcontextprotocol/adcp/issues/6014)) companions to the geo_cells RFC ([#5969](https://github.com/adcontextprotocol/adcp/issues/5969)), with Nathan Woodman.
- **Static OOH: the channel with no play event** — static out-of-home has nothing to emit an impression against, so proof-of-posting has no shape in the delivery contract; filed with a measurement shape and posting-record proposal ([#6140](https://github.com/adcontextprotocol/adcp/issues/6140)). The channel contract it asked for merged — `ooh_metrics`, posting records and a channel guide ([PR #6241](https://github.com/adcontextprotocol/adcp/pull/6241)) — and the measurement-shape half is still open.
- **A seller shape the taxonomy has no slot for** — the specialisms treat guaranteed-vs-non-guaranteed as a proxy for human-approval-vs-auction, so a publisher-direct seller running fixed-price, non-guaranteed inventory behind a human approval gate matches neither: `sales-non-guaranteed` assumes bidding and states that buys need no human approval, while `sales-guaranteed` describes the human gate but assumes IO-signed reserved inventory and proposal flows ([#6303](https://github.com/adcontextprotocol/adcp/issues/6303), filed with our own live agent as the reproduction after withdrawing a claim we couldn't honestly certify). The certification contradiction found alongside it is already fixed: the docs stated that grading neither requires nor uses `comply_test_controller`, while specialism certification requires `seed_*` scenarios only that controller can execute — confirmed and scoped to the storyboards it actually covers, since the exemption holds for universal and protocol runs but not for specialisms that seed state ([#6301](https://github.com/adcontextprotocol/adcp/issues/6301), fixed).
- **Eligibility you can read off the API** — `verified` is a bare boolean computed from badge rows, so a seller cannot tell “declare specialisms” from “fix storyboards” from “membership tier” ([#6374](https://github.com/adcontextprotocol/adcp/issues/6374), split from #6363 because the bot triage there flagged it as a separate API-contract issue, auto-triaged ready-to-implement within the hour, and untouched by a maintainer since — closes the API half of #3525): proposes a per-role `eligibility` block with machine-readable blocker codes, filed with our agent as the reproduction — zero failing storyboards, `verified: false`, and the actual first-guard blocker (no declared specialisms, the #6303 taxonomy gap) surfaced by no public field.
- **revoke_activation** revocation primitive ([#4203](https://github.com/adcontextprotocol/adcp/issues/4203)) · **Measurement Feedback Signal** ([#4296](https://github.com/adcontextprotocol/adcp/issues/4296)).
- **JWKS adoption baseline** — the chain-of-custody gate on signal-payment work ([#4206](https://github.com/adcontextprotocol/adcp/issues/4206)).

### Not protocol work — bug reports and a feature request against the AAO platform

- **Shipped as filed, one of them only in part** — the member profile edit page threw `parsed is not defined` on load, a one-line scoping error ([#4257](https://github.com/adcontextprotocol/adcp/issues/4257)), and photo uploads on the same page reverted silently on save, from two compounding causes: the upload handler wrote a base64 data URL the brand-identity endpoint rejects, and the save never sent the photo field ([#4260](https://github.com/adcontextprotocol/adcp/issues/4260)). Both were fixed in [PR #4352](https://github.com/adcontextprotocol/adcp/pull/4352), merged May 10, 2026, which references neither issue; its description credits my in-app escalations of the same two defects, and both issues were closed on May 12 with a comment pointing to it. Badge links of the form `/registry/agents/{encoded-url}` returned `Cannot GET` ([#5485](https://github.com/adcontextprotocol/adcp/issues/5485)) until [PR #5492](https://github.com/adcontextprotocol/adcp/pull/5492), a five-issue batch merged June 12, 2026, served that path as a public agent profile page. A “0 / 0 Community seats” row on a Professional plan, which the filing itself called display-only ([#5494](https://github.com/adcontextprotocol/adcp/issues/5494)), was hidden on plans without Community seats by a small conditional ([PR #5586](https://github.com/adcontextprotocol/adcp/pull/5586), merged June 18, 2026). A copy button for replies in AAO’s Addie assistant shipped ([#4266](https://github.com/adcontextprotocol/adcp/issues/4266) → [PR #4269](https://github.com/adcontextprotocol/adcp/pull/4269)) without the plain-text/markdown toggle the request also asked for, which the bot triage declined and the PR left out of scope.
- **Wrong or partial diagnoses, and one wrong report** — the dashboard’s Test view listed media-buy storyboards for a signals-only agent; filed as missing capability filtering, but the filter already existed, and a fallback to the full catalog, taken when the platform’s capability probe of my agent failed for a reason the record does not give, bypassed it. The fix drops the fallback and shows the probe error, with a pointer to what `get_adcp_capabilities` must return, rather than the filtered list the filing expected ([#4254](https://github.com/adcontextprotocol/adcp/issues/4254) → [PR #4369](https://github.com/adcontextprotocol/adcp/pull/4369)). The member directory showed “Tools: 0” for an agent with eight tools; filed as a stale comply cache, a theory the fixing PR calls incorrect: the public discovery endpoint probed the agent live and left the tool list out of its response ([#4256](https://github.com/adcontextprotocol/adcp/issues/4256) → [PR #4261](https://github.com/adcontextprotocol/adcp/pull/4261)). The organization page offered “Register an agent” to an org that had one; the filing guessed the page was not querying the registry or was filtering on a stale comply cache, and the health service in fact returned a hard-coded agent count of zero ([#4255](https://github.com/adcontextprotocol/adcp/issues/4255) → [PR #4258](https://github.com/adcontextprotocol/adcp/pull/4258)). Listing the org’s agents on that page, the filing’s first expected behaviour and its whole suggested fix, was left out of scope by the bot triage and the PR. Addie kept reporting GitHub as unconnected for a turn after OAuth completed; the bot triage and the fixing PR found the token lookup already ran live on every tool call, which rules out the filing’s caching guesses, and put the lag down to propagation delay in the upstream WorkOS API, which none of the filing’s three guesses named. The fix is a single 1.5-second retry that absorbs that window, a note in the not-connected reply that the connection may still be propagating, and a prompt rule that stops Addie offering the Connect link again right after the user says it is connected; none of it is a change to connection state ([#4348](https://github.com/adcontextprotocol/adcp/issues/4348) → [PR #4349](https://github.com/adcontextprotocol/adcp/pull/4349)). And one report was wrong. A community profile photo picker, on a different page from #4260, reported as broken, was the reference-photo input for AI portrait generation: the filing’s own steps name it (“Upload a reference photo”), and the bot triage found its hint reads “Used as reference only, not stored” and that the avatar changes only after Generate and Approve. That triage put a choice between a direct upload path and clearer labels to the maintainer, and the merged fix built the upload path ([#4658](https://github.com/adcontextprotocol/adcp/issues/4658) → [PR #5157](https://github.com/adcontextprotocol/adcp/pull/5157), merged May 29, 2026).
- **Registry & docs reliability** — registry UI rendering empty product/format sections for anonymous viewers despite working public endpoints ([#6229](https://github.com/adcontextprotocol/adcp/issues/6229), fixed and closed; my own duplicate of it, [#6230](https://github.com/adcontextprotocol/adcp/issues/6230), filed 57 seconds later, drew a bot triage the same day that surfaced a third break in publisher discovery; I carried that finding across when I closed #6230 as a duplicate on August 6, 2026, which GitHub records as not planned, and it was fixed in the same change) and the dashboard's aao-verified doc links returning 404 ([#6231](https://github.com/adcontextprotocol/adcp/issues/6231), fixed and closed). The registry card's "Publishers & properties" panel surfacing a raw JSON-parse exception instead of the actual authorization-list cause ([#7333](https://github.com/adcontextprotocol/adcp/issues/7333)) is fixed too — [PR #7362](https://github.com/adcontextprotocol/adcp/pull/7362) now indexes publisher authorization data, guards invalid JSON responses, and renders clean 404/error states.

Contribution statuses validated September 16, 2026 against the public AdCP repository; open proposals are point-in-time and may merge, change, or close. Maintainer-authored work is credited as review influence, not authorship.

*Domains*

## Protocol domains.

AdCP organizes work into domain-specific tasks and schemas. Task names below are drawn from current official documentation.

- **Media Buy** — Inventory discovery, campaign creation, delivery reporting. `get_products · create_media_buy · get_media_buy_delivery`
- **Creative** — Creative format discovery, building, preview, distribution. `build_creative · preview_creative · list_creative_formats`
- **Signals** — Audience and contextual data discovery and activation. `get_signals · activate_signal`
- **Accounts** — Commercial identity, billing, and usage reporting. `list_accounts · sync_accounts · report_usage`
- **Governance** — Brand suitability, approval, policy, audit, content standards. `create_content_standards · calibrate_content`
- **Brand** — Machine-readable brand identity and authorized agents via brand.json. `brand.json discovery`
- **Sponsored Intelligence** — Conversational brand experiences on AI platforms. `Experimental surface in AdCP 3.0`
- **Curation** — Media inventory curation. `Listed "coming soon" — not a current domain`

*Figure: AdCP at the center; each domain connects to a workflow surface.*

*Workflow*

## From brief to governed execution.

1. **Discover authorized agents** — adagents.json, brand.json, registry
2. **Set up account context** — commercial identity, billing, advertiser / operator relationship
3. **Discover inventory and products** — natural-language brief into structured product responses
4. **Build or sync creative** — formats, assets, brand identity, approvals
5. **Add signals** — audiences, suppression, contextual signals, signal activation
6. **Check governance** — budget, brand safety, targeting rules, approvals
7. **Execute, report, and audit** — media buy, delivery, events, audit logs

*Figure: Brief → discovery → accounts → products → creative → signals → governance → buy / report / audit.*

Discovery starts from two machine-readable files — a publisher's `adagents.json` (who may sell its inventory) and a brand's `brand.json` (who may act for the brand, and how):

**adagents.json** (illustrative)

```json
{
  "publisher": "example-publisher.com",
  "authorized_agents": [
    {
      "url": "https://sales-agent.example-ssp.com",
      "role": "seller",
      "properties": ["news", "sports"]
    }
  ],
  "signing_keys": [
    { "kid": "2026-key-1", "alg": "Ed25519" }
  ]
}
``` **brand.json** (illustrative)

```json
{
  "brand": "example-brand.com",
  "display_name": "Example Brand",
  "authorized_agents": [
    { "url": "https://agent.example-buyer.com", "role": "buyer" }
  ],
  "identity": {
    "logos": ["/brand/logo.svg"],
    "colors": ["#1a1a1a", "var(--accent)"],
    "tone": "confident, plain-spoken"
  },
  "policy": { "restricted_categories": ["gambling", "politics"] }
}
```

*Signals*

## Signals: where AdCP meets signal containerization.

The signals layer is where AdCP becomes especially important for agentic advertising. Agents need to discover signals, understand what they mean, check provenance and policy, activate them, and monitor status. That is the same operating problem behind [signal containerization](https://nofluffadvisory.com/writing/signal-containerization-agentic-advertising/) — turning audience logic into a governed, executable object.

- **Discover** — What signals exist and what do they mean?
- **Inspect** — Where did the signal come from, how fresh is it, and what policy applies?
- **Activate** — Where can the signal run: seller, platform, identity path, contextual path, or measurement layer?
- **Monitor** — What is the activation status and what outcome did it improve?

*Figure: Discover, inspect, activate, monitor — signals as executable objects.*

An agent discovers signals with a natural-language brief, then activates the chosen signal to a destination — a single `get_signals` call rather than a taxonomy lookup:

**get_signals (MCP tool call)** (illustrative)

```json
{
  "tool": "get_signals",
  "arguments": {
    "brief": "in-market for premium CTV, US households, privacy-safe",
    "deliver_to": { "platform": "dsp", "account": "acct_123" },
    "max_results": 10
  }
}
```

One open question now sits under this layer. The vectors agents exchange today are text-family embeddings — they encode the words that describe an audience or a brief, and text models famously lose numbers, geography, and time. A second family, [spatiotemporal embeddings](https://nofluffadvisory.com/writing/the-context-economy/#the-moment-has-four-dimensions), encodes the place and hour themselves. A text space and a place-time space do not share a geometry: similarity across the two is undefined until someone defines it — a signals-standards question, exactly the kind of definition a signals working group exists to produce, not an integration ticket.

*Trust*

## Governance is the trust layer.

Agentic advertising only works if actions are accountable. A protocol needs to know who called a tool, what authority they had, what was approved, what conditions applied, and what actually ran.

- Human-in-the-loop approvals (a three-party separation of duties)
- Idempotency keys on every mutating request
- Request signing (RFC 9421 HTTP Message Signatures)
- Correlated audit logs
- Governance checks and signed governance tokens
- Brand-safety and content-standard enforcement
- Budget thresholds and authority / role boundaries

**The principle**

Human judgment is embedded in the system design, not bolted on afterward — the human stays the locus of accountability.

*Complementarity*

## Where AdCP fits with IAB Tech Lab standards.

AdCP is best understood as an agentic management and workflow layer. IAB Tech Lab's AAMP work extends existing standards with agentic foundations, protocols, and trust infrastructure — and its buyer and seller reference agents do workflow-layer work of their own (briefs, planning, negotiation, OpenDirect booking); ARTF focuses on containerized real-time execution; Agentic Audiences on embedding-based signal exchange. These layers can be complementary with clear boundaries — the full repository-level comparison, verified against both codebases, is in [AdCP vs AAMP: The Retrofit and the Greenfield](https://nofluffadvisory.com/writing/adcp-vs-aamp/). See also the [IAB Agentic Standards guide](https://nofluffadvisory.com/standards/iab-agentic-standards/). The protocol's sell side already has a shipping open-source implementation — Prebid.org took stewardship of AdCP's sell-side reference code in January 2026, dissected in [The Prebid Sales Agent](https://nofluffadvisory.com/writing/the-prebid-sales-agent/) — and landing inside the publisher execution layer documented in [Prebid & Header Bidding Infrastructure](https://nofluffadvisory.com/standards/prebid-header-bidding/).

| Initiative | Role | Best question |
| --- | --- | --- |
| AdCP | Agent task / workflow language | What should the agent ask or do? |
| AAMP | IAB Tech Lab umbrella — buyer/seller reference agents plus foundations and trust | How do agents run briefs, negotiation and booking on the standards already in production? |
| ARTF | Containerized real-time execution framework | How can service agents run inside host infrastructure with low latency and controlled mutation? |
| Agentic Audiences | Embedding-based signal exchange | How do agents exchange identity, contextual, and reinforcement signals? |
| OpenRTB / AdCOM / Deals API / OpenDirect | Existing transaction and object standards | What underlying objects and transaction models should agentic systems reference? |

*Figure: Two ancestries — new rails and existing rails — overlapping in function, meeting head-to-head at the deal plane.*

*Implementation*

## Implementation lens by company type.

Pick your company type to see what to expose or consume — and the AdCP domains it touches first.

**Publisher / seller — What to expose.** Authorized agents, inventory products, packages, account setup, governance, reporting.

*Key protocols: adagents.json, Media Buy, Accounts, Governance.*

**Agency / buyer — What to consume.** Partner discovery, product discovery, creative formats, media buy, governance, reporting.

*Key protocols: brand.json, Media Buy, Creative, Signals.*

**Data / signals vendor — What to expose.** Signal catalog, provenance, activation paths, pricing, policy, status.

*Key protocols: Signals, Accounts, Governance.*

**SSP / exchange — What to support.** Seller agents, deals, signals, governance, a real-time execution bridge, reporting.

*Key protocols: Media Buy, Signals, Governance, registry.*

**DSP / buying platform — What to support.** Buyer agents, media buys, creative, signal activation, governance, measurement.

*Key protocols: Media Buy, Creative, Signals, Governance.*

**Creative / AI platform — What to expose.** Formats, asset generation, preview, brand identity, approval workflow.

*Key protocols: Creative, Brand, Governance.*

**Measurement / clean room — What to expose.** Delivery, event logging, attribution, audit, lift, governed outputs.

*Key protocols: Media Buy, Accounts, Governance.*

*No Fluff POV*

## A protocol defines the task. It does not replace judgment.

The industry should avoid treating AdCP as a magic layer that makes agents safe by default. The protocol can define the task. It cannot replace commercial judgment, governance design, data rights, measurement discipline, or operating ownership.

- Start with one workflow, not every workflow.
- Expose the safest useful task first.
- Design governance before spend movement.
- Treat signals as governed objects, not just segment IDs.
- Build audit and status from day one.
- Connect protocol work to business outcomes, not demos.

*Stack fit*

## Where this fits in the full standards stack.

**The layer map**

AdCP defines the agent workflow layer. It still needs transaction rails, privacy constraints, measurement trust, and evidence discipline around it.

- [Core AdTech Standards](https://nofluffadvisory.com/standards/core-adtech-standards/)
- [Privacy & Consent Standards](https://nofluffadvisory.com/standards/privacy-consent-platform-apis/)
- [Measurement & Media Quality](https://nofluffadvisory.com/standards/measurement-verification-media-quality/)
- [IAB Agentic Standards](https://nofluffadvisory.com/standards/iab-agentic-standards/)
- [Research & Measurement Science](https://nofluffadvisory.com/standards/research-measurement-science/)

*Related*

## Related materials.

- [Agentic Transformation](https://nofluffadvisory.com/services/playbooks/agentic-transformation/)
- [AdCP vs AAMP (essay)](https://nofluffadvisory.com/writing/adcp-vs-aamp/)
- [Signal Containerization (essay)](https://nofluffadvisory.com/writing/signal-containerization-agentic-advertising/)
- [The Context Economy (essay)](https://nofluffadvisory.com/writing/the-context-economy/)
- [The Prebid Sales Agent (essay)](https://nofluffadvisory.com/writing/the-prebid-sales-agent/)
- [Prebid & Header Bidding](https://nofluffadvisory.com/standards/prebid-header-bidding/)
- [AdCP Ecosystem prototype](https://nofluffadvisory.com/building/adcp-ecosystem/)
- [AdCP Signals Adaptor](https://nofluffadvisory.com/building/adcp-signals-adaptor/)
- [Enterprise Data Collaboration](https://nofluffadvisory.com/services/playbooks/multicloud-data-orchestration/)
- [Semantic Infrastructure](https://nofluffadvisory.com/services/playbooks/multicloud-data-orchestration/ecosystem-surfaces/semantic-infrastructure/)
- [DSP / Agentic Buying](https://nofluffadvisory.com/services/playbooks/multicloud-data-orchestration/ecosystem-surfaces/dsp-agentic-buying/)
- [BI / MMM / Decision Intelligence](https://nofluffadvisory.com/services/playbooks/multicloud-data-orchestration/ecosystem-surfaces/bi-mmm-decision-intelligence/)
- [IAB Agentic Standards](https://nofluffadvisory.com/standards/iab-agentic-standards/)
- [Core AdTech Standards](https://nofluffadvisory.com/standards/core-adtech-standards/)
- [Privacy & Consent Standards](https://nofluffadvisory.com/standards/privacy-consent-platform-apis/)
- [Measurement & Media Quality](https://nofluffadvisory.com/standards/measurement-verification-media-quality/)
- [Writing: Agentic Advertising](https://nofluffadvisory.com/topics/agentic-advertising/)
- [Glossary: AdCP](https://nofluffadvisory.com/glossary/#adcp)
- [Embeddings in Advertising](https://nofluffadvisory.com/topics/embeddings/)

### Primary sources to validate (15 sources)

- [AdCP — Advertising Context Protocol (repository README)](https://github.com/adcontextprotocol/adcp) — AgenticAdvertising.org / adcontextprotocol. Official GitHub; confidence: primary; checked 2026-06-07. Authoritative expansion "AdCP - Advertising Context Protocol"; an open standard for advertising automation over MCP and A2A; reference implementation + docs. Supports: Official name, Scope, Transport (MCP/A2A), Stewardship.
- [AdCP Documentation — Introduction](https://docs.adcontextprotocol.org/docs/intro) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Defines AdCP as "an open agentic advertising standard" using MCP (tool calls) and A2A (agent-to-agent) — "same tasks, same schemas, different transport." Supports: What AdCP is, Transport model, Positioning.
- [AdCP docs index (llms.txt)](https://docs.adcontextprotocol.org/llms.txt) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Machine-readable docs index; enumerates the layered architecture (L0 wire/transport → L4 business logic) and the protocol domains + task references. Supports: Architecture layers, Domain/task index.
- [AdCP Media Buy Protocol](https://docs.adcontextprotocol.org/docs/media-buy/) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Inventory discovery, campaign creation, and delivery reporting. Verified tasks include get_products, create_media_buy, get_media_buy_delivery. Supports: Media Buy domain, Verified task names.
- [AdCP Creative Protocol](https://docs.adcontextprotocol.org/docs/creative/) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Creative from brief to delivery across CTV, display, social. Verified tasks include build_creative, preview_creative, list_creative_formats. Supports: Creative domain, Verified task names.
- [AdCP Signals Protocol (overview)](https://docs.adcontextprotocol.org/docs/signals/overview) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Discover and activate audience/contextual signals across data providers via natural language. Verified tasks: get_signals, activate_signal. Supports: Signals domain, Signal containerization link.
- [AdCP Accounts Protocol (overview)](https://docs.adcontextprotocol.org/docs/accounts/overview) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Commercial layer — billing, operator authorization, usage reporting. Verified tasks: list_accounts, sync_accounts, report_usage. Supports: Accounts domain, Verified task names.
- [AdCP Governance Protocol (overview)](https://docs.adcontextprotocol.org/docs/governance/overview) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Human oversight of autonomous buying via three-party separation of duties and signed governance tokens; embedded human judgment as the locus of accountability. Verified tasks: create_content_standards, calibrate_content. Supports: Governance domain, Human-in-the-loop, Verified task names.
- [AdCP Brand Protocol](https://docs.adcontextprotocol.org/docs/brand-protocol/) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Machine-readable brand guidelines via brand.json — the buy-side identity file paralleling publisher adagents.json. Supports: Brand domain, brand.json.
- [AdCP Registry](https://docs.adcontextprotocol.org/docs/registry/) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Public REST API for agent discovery, brand resolution, property lookup, and authorization; validates adagents.json (publisher) against brand.json (operator). Supports: adagents.json, Discovery/identity, Authorization.
- [AdCP Security Model](https://docs.adcontextprotocol.org/docs/building/concepts/security-model) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. Required idempotency_key on every mutating request; RFC 9421 HTTP Message Signatures (Ed25519/ECDSA P-256); correlated audit records; replay protection. Supports: Idempotency, Signatures, Audit, Trust layer.
- [AdCP Release Notes](https://docs.adcontextprotocol.org/docs/reference/release-notes) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-09-17. AdCP 3.1 reached GA at v3.1.0 (GitHub tag, June 18, 2026; wire pin "3.1"), patched through v3.1.2 (July 8, 2026 — protocol-only fixes and spec clarifications; a 3.0.x maintenance line continues in parallel). v3.1.3 (July 13) was withdrawn days later for adding a stable schema field in a patch release plus a publisher-domain filter bug; the docs route implementers around it to v3.1.2. Patches ran on to v3.1.23 (September 14, 2026), the latest stable tag — which carries the #7404 required_tools gate fix (#7405 on main, #7406 backported) and the v3.1.22 record correction (#7451). v3.1.21 (September 9) was a one-change patch (#7383) that scopes guaranteed idempotency replay to state-mutating requests, leaves idempotency_key optional on reads (an optional key now sits on the get_products request schema), and relaxes the read-tool-idempotency storyboard to match; the 3.1-era plan to make reads reject a missing key at 3.2 is withdrawn. v3.1.22 carries two patch changes — legacy format asset declarations aligned with the canonical asset union and guarded against drift (#7423), and Context Match embeddings derived from non-public single-user content restricted, with privacy reduction required for free-form context signals (#7424, the 3.1.x backport of #7396). That record is incomplete by the maintainers’ own account: #7451 merged on September 13, 2026 to correct it, the companion cache-partitioning fix (#7397) having shipped without changelog coverage, and landed the next day in v3.1.23 as commit 8a933df. The 3.2 line has been in release candidate since September 3, 2026 and moved three times in eleven days, most recently to v3.2.0-rc.3 on September 14, 2026: the docs call rc.3 the current signed protocol checkpoint and restrict it to development and staging, and the SDKs caught up on September 15 — @adcp/sdk 14.0.0-rc.37 and rc.38 and Python adcp 8.0.0b15 declare ADCP_VERSION 3.2.0-rc.3, while Go adcp/v3.2.1 remains on rc.1; the versions page still says no SDK embeds rc.3, held there until Go catches up (adcp-go#536) so the doc aligns once rather than twice. 3.2 hardens delivery, reach and vendor-metric semantics — naming Reliable Reporting as a discoverable capability, deprecating cross-buy delivery aggregates in favour of media-buy-level currency, disambiguating deduplicated from summed cross-buy reach, and adding a closed vendor_relationship enum (first_party / affiliated / third_party) so a seller must declare when it is its own measurement vendor. Every 3.1.x GitHub release body is version-only (the string "AdCP 3.1.13"), so per-patch detail comes from the repo CHANGELOG.md: 3.1.9 fixed a literal tab that made the runner output contract unparseable for strict YAML parsers in the packaged 3.1.4/3.1.5 compliance caches, and reshaped the experimental TMPX macro mapping while it has no production adopters; 3.1.10 published additive legacy Retina creative formats for seven standard display sizes and named list_accounts the recommended cold-start recovery read; 3.1.11 clarified that 3.1 SDKs preserve pixel-ratio registry metadata without interpreting it, with typed validation and precedence beginning in 3.2; 3.1.12 was documentation and comment text only; 3.1.13 gated two compliance-runner storyboards on capabilities the seller actually advertises. These are conformance-suite, docs, and additive registry changes — the repo docs on main list 3.1.4 through 3.1.21 as supported patches, wire-compatible with 3.1.0, and 3.1.23 as the latest stable patch, also wire-compatible, and state that supported patches do not change stable wire surfaces. They give 3.1.22 its own row: its emergency privacy/security corrections changed the explicitly experimental TMP contract under the recorded notice exception. Additive over 3.0. Production-hardening release: version negotiation, signed brand trust, canonical creative formats + transformers, vendor-attested measurement, required per-task idempotency. Feature detail lives in the official "What's New in 3.1" and 3.0→3.1 migration docs. Supports: Version status, AdCP 3.1 GA / v3.1.23, 3.2 release candidate, What's new in 3.1, 3.0→3.1 migration.
- [AdCP — What's new in v3](https://docs.adcontextprotocol.org/docs/reference/whats-new-in-v3) — AgenticAdvertising.org. Official docs; confidence: primary; checked 2026-06-07. 3.0 expands AdCP into brand identity, governance, media planning, and conversational brand experiences; v2 fully deprecated August 1, 2026 (UTC). Supports: 3.0 scope, Deprecation timeline.
- [AgenticAdvertising.org](https://agenticadvertising.org/) — AgenticAdvertising.org (AAO). Official standards page; confidence: supporting; checked 2026-06-07. The organization that publishes and governs AdCP — an industry body of publishers, platforms, agencies, and technology providers (in formation). Supports: Stewardship, Governance body.
- [IAB Tech Lab — Introducing the Agent Registry](https://iabtechlab.com/introducing-the-iab-tech-lab-agent-registry/) — IAB Tech Lab. Official standards page; confidence: primary; checked 2026-06-07. Trust/transparency layer for agent identity, verification, and disclosure; registrants associate a GPP ID (incl. TCF GVL IDs); the registry is itself an MCP server; "test and learn" phase. Supports: Agent Registry, Identity/verification, Status.

> Platform capabilities and naming change quickly. Last validated: 2026-09-17. Check current documentation before implementation.
