---
title: "Notes from the Implementer Seat"
date: 2026-06-13
summary: "What running a live AdCP signals agent teaches you that reading the spec never will. Revised September 2026: a privacy gap I filed against Trusted Match shipped in AdCP v3.1.22 — on stricter terms than I proposed, in a maintainer PR rather than mine — and two threads listed here as open proposals have since closed as completed."
standfirst: "Standards takes written from the spectator seat are weightless — nothing happens when you're wrong. Running a live AdCP signals agent is different: the freshness gap you file becomes a merged schema field, the compliance grader that wrongly grades your perfect run becomes a P0 fix, and your wire-size data backs a design concern in review. The diligence question for any agentic vendor: show me your issues, not your deck."
canonical: https://nofluffadvisory.com/writing/notes-from-the-implementer-seat/
---

Most standards commentary is written from the spectator seat. You read the spec, you form a take, you publish the take. The take is usually fine. It is also usually weightless, because nothing happens to you when you are wrong.

The implementer seat is different. I build and operate a live [AdCP](/writing/adcp-the-open-standard-for-agentic-advertising/) signals agent — the [No Fluff Advisory adaptor](/building/adcp-signals-adaptor/), listed in the AAO registry, with all-pass conformance runs across the 3.0 and 3.1.0 GA suites. When the protocol has a gap, my agent fails a storyboard at 2am. When the conformance grader has a bug, my dashboard says "Degraded" in front of anyone who looks. The protocol bills me for my opinions.

This essay is what that seat has taught me — told through the actual issues and pull requests, because in standards work the receipts *are* the argument.

## The freshness field nobody had

Run a signals agent for a while and you notice something the spec review never surfaced: a buyer agent receiving a signal record has no standard way to know how fresh it is. Is this audience definition from yesterday or from March? In a market where agents act on signals without a human sanity-check, that is not a metadata nicety. It is a trust gap.

So I filed the gap analysis ([#5248](https://github.com/adcontextprotocol/adcp/issues/5248)) and authored the fix: a `last_updated` field on signal-definition ([PR #5249](https://github.com/adcontextprotocol/adcp/pull/5249)), merged and shipping in the 3.1.0 line since rc.7.

**The lesson:** protocol gaps appear at runtime, not in document review. Nobody reads a schema and thinks "this lacks a freshness contract." You only feel it when your agent has to decide whether to act on a record of unknown age.

## When the grader lies

In June, a rollup regression in the compliance grader started rendering all-pass single-protocol runs as "Degraded." My agent had a perfect run and a failing grade. For a registry-listed agent, that is not cosmetic — conformance status is the product.

I root-caused it to the exact commit that introduced it, filed it ([#5429](https://github.com/adcontextprotocol/adcp/issues/5429), auto-triaged P0), and authored the fix a maintainer merged ([PR #5444](https://github.com/adcontextprotocol/adcp/pull/5444)).

**The lesson:** the conformance tooling is part of the standard. A spec with a buggy grader is a buggy spec, operationally — because what implementers and buyers experience is the grade, not the prose. If you are evaluating an agentic vendor, ask who fixes the test harness when it is the harness that is wrong.

## Deprecating politely

Earlier in the cycle, the webhook-signing guidance still carried a deprecated HMAC framing. I inventoried every place it leaked into the storyboards and SDK on-ramps ([#4270](https://github.com/adcontextprotocol/adcp/issues/4270)) and drafted the PRs pointing the defaults at RFC 9421 ([#4273](https://github.com/adcontextprotocol/adcp/pull/4273), [#4275](https://github.com/adcontextprotocol/adcp/pull/4275)). Those drafts were closed in favor of the maintainer implementation — which is exactly how it should work — and the 3.0.9 line realigned away from HMAC.

**The lesson:** sometimes your contribution is the case, not the commit. Standards bodies run on maintainer trust; an implementer who insists on landing their own patch over making the argument well is optimizing for credit instead of the protocol.

## A test suite is only as real as its edge cases

Signals-only agents used to fail storyboards that had nothing to do with them — media-buy gating applied to agents that never buy media, error-handling tracks gated behind tasks a signals agent does not implement, envelope assertions against transport responses where the field does not exist.

Six root-caused reports later ([#2916](https://github.com/adcontextprotocol/adcp/issues/2916), [#3350](https://github.com/adcontextprotocol/adcp/issues/3350), [#4009](https://github.com/adcontextprotocol/adcp/issues/4009), and 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)), the 3.1.0 suite skips non-applicable gating and gives signals-only agents dedicated error-handling and schema-validation storyboards.

**The lesson:** a standard claims to support a class of participant; the test suite decides whether that claim is true. Single-protocol agents are the canary for whether "modular" is real.

## Review is where implementers earn their seat

The most consequential signals work in the current cycle — the signal-definition epistemic and provenance layer ([#5017](https://github.com/adcontextprotocol/adcp/pull/5017)) — was opened under the maintainer account, not by me. My contribution was review, and one piece of data the thread did not yet have — actual wire sizes from my live agent. Five signals came to 88,590 bytes against a 64 KB probe ceiling before any of #5017’s new fields, though that was pretty-printed, and our own `x_*` extension blocks made up most of each signal’s bytes by the breakdown I posted; compacted, it was an estimated 60 KB. The point was what the new fields would add on top: 3–5 KB a signal, by my estimate. That backed a progressive-disclosure concern another reviewer had already raised, and before the merge the maintainer account added compact-by-default guidance and a `fields` selector on `get_signals`. My field-level schema notes came an hour after the merge; the follow-up, [#5190](https://github.com/adcontextprotocol/adcp/pull/5190), addressed them without citing them, not always my way.

**The lesson:** implementers bring evidence to review that no amount of careful reading can produce. And crediting the author accurately is not modesty — in a working group, overclaiming is how you lose the seat.

*(Revised September 17, 2026 — this section said five “enriched” signals weighed in at 88 KB and that the number “drove” the progressive-disclosure design. The signals carried none of #5017’s new fields, the 88,590 bytes were pretty-printed (my comment on #5017 did not say so), another reviewer raised progressive disclosure first, and my schema notes came after the merge and were taken up, uncited, in the follow-up #5190.)*

## Interoperability is a crosswalk problem, not a primitive problem

A newer thread shows the same discipline from a different angle: geographic cell targeting. RFC [#5969](https://github.com/adcontextprotocol/adcp/issues/5969) defines `geo_cells` / `geo_cells_exclude` as the addressable unit for geo targeting — deliberately not defining what a seller does when it cannot execute on that unit natively, which is every seller today. The WG named that gap decision point X-A vs. X-B; the resolution (X-B) keeps the wire contract minimal ("MUST NOT deliver outside the declared cells") and pushes the conversion machinery into a companion document instead of the normative surface.

Working with Nathan Woodman ([@nwoodman-spec](https://github.com/nwoodman-spec)), I filed both halves of that companion: cell-to-execution conversion ([#6013](https://github.com/adcontextprotocol/adcp/issues/6013)) and cell-grain delivery reporting ([#6014](https://github.com/adcontextprotocol/adcp/issues/6014)). The #6014 design — `cell` as a fifth `geo_level`, inheriting the existing per-level reporting apparatus rather than a parallel array — is one I proposed on [#5969](https://github.com/adcontextprotocol/adcp/issues/5969); Nathan wrote the full specification.

A small confession is part of the record: an earlier comment on [#5969](https://github.com/adcontextprotocol/adcp/issues/5969) referenced the reporting companion by a placeholder number that never got replaced. Nathan went looking for it while writing #6013 and correctly couldn't find it. [I fixed the record](https://github.com/adcontextprotocol/adcp/issues/5969#issuecomment-5074516723) once both issues existed, accepted the one sentence [#5969](https://github.com/adcontextprotocol/adcp/issues/5969) needed in its own normative text (binding the delivery restriction to the seller's *output footprint*, not its internal representation), and added a privacy-considerations note a third contributor pushed on: a resolution floor alone doesn't protect a sparse cell, and an audience floor alone doesn't stop someone from drawing geometry around one household — you need both, stated together.

**The lesson:** a placeholder reference is a debt against your collaborator's time, not a stylistic shortcut — fix it before someone goes looking for it. And the same interoperability argument that justifies a spatial base unit generalizes cleanly to time: my [draft framing](https://github.com/adcontextprotocol/adcp/issues/5969#issuecomment-5074526067) for a temporal companion proposes UTC hour-of-week as the base unit, with broadcast-day conventions as declared, versioned crosswalks onto it — never the reverse — for the same reason `geo_cells` doesn't defer to administrative boundaries. It's still a draft, posted for a gut check before it goes anywhere formal. That's the nature of the seat: some proposals are load-bearing before you're sure they're right.

## The embedding on the rung that says don't share the content

AdCP 3.1.21 shipped Trusted Match with a `context_signals.embedding` field on the classified-output tier — the tier whose entire purpose is that the raw content does not travel. On an `ai_assistant` property the "content environment" is one person's conversation turn, and a dense vector of that turn is partially invertible back to their words. A field that exists to avoid sharing content was carrying it.

I filed that against v3.1.21 with the inversion literature and two additive text edits ([#7393](https://github.com/adcontextprotocol/adcp/issues/7393)), then opened a PR of my own ([#7415](https://github.com/adcontextprotocol/adcp/pull/7415)). The fix that shipped was not mine. A maintainer wrote [#7396](https://github.com/adcontextprotocol/adcp/pull/7396) four days after the issue, it was backported to the 3.1 line as [#7424](https://github.com/adcontextprotocol/adcp/pull/7424), and it went out in **v3.1.22** on September 13, 2026. My PR is still open.

That is the second time in this essay the same thing has happened, and it is worth naming rather than smoothing over: the argument landed, the patch did not. Nor did the maintainers take my proposal as written — I argued for a demonstrate-on-request carve-out, they chose a flat prohibition, and they added policy-filtering rules on `keywords` and `summary` my issue never asked for. The stricter route was the better one. Being overruled upward is still being overruled, and "I filed the issue that became v3.1.22" is a sentence that needs the rest of this paragraph attached to it.

The companion thread did not land at all. Triage asked me to split out the cache problem, since it carried no privacy dependency: the recommended Context Match 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 correctness half shipped in [#7397](https://github.com/adcontextprotocol/adcp/pull/7397) as a `{provider_id, context_hash}` key over the full forwarded request; my issue was closed **not planned** — superseded, not implemented — and the steer toward `cache_ttl: 0` for viewer-variable placements was not taken up.

That release's changelog is itself incomplete, by the maintainers' own account: [#7451](https://github.com/adcontextprotocol/adcp/pull/7451), filed by a maintainer and merged September 13, corrected the v3.1.22 record in v3.1.23 the next day, because #7397 shipped without changelog coverage. Every 3.1.x release body on GitHub is version-only — the v3.1.22 body is literally the string "AdCP 3.1.22". If you are auditing anyone's contribution claims, mine included, the release notes will not help you. The repository will.

*(Added September 13, 2026. This essay published in June, and this is the clearest instance it has of the thing it argues for, so it belongs in the body rather than in a footnote.)*

## What I am proposing next

Two open threads, stated as proposals because that is what they are:

- **A revocation primitive** — `revoke_activation` ([#4203](https://github.com/adcontextprotocol/adcp/issues/4203)), because governed activation without governed un-activation is half a contract. Alongside it, a Measurement Feedback Signal ([#4296](https://github.com/adcontextprotocol/adcp/issues/4296)).
- **Migration coordination** — the JWKS adoption baseline that gates chain-of-custody work ([#4206](https://github.com/adcontextprotocol/adcp/issues/4206)). Deprecations without adoption data are just wishes.

All of these may merge, change, or close. That is the nature of the seat.

*(Revised September 13, 2026 — two threads listed here have since closed as completed and have moved out of the proposal list: runtime signal-quality attestations on `check_governance` ([#5418](https://github.com/adcontextprotocol/adcp/issues/5418)) and the RFC 9421 webhook-signing migration coordination ([#4205](https://github.com/adcontextprotocol/adcp/issues/4205)). Leaving shipped work filed under "proposing next" understates the record — the direction of error nobody thinks to check for.)*

## The operator takeaway

If you are a buyer, a board, or an operator evaluating anyone's agentic advertising story — including mine — the diligence question is simple: **show me your issues, not your deck.** A vendor who runs a live agent against the public conformance suite has receipts: merged PRs, root-caused bugs, review contributions with data, proposals that survived contact with maintainers. A vendor who does not will show you architecture slides.

The implementer seat is slower than the spectator seat. It is also the only seat where you find the freshness gaps, catch the grader lying, and learn what five signals actually weigh on the wire.

That discomfort is the point.

---

*The full contribution record, with statuses validated against the public AdCP repository, lives on the [AdCP protocol guide](/standards/adcp/#implementer-seat). The agent itself is documented at [Building: AdCP Signals Adaptor](/building/adcp-signals-adaptor/).*
