Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 77 additions & 44 deletions examples/seller_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ async def get_adcp_capabilities(
"simulate_budget_spend",
],
},
# adcp.idempotency is required by spec (get-adcp-capabilities-response.json)
idempotency={"supported": False},
)

async def sync_accounts(self, params: dict[str, Any], context: Any = None) -> dict[str, Any]:
Expand Down Expand Up @@ -223,27 +225,35 @@ async def create_media_buy(self, params: dict[str, Any], context: Any = None) ->
}
)

# check input packages (not the built output) — creatives live on the request pkg
has_creatives = any(
pkg.get("creatives") or pkg.get("creative_assignments")
for pkg in params["packages"]
)
status = "active" if has_creatives else "pending_creatives"
mb_id = f"mb-{uuid.uuid4().hex[:8]}"
media_buys[mb_id] = {
"status": "active",
"status": status,
"currency": "USD",
"packages": packages,
"revision": 1,
}
return media_buy_response(mb_id, packages, status="active")
return media_buy_response(mb_id, packages, status=status)

async def get_media_buys(self, params: dict[str, Any], context: Any = None) -> dict[str, Any]:
requested_ids = params.get("media_buy_ids")
results = []
for mb_id, mb in media_buys.items():
if requested_ids and mb_id not in requested_ids:
continue
pkgs = mb.get("packages", [])
results.append(
{
"media_buy_id": mb_id,
"status": mb["status"],
"currency": mb.get("currency", "USD"),
"packages": mb.get("packages", []),
"total_budget": sum(pkg.get("budget") or 0 for pkg in pkgs), # None for flat-rate pkgs
"packages": pkgs,
}
)
return media_buys_response(results)
Expand All @@ -257,6 +267,19 @@ async def update_media_buy(self, params: dict[str, Any], context: Any = None) ->
if params.get("revision") and params["revision"] != mb.get("revision", 1):
return adcp_error("CONFLICT", "Revision mismatch - refetch and retry")

if params.get("packages"):
existing_pkg_ids = {pkg["package_id"] for pkg in mb.get("packages", [])}
for pkg_update in params["packages"]:
if pkg_update.get("package_id") not in existing_pkg_ids:
return adcp_error(
"PACKAGE_NOT_FOUND",
"Package not found in this media buy",
field="packages",
)
# Note: this reference implementation validates package IDs but does not
# apply budget/targeting updates. A production seller should merge pkg_update
# fields back into mb["packages"] here.

status = mb["status"]
if params.get("paused") is True and status == "active":
mb["status"] = "paused"
Expand All @@ -274,50 +297,60 @@ async def update_media_buy(self, params: dict[str, Any], context: Any = None) ->
async def list_creative_formats(
self, params: dict[str, Any], context: Any = None
) -> dict[str, Any]:
return creative_formats_response(
[
{
"format_id": {
"agent_url": AGENT_URL,
"id": "display_300x250",
},
"name": "Display 300x250",
"renders": [{"width": 300, "height": 250}],
"assets": [
{
"item_type": "individual",
"asset_id": "image",
"asset_type": "image",
"required": True,
"accepted_media_types": [
"image/png",
"image/jpeg",
],
}
],
all_formats: list[dict[str, Any]] = [
{
"format_id": {
"agent_url": AGENT_URL,
"id": "display_300x250",
},
{
"format_id": {
"agent_url": AGENT_URL,
"id": "display_970x250",
},
"name": "Display 970x250",
"renders": [{"width": 970, "height": 250}],
"assets": [
{
"item_type": "individual",
"asset_id": "image",
"asset_type": "image",
"required": True,
"accepted_media_types": [
"image/png",
"image/jpeg",
],
}
],
"name": "Display 300x250",
# role is required; width/height must be nested under dimensions
"renders": [{"role": "primary", "dimensions": {"width": 300, "height": 250}}],
"assets": [
{
"item_type": "individual",
"asset_id": "image",
"asset_type": "image",
"required": True,
"accepted_media_types": [
"image/png",
"image/jpeg",
],
}
],
},
{
"format_id": {
"agent_url": AGENT_URL,
"id": "display_970x250",
},
"name": "Display 970x250",
# role is required; width/height must be nested under dimensions
"renders": [{"role": "primary", "dimensions": {"width": 970, "height": 250}}],
"assets": [
{
"item_type": "individual",
"asset_id": "image",
"asset_type": "image",
"required": True,
"accepted_media_types": [
"image/png",
"image/jpeg",
],
}
],
},
]
# format_ids is optional per spec: absent means return all formats
# match on compound (agent_url, id) key — correct for multi-agent deployments
requested = params.get("format_ids")
if requested:
keys = {(r.get("agent_url"), r.get("id")) for r in requested}
all_formats = [
fmt for fmt in all_formats
if (fmt["format_id"]["agent_url"], fmt["format_id"]["id"]) in keys
]
)
return creative_formats_response(all_formats)

async def sync_creatives(self, params: dict[str, Any], context: Any = None) -> dict[str, Any]:
results = []
Expand Down
Loading