On September 22, 2026 IAB Tech Lab shipped AAMP 3.0 with OpenProposal, a draft spec for how seller agents describe ad products and how buyer agents compare those representations to a campaign brief. Public comment runs through October 22. IAB Australia opened a seller sandbox the same week to exercise discovery and proposal flows on synthetic data, with live spend out of scope.
That is the right problem to automate. A human media team can read three RFP responses. Software cannot compare thousands unless every seller encodes what they are selling the same way. OpenProposal is that encoding layer, wired to the transaction rails Tech Lab already publishes: AdCOM, OpenDirect, and the Deals API.
The failure mode shows up one hop later, when the accepted line item is not a signed insertion order sitting in a folder but an auction call.
Two stages, one wire format
OpenProposal lives in the planning stage. The buyer agent holds a brief: channel, geography, budget band, format constraints, maybe a content taxonomy slice. Seller agents return structured products. The buyer agent scores fit.
AAMP 2.x already supports programmatic guaranteed, preferred deals, PMP lines, and the open marketplace through the same buyer and seller SDKs. When the winning path is programmatic, execution is still an OpenRTB bid request and response pair on the exchange you already operate. Nothing in OpenRTB names which OpenProposal response won. There is no proposal_id, no back-pointer to the brief version, and no guarantee that the imp.video object still carries the duration or placement semantics the comparison used.
AdCP negotiates version on every message and returns a typed error when buyer and seller disagree. AAMP 2.3 added trust verification on price-moving paths. OpenRTB still agrees its dated snapshot in onboarding docs, not in the JSON. We wrote about that asymmetry in the agentic version negotiation gap. OpenProposal adds a third layer: a structured comparison that never has to survive into the auction object.
Duration is the easy miss
Live CTV breaks on imprecise creative length. OpenRTB 2.6 added rqddurs, an array of exact acceptable durations in seconds. It is mutually exclusive with minduration and maxduration. Sports and news pods use it because a 29 second ad in a 30 second slot is dead air.
Suppose the brief asks for 15 and 30 second pods. OpenProposal matching scores a seller product that advertises those exact lengths under AdCOM placement semantics. The buyer agent accepts the proposal, then builds the programmatic hop from a template that still sets a range:
"video": {
"mimes": ["video/mp4"],
"protocols": [7, 8],
"minduration": 5,
"maxduration": 60,
"plcmt": 1
}
The JSON is well formed. A DSP can bid 6, 12, or 45 second VAST tags that satisfy the range. Every tag violates what the brief and the proposal comparison already agreed. Quartile and podding logic downstream assumes the tighter contract.
The fix on the wire is not a comment in the SDK README. It is replacing the range with the exact set the proposal scored:
"rqddurs": [15, 30]
and dropping minduration and maxduration entirely. RTBlint flags the mutual exclusivity and the 2.6 field set in the rqddurs rule doc. The CTV OpenRTB guide is the field map for pod bidding (podid, slotinpod, rqddurs, duration floors).
validate_bid_request is not a brief checker
An implementation that lets a model emit the auction JSON still has to check that JSON against the OpenRTB snapshot the exchange runs. rtblint (cargo install rtblint, npm install rtblint-core, MCP rtblint-mcp) is that check on the bid request and bid response. It is independent of IAB Tech Lab and of AAO. The spec does not require it.
The hosted MCP server exposes validate_bid_request with an optional version argument. Omit version and validation defaults to the latest tracked 2.6 dated release in the build, not necessarily the snapshot your SSP pinned in a PDF three years ago. Pass the wrong id and you get a structured finding rather than a silent pass against the wrong rule set. See openrtb-version-unsupported for what that looks like on the wire.
$ rtblint validate --dialect spec-json bid.json
ok: true
# same bytes, exchange on 2.6-202303 with rqddurs sent alongside minduration:
$ rtblint validate --version 2.6-202303 bid.json
rule: openrtb-2.6-imp-video_audio-rqddurs
severity: error
message: rqddurs is mutually exclusive with minduration and maxduration
The tool validates the auction object, not the RFP story. If your pipeline only checks JSON Schema on the OpenProposal response and then forwards a hand-written imp, you can ship a buy that never existed in the comparison step.
Pin version to the exchange contract on every forward. Cross-check imp.video.plcmt and related AdCOM placement fields against what OpenProposal scored. AdCOM moved placement to plcmt with a different enum; echoing 2.5 integers without cattax and subtype discipline mislabels inventory. The plcmt migration write-up is still the readable map for teams that lived through the rename.
For video lines that clear to VAST, the auction check is only half the hop. Run the live ad tag through the VAST tag tester for fetch, preview, and tracking URLs, then the VAST inspector for wrapper hops. vastlint owns that XML payload. OpenProposal JSON does not substitute.
Where to read next
-
MCP tools and AdCP discovery for wiring
validate_bid_requestinto a buyer agent loop. -
Video object fields including
rqddursversus duration ranges. - Agentic version negotiation on OpenRTB for why the auction layer still lacks an on-wire snapshot id even while AAMP and AdCP argue about versions above it.
OpenProposal public comment is open until October 22, 2026. Whether or not the draft gains a formal bridge field in a later revision, production paths already split planning from execution. Treat the forwarded bid request as a separate contract and validate it like one.
Top comments (0)