DEV Community

Aleksander Sekowski
Aleksander Sekowski

Posted on

AAMP Can Finish a Video Buy With a Wrapper. It Cannot Prove the InLine Exists.

An AAMP buyer agent completes a programmatic video buy and returns a VAST tag URL. The task status is success. The deal is in the Deals Library. Nobody has followed the URL.

Two weeks later fill is at forty percent and the report says "no ad response." The tag the agent negotiated is a <Wrapper> pointing at another host. That second hop is another wrapper. The third hop times out on CTV. Google IMA stops at four hops. The slot goes empty. Nothing in the agent transcript says anything failed, because nothing in the agent layer required anyone to resolve the chain.

IAB Tech Lab's Agentic Advertising Management Protocols (AAMP) is explicit about keeping VAST as the video envelope. OpenRTB stays the auction rail. AdCOM stays the object model. The agent negotiates above or beside those layers, and what ships to the player is still XML. That design is coherent. It also means the last mile is identical to the last mile you already had: a URL that may be a redirect graph, not a creative.

What "delivery" means in an agentic buy

AAMP 2.0 brought programmatic into scope with buyer and seller agent SDKs that can transact over MCP. AAMP 2.3 added operational gates: diligence checks, server-side trust verification on price-moving paths, deployment targets on Bedrock and Databricks. Those are real controls on money and authorization.

None of them fetch VAST.

Read the IAB agentic advertising standards guide next to the agentic buying and OpenRTB primer and the split is obvious. ARTF agents may rewrite bid requests mid-auction. AdCP-style negotiation may produce a deal ID that shows up in imp.pmp.deals. Either way, when the format is video, execution still collapses to a tag endpoint.

That endpoint can legally be hop one of a wrapper chain. VAST 2.0 through 4.x all allow a <Wrapper> with a <VASTAdTagURI> instead of an <InLine>. SSPs, DSPs, and measurement vendors stack wrappers because each hop carries its own impression and error beacons. The pattern is normal. Treating the first URL as proof of delivery is not.

A wrapper-only response validates against schema. It can return HTTP 200 with well-formed XML and still never reach media. The player needs an <InLine> with a <MediaFile> somewhere downstream, within a depth budget that varies by platform (four hops on IMA and most CTV stacks). An agent that stops at the negotiated URI has verified negotiation, not playback.

The failure modes wrappers hide

These are the ones I see after an agent handoff, not the ones a JSON Schema catches.

Depth exceeded. Four wrappers before the inline is common in open market paths. A fifth hop fails silently on CTV. The outer wrapper often has no <Error> URL, so reporting shows underdelivery with no VAST error code.

Circular or dead URIs. A misconfigured ad server points <VASTAdTagURI> back to itself or to a 404 that returns HTML with a 200 status. The agent never requested the body. The wrapper chains guide lists platform limits and the checklist; circular chains are almost always configuration, and they are invisible until something walks the graph.

followAdditionalWrappers="false" mid-chain. A wrapper that sets this attribute tells the player to stop even if the next response is another wrapper. The chain aborts at that hop. Schema-valid, unplayable.

Wrong host on the inline. The wrapper you tested is not the creative that plays. The InLine lives on a different CDN with a different duration and a different tracking set. That is a separate bug, but wrapper-first QA makes it worse because you never saw the terminal document.

Version drift across hops. Hop one declares VAST 4.2. Hop three uses 3.0 elements. Players pick rules per document. An agent that recorded "4.2" in a deal artifact did not open either file.

AdCP's creative protocol has the same blind spot at the asset layer: a manifest can declare a VAST URL and optional metadata without parsing the tag. AdCP can declare a VAST tag; it cannot check one. AAMP and AdCP disagree about where agents sit, but they agree that VAST stays the envelope. Neither specification resolves wrappers for you.

How to catch it before the flight

Split the job the way players split it.

Step one: the live tag URL in the VAST tag tester. Paste the URI the agent returned, not a saved XML snippet from an earlier debug session. The tester fetches what the endpoint serves now, previews the creative when it can, and surfaces tracking and click URLs on the response it actually got. If hop one is a wrapper, you see wrapper structure immediately.

Step two: the same URL in the VAST inspector. The inspector resolves hop by hop. It reports chain depth, where each <VASTAdTagURI> points, and whether the chain terminates in an <InLine>. That is the check the agent task skipped. If depth is four and your target platform is Roku or Fire TV, you already know you are at the limit before the first impression.

Step three: validate the terminal XML. Once the inspector shows the inline, run structural rules on that document: Duration in HH:MM:SS, required Impression, HTTPS media files, declared version against elements used. CLI or MCP if the agent pipeline needs automation; the tester and inspector are the human and agent-facing entry points.

Wire this into the agent loop the same way you would wire OpenRTB validation after an ARTF mutation. The version negotiation gap on OpenRTB is a parallel problem: the handshake succeeds while the payload downstream is wrong for the receiver. Here the receiver is the player, and the payload is three redirects away.

Where the check belongs

If you host a buyer agent, treat "tag URI received" as an intermediate state, not COMPLETE. Resolve the chain (or call a tool that does) before writing the deal to your system of record.

If you sit on the sell side, reject or flag creatives whose entry URL does not terminate in an inline within your platform's depth budget. The cost of a retry in the agent protocol is lower than the cost of a week of silent no-fill.

If you are comparing stacks, the AAMP, AdCP, and OpenRTB landscape write-up is useful context, but the invariant is stack-agnostic: agents changed who negotiates; VAST still defines what renders.

AAMP's trust work on price-moving paths is worth having. It does not replace proving the creative exists. The tag URL is an address, not an ad. Follow it.

Top comments (5)

Collapse
 
vinhnguyenthanhdn profile image
Vinh Nguyen

Chain depth is only one budget; the resolver also needs one monotonic end-to-end deadline. Four individually acceptable hop timeouts can still exceed the player startup budget, so a useful negative control is a chain where every hop responds just under its per-hop timeout but the aggregate must still fail before playback.

Collapse
 
aleksuix profile image
Aleksander Sekowski

Yeah. Depth is the hop budget the spec talks about; the player still has a wall clock. Roku RAF gives you three seconds for the whole chain. Fire TV is five. VAST 301 is that timeout, not 302.

A four-hop chain that spends two and a half seconds per hop looks healthy if you only check per-hop timeouts, and still never starts playback. The inspector I pointed at currently gives each hop ten seconds, which is the wrong shape for the control you described. Four hops at nine seconds would still resolve in the tool.

The fixture I want is exactly the one you named: every hop answers just under its own timeout, aggregate over the player budget, expect 301.

Collapse
 
vinhnguyenthanhdn profile image
Vinh Nguyen

One thing that fixture needs alongside the expected 301: an assertion about attribution. When the aggregate budget trips, the naive implementation reports whichever hop was in flight, so the operator tunes that hop timeout and the chain still never plays. It also matters where the clock starts - if it starts at the first hop response rather than at the player request, DNS and TLS on every hop sit outside the budget you are trying to enforce.

Collapse
 
crdtcto profile image
Kane Lim

This is an important architectural distinction: “the agent successfully negotiated a VAST URL” is not equivalent to “the player can successfully render the ad.”

The wrapper-chain example exposes a broader problem with agentic systems: success criteria often terminate at the protocol boundary instead of the execution boundary.

For an agent handling video inventory, I’d model the lifecycle more explicitly:

Negotiated → Retrieved → Resolved → Validated → Playable

A VAST URL should therefore be treated as an intermediate artifact until the resolver confirms that the chain terminates in a valid containing an appropriate .

The useful part is that this can become a deterministic machine-checkable contract rather than relying on human QA. For example, the resolver could record:

maximum wrapper depth allowed by the target player
every hop and HTTP response
redirect/cycle detection
followAdditionalWrappers behavior
VAST version at each hop
terminal presence
media type/codec compatibility
HTTPS and timeout requirements
impression/error tracking availability

Then the agent can return something much more meaningful than status=success:

negotiation=success
vast_resolution=success
terminal_inline=success
playability=validated

That separation also makes failures dramatically easier to diagnose. A failed campaign could be attributed to negotiation, retrieval, wrapper resolution, terminal creative validation, or player compatibility instead of collapsing everything into “no ad response.”

I also think this principle extends beyond advertising. Agentic workflows need execution-level assertions at every boundary where an artifact is handed to another system. Schema validation proves that something is structurally acceptable; end-to-end validation proves that the next consumer can actually use it.

That would make “delivery readiness” a first-class capability of the agent rather than an assumption after the deal is created.

Interesting problem space. I’d be glad to exchange ideas around building these kinds of validation/automation layers and potentially collaborate on longer-term engineering projects as well.

Collapse
 
aleksuix profile image
Aleksander Sekowski

Agree on the state machine. Negotiated is just we have a URL. I would not write the deal complete until Playable.

Most of that checklist is what a hop walk already returns: depth, each URI, cycles, followAdditionalWrappers, version per document, whether it terminated in an InLine. Playable is the extra gate. An InLine with a MediaFile the target player cannot decode is still not playable.

Keep those statuses split. If the agent collapses them into one success flag, you are back to a week of silent no-fill.