You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
Motivation
get_productscarries a number of request-shape parameters that are buyer-facing protocol concerns, not seller business logic:fieldsprojection,pagination,property_list,time_budget,refine, plus the cross-toolimplementation_configplumbing oncreate_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 ownfilter_products_by_property_list/should_include_product_for_property_list. It does NOT handlefields,pagination,time_budget, orrefineat all — those just pass through.implementation_configlookup runs inline inmedia_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 rawGetProductsRequestto the adopter and expects the rawGetProductsResponseback.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)
feat(decisioning): built-in fields projection on get_products responses— pure post-filter, no capability gatefeat(decisioning): cursor-based pagination helper for list responses— opaque-cursor codec +framework_paginationcapabilityfeat(decisioning): property_list resolver + intersection helper for get_products— capabilityproperty_list_filtering(already wire-defined)feat(decisioning): time_budget deadline wrapper + incomplete projection on get_products— universal,IncrementalGetProductsopt-in for partial resultsfeat(decisioning): refine[] flow scaffold for get_products (position-matched echo)—buying_mode='refine'+ position-matchedrefinement_applied[]echofeat(decisioning): implementation_config lookup helper for create_media_buy—ProductConfigStoreprotocol, scoped to create_media_buy firstEach child is independently scoped — no cross-dependency. They can land in any order.
Cross-references
src/adcp/decisioning/webhook_emit.pysrc/adcp/types/generated_poc/bundled/media_buy/get_products_request.pysrc/adcp/types/generated_poc/bundled/media_buy/get_products_response.pysrc/adcp/types/generated_poc/core/media_buy_features.py(property_list_filteringalready wire-defined)/src/core/tools/products.py,/src/core/tools/media_buy_create.py:2431-2466Out of scope for this tracker