Summary
After #855, the Python SDK exposes resolve_requested_adcp_version(), which is useful, but seller applications still have to wire the versioning contract manually inside tool handlers.
That leaves generic protocol behavior in every adopter:
- Resolve the buyer's requested AdCP release from request payload fields.
- Default omitted/legacy buyers to the correct 3.0 compatibility behavior.
- Convert unsupported versions into a protocol error.
- Project media-buy responses into the requested release shape.
- Keep MCP and A2A behavior consistent.
This should be automatic in the SDK/server dispatch layer. Seller handlers should be able to return the canonical current response model, and the server should serialize the correct wire shape for the buyer.
Current adopter-side code
Prebid Sales Agent currently has to carry local code equivalent to:
SUPPORTED_ADCP_VERSIONS = ("3.0", "3.1-beta.3")
requested_adcp_version = resolve_requested_adcp_version(
request_payload,
supported=SUPPORTED_ADCP_VERSIONS,
)
if requested_adcp_version == "3.0" and response.status == "completed":
response.status = response.media_buy_status
del response.media_buy_status
The real code is more defensive, but the important point is that it is protocol negotiation and response projection, not seller business logic.
Expected
The SDK/server layer should own version negotiation and response serialization:
- Resolve the requested version once during dispatch.
- Reject unsupported versions before invoking the platform handler, or expose a standard exception mapping.
- Expose the resolved version on
RequestContext for legitimate business-logic cases.
- Normalize versioned response shapes after the handler returns, for both MCP and A2A.
- Keep this behavior aligned with advertised
supported_versions.
Then a seller can implement create_media_buy/update_media_buy once and return the current canonical model:
{
"status": "completed",
"media_buy_status": "pending_creatives"
}
The SDK would emit legacy 3.0 wire shape for 3.0 buyers:
{
"status": "pending_creatives"
}
and 3.1 shape for explicit 3.1 buyers:
{
"status": "completed",
"media_buy_status": "pending_creatives"
}
Why this matters
If this stays in seller code, every adopter has to rediscover the same edge cases and keep MCP/A2A behavior aligned by hand. That is exactly the kind of SDK workaround that will fragment implementations.
Related follow-ups from the same integration pass:
Summary
After #855, the Python SDK exposes
resolve_requested_adcp_version(), which is useful, but seller applications still have to wire the versioning contract manually inside tool handlers.That leaves generic protocol behavior in every adopter:
This should be automatic in the SDK/server dispatch layer. Seller handlers should be able to return the canonical current response model, and the server should serialize the correct wire shape for the buyer.
Current adopter-side code
Prebid Sales Agent currently has to carry local code equivalent to:
The real code is more defensive, but the important point is that it is protocol negotiation and response projection, not seller business logic.
Expected
The SDK/server layer should own version negotiation and response serialization:
RequestContextfor legitimate business-logic cases.supported_versions.Then a seller can implement
create_media_buy/update_media_buyonce and return the current canonical model:{ "status": "completed", "media_buy_status": "pending_creatives" }The SDK would emit legacy 3.0 wire shape for 3.0 buyers:
{ "status": "pending_creatives" }and 3.1 shape for explicit 3.1 buyers:
{ "status": "completed", "media_buy_status": "pending_creatives" }Why this matters
If this stays in seller code, every adopter has to rediscover the same edge cases and keep MCP/A2A behavior aligned by hand. That is exactly the kind of SDK workaround that will fragment implementations.
Related follow-ups from the same integration pass:
outputSchemastill rejects negotiated 3.0 media-buy success statuses.status: "canceled"with task cancellation.