Skip to content

feat(decisioning): built-in helpers for buyer-side request-shape parameters on get_products (parent tracker) #491

@bokelley

Description

@bokelley

Motivation

get_products carries a number of request-shape parameters that are buyer-facing protocol concerns, not seller business logic: fields projection, pagination, property_list, time_budget, refine, plus the cross-tool implementation_config plumbing on create_media_buy. Every adopter writes substantively the same code to handle them. The framework should ship these as capability-gated helpers — same pattern as the F12 sync-completion webhook auto-emit (src/adcp/decisioning/webhook_emit.py): adopter declares the capability, framework intercepts at the right seam, business logic stays focused on inventory.

Brian's framing: "this is one of the many things we can do to help the user not have to build all these utilities."

Reference: salesagent today

Salesagent (src/core/tools/products.py:94-142) inlines its own filter_products_by_property_list / should_include_product_for_property_list. It does NOT handle fields, pagination, time_budget, or refine at all — those just pass through. implementation_config lookup runs inline in media_buy_create.py:2425-2466. Every adopter will rebuild the property-list helper; no adopter currently has the others.

Reference: SDK today

adcp.decisioning.handler.MediaBuyHandler.get_products (src/adcp/decisioning/handler.py:1015-1033) is a pure pass-through to _invoke_platform_method — no pre/post-processing, no capability gate, no projection. SalesPlatform.get_products (src/adcp/decisioning/specialisms/sales.py:105-119) hands the raw GetProductsRequest to the adopter and expects the raw GetProductsResponse back.

The auto-emit pattern (src/adcp/decisioning/webhook_emit.py) shows what "framework intercepts at the seam" looks like in this codebase — that's the reference design for every child issue.

Children (parallelizable — pick up in any order)

Each child is independently scoped — no cross-dependency. They can land in any order.

Cross-references

  • Migration doc: docs: salesagent → adcp Python SDK migration guide #489
  • Auto-emit reference pattern: src/adcp/decisioning/webhook_emit.py
  • Wire request: src/adcp/types/generated_poc/bundled/media_buy/get_products_request.py
  • Wire response: src/adcp/types/generated_poc/bundled/media_buy/get_products_response.py
  • Capabilities: src/adcp/types/generated_poc/core/media_buy_features.py (property_list_filtering already wire-defined)
  • Salesagent reference: /src/core/tools/products.py, /src/core/tools/media_buy_create.py:2431-2466

Out of scope for this tracker

  • Dynamic-product assembly from signals (salesagent has it, but no AdCP wire shape exists — speculative)
  • Key-value targeting threading product → create_media_buy (salesagent-internal, no wire shape)
  • Migration guide edits (handled in docs: salesagent → adcp Python SDK migration guide #489)
  • Catalog/collection filter helper — same shape as property_list, but the adoption signal is weaker (salesagent doesn't implement it either). File a follow-up if a second adopter requests it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions