Wire response ≠ model context
The single most important point: the bytes on the wire are not what your model has to consume. AdCP responses are structured data. An MCP response arrives asstructuredContent — typed JSON that the client parses before any model sees it. An A2A response pairs a human-readable TextPart with an authoritative DataPart. In both cases, a well-built client stores the full response and projects or summarizes it before prompting the next model turn.
Ask for a plan when you want curation
Userequest_proposals when the seller should turn a campaign brief into a
small set of actionable plans:
refine_proposals requests to narrow the plan without retransmitting the
full source response.
Use list_products instead when the buyer wants published offers or maintains
a wholesale mirror. A mirror is a feed-synchronization topology, not a cheaper
proposal mode.
fields selector for lightweight discovery
When you only need a subset of published product data, pass fields to
list_products:
- Your agent is scanning multiple sellers and only needs IDs and prices for initial comparison
- You want to skip heavy fields like
product_card,product_card_detailed,placements, or signal metadata - You’re building a summary view before drilling into specific products
fields, the seller returns the full product object — including visual card definitions, placement specs, and any bundled signal metadata. For a first-pass discovery across multiple sellers, that’s more data than you need.
Pagination for cardinality control
list_products uses cursor-based pagination:
Response:
Pass
next_cursor into the next list_products request. A mirror stores
feed_version with its cache_scope and uses account-level product webhooks
for routine changes. Conditional reads with if_feed_version repair gaps or
confirm that a selected feed is unchanged; they do not replace a healthy
webhook stream.
Truncation flags on delivery
get_media_buy_delivery returns breakdown arrays (by geo, by creative, by day, etc.) that can grow large. Each breakdown array has a sibling boolean flag — by_geo_truncated, by_creative_truncated, etc. — that tells you whether the returned rows are the complete set or just the top-N:
When a flag is
true, the returned rows are sorted by the requested metric descending — you have the most significant breakdowns, and the tail is omitted. This is by design: delivery breakdowns are for optimization decisions, not archival reporting. If you need the full dataset, use the seller’s native reporting API.
Putting it together
A token-efficient AdCP integration follows this pattern:- Use
request_proposalsfor seller curation. Ask for plans instead of downloading a feed and prompting a model to rediscover seller expertise. - Use typed
refine_proposals. Carry proposal IDs and changes, not the full prior response, into the next turn. - Store raw responses client-side. Don’t feed full product objects into the model context. Extract what matters, summarize the rest.
- Read truncation flags before paginating delivery. If
by_geo_truncated: false, you already have everything — no need for follow-up calls. - Treat wholesale as synchronization. Bootstrap with
list_products, apply product webhooks, and use versioned reads for repair.
Discovery and planning
Choose published offers, wholesale mirroring, or seller-planned proposals.
list_products reference
Field selection, cursor pagination, feed versions, and mirror repair.
Delivery reporting
Breakdown arrays, truncation flags, and sort semantics.
How agents communicate
MCP vs A2A transport and how responses are structured.
Media products
Product structure,
product_card vs product_card_detailed, and rendering.