Skip to content
Open
Show file tree
Hide file tree
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
13 changes: 13 additions & 0 deletions .changeset/targeting-aware-product-discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"adcontextprotocol": minor
---

Unify targeting across `get_products`, configured product selection, and media-buy execution.

Buyers can now provide concrete `targeting_overlay` values during discovery and require product-scoped future targeting through `required_overlay_support`. Products disclose selectable `overlay_support`, sparse buyer-reviewable `targeting_resolution` changes, and opaque buyable `product_id` values that remain stable within a discovery/refinement context without promising validity in independent discovery contexts. Product pricing and forecasts are bound to effective targeting. Buyers should prefer structured fields over equivalent brief prose, while sellers continue to apply explicit hard brief requirements and can confirm inferred predicates once at response-level `targeting_resolution.brief_targeting`.

Move purchased placement selection into `targeting_overlay` alongside property and collection selection, while preserving creative placement references as routing-only. Add typed device-platform exclusion with independently declared product support, and keep arbitrary buyer-supplied ad-server key/value targeting outside the protocol trust boundary. Put discovery and package resolution behind lifecycle-specific schemas, move demographic package execution readback to `targeting_resolution.demographics` before its 3.2 release, deprecate targeting-like product filters, add migration guidance and conformance coverage, and retain exact-only booked package execution.

Clarify that deterministic product filters exclude non-matching products in `brief`, `wholesale`, and `refine` modes, and add seeded behavioral conformance coverage that detects full and partial filter no-ops.

Update the buyer skill, Addie knowledge, and buyer learning modules to teach structured-first request decomposition and targeting-resolution review. Live training-agent support follows the generated 3.2 beta SDKs under issue #6199.
3 changes: 2 additions & 1 deletion docs/building/by-layer/L3/error-handling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,8 @@ The wire-level `recovery: "correctable"` on the sandbox-only path is the registe

| Code | Recovery | Description | Resolution |
|------|----------|-------------|------------|
| `PRODUCT_NOT_FOUND` | correctable | Referenced product IDs are unknown or expired | Remove invalid IDs, or re-discover with `get_products` |
| `PRODUCT_NOT_FOUND` | correctable | Referenced product IDs are unknown | Remove invalid IDs, or re-discover with `get_products` |
| `PRODUCT_EXPIRED` | correctable | Referenced configured products passed `expires_at` | Re-discover with `get_products` |
| `PRODUCT_UNAVAILABLE` | correctable | Product is sold out or no longer available | Choose a different product |
| `PROPOSAL_EXPIRED` | correctable | Referenced proposal has passed its `expires_at` | Run `get_products` to get a fresh proposal |
| `PROPOSAL_NOT_FOUND` | correctable | `proposal_id` is unknown to the seller (never finalized, wrong tenant, or evicted from cache) | Re-issue `get_products` with `buying_mode: "refine"` + `action: "finalize"` to obtain a current proposal_id |
Expand Down
16 changes: 13 additions & 3 deletions docs/intro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,28 @@ The seller responds with the account status — active, pending review, or what

This is where it gets powerful. Sam wants to find premium sports inventory for Acme Outdoor's Q2 campaign. In the old world, he'd log into four dashboards and compare apples to oranges.

With AdCP, `get_products` sends the same brief to every connected seller. Sam describes what he wants in natural language:
With AdCP, `get_products` sends the same structured request and brief to every connected seller. Sam keeps semantic intent in prose and exact constraints in fields every seller can process deterministically:

```json
{
"$schema": "https://adcontextprotocol.org/schemas/v3/media-buy/get-products-request.json",
"buying_mode": "brief",
"brief": "Premium sports video inventory, Q2 2026, targeting 25-45 males interested in outdoor recreation. Budget $50K across CTV and display.",
"brief": "Premium sports and outdoor-recreation contexts for Acme Outdoor's Q2 launch. Budget $50K.",
"filters": {
"channels": ["ctv", "display"],
"pricing_currencies": ["USD"]
},
"targeting_overlay": {
"geo_countries": ["US"],
"demographics": {
"age": { "min": 25, "max": 45, "include_unknown": false }
}
},
"brand": { "domain": "acmeoutdoor.com" }
}
```

Every seller responds in the same format — products with pricing, forecasts, targeting options, and creative requirements. Sam compares proposals side by side on one screen instead of four.
Every seller responds in the same format — products with pricing, forecasts, targeting support, resolution, and creative requirements. Sam can verify exact constraints without asking every seller to infer them from prose.

<Accordion title="What a product response looks like">

Expand Down
9 changes: 9 additions & 0 deletions docs/learning/foundations/a2b-testing-your-first-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ Use these as a quick reference while working through the module with Addie, or t

Call `get_products` with `buying_mode: "brief"` and a plain-English description of your campaign goals. The agent returns curated `products[]` and ready-to-execute `proposals[]`.

<Note>
This public training-agent lab continues to use the pre-3.2 brief flow. The 3.2
structured discovery exercise will be enabled only after the beta SDKs and
training runtime implement targeting-aware discovery; follow
[issue #6199](https://github.com/adcontextprotocol/adcp/issues/6199). Until
then, do not use this sandbox to test `get_products.targeting_overlay` or
`required_overlay_support`, because the live runtime does not enforce them.
</Note>

```bash
curl -X POST https://test-agent.adcontextprotocol.org/sales/mcp \
-H "Content-Type: application/json" \
Expand Down
66 changes: 60 additions & 6 deletions docs/learning/supplements/buyer-briefs-and-get-products.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Buyer briefs and get_products request shape"
sidebarTitle: "Buyer briefs"
description: "How buyer agents decide what belongs in the get_products brief string, structured filters, and follow-up refinement requests."
description: "How buyer agents decompose campaign intent into get_products briefs, product filters, targeting overlays, future targeting support, and refinements."
"og:title": "AdCP - Buyer briefs and get_products request shape"
---

Expand All @@ -11,12 +11,21 @@ This supplement prepares buyer-side implementers to turn a human campaign reques

The goal is not to make the brief verbose. The goal is to put intent in the brief and hard constraints in typed fields so the seller can curate inventory without guessing which parts are negotiable.

<Note>
This module teaches the AdCP 3.2 targeting-aware discovery contract. Use it
against sellers and SDKs that declare 3.2 support. The public training-agent lab
will enable these calls after the 3.2 beta SDK release; implementation is
tracked in [issue #6199](https://github.com/adcontextprotocol/adcp/issues/6199).
</Note>

## Mental model

| Input | Use it for | Avoid putting here |
|---|---|---|
| `brief` | Buyer intent, audience language, context, tone, business goal, and success definition | Machine-enforceable constraints that already have typed fields |
| `filters` | Hard constraints that should silently exclude non-matching products | Soft preferences that a seller could satisfy through curation |
| `brief` | Buyer intent, semantic audience language, context, tone, business goal, and requirements without a typed representation | Constraints that already have structured fields |
| `filters` | Hard offer filters—metadata, dates, budget, availability, commercial fit, and reporting capabilities—that exclude non-matching products | Delivery targeting or soft preferences |
| `targeting_overlay` | Exact delivery constraints known now; availability, pricing, and forecasts must account for them | Product characteristics or values the buyer has not chosen yet |
| `required_overlay_support` | Targeting dimensions whose values will be selected independently on packages later | Current targeting values or a request for one product per value |
| `brand` | The buyer brand identity the seller uses for eligibility, safety, and fit | A second copy of the campaign brief |
| `catalog` | Commerce or product-set context when the campaign is catalog-driven | General brand positioning |
| `refine` | Specific changes to a prior discovery response | New unrelated discovery goals |
Expand Down Expand Up @@ -46,11 +55,13 @@ Example:
## What goes in filters

Use filters when a product that fails the condition should not come back.
That exclusion rule is identical in `brief`, `wholesale`, and `refine`; the
mode changes how the seller curates and versions the result, not whether a
valid filter applies.

Good filter candidates:

- required channels or formats
- required geo targeting support
- required measurement or reporting capabilities
- pricing currency constraints
- budget ranges
Expand All @@ -76,6 +87,43 @@ Example:

If the buyer says "ideally CTV, but display is okay," keep that preference in the brief. If they say "CTV only," use `filters.channels`.

## What goes in targeting

Use `targeting_overlay` for exact delivery constraints the buyer knows now:

```json
{
"targeting_overlay": {
"geo_countries": ["US"],
"demographics": {
"age": { "min": 25, "max": 44, "include_unknown": false }
}
}
}
```

Use `required_overlay_support` when the dimension is mandatory but its values
will be chosen later:

```json
{
"required_overlay_support": {
"geo_metros": { "systems": ["nielsen_dma"] },
"placement_selection": true
}
}
```

This does not ask for products broken out by DMA or placement. It asks for
products on which packages can select those values later.

If an exact constraint appears only in prose, it remains binding, but the
seller must infer its wire meaning. Prefer the structured field. When a seller
does infer hard targeting from the brief, inspect
the response-level `targeting_resolution.brief_targeting` before purchase. Also inspect sparse
`targeting_resolution.modifications`; selecting that configured `product_id`
accepts the disclosed differences.

## Brief vs. refine

Use `buying_mode: "refine"` when the buyer is reacting to a previous discovery response. A refine request should point at what changed: remove a product, adjust budget, request more premium placements, narrow geography, or ask for alternatives.
Expand All @@ -84,20 +132,26 @@ Do not send a totally new campaign in `refine`; start a new `brief` request inst

## Implementation checklist

- Read `get_adcp_capabilities.adcp.supported_versions`, pin a compatible 3.2 release in `adcp_version`, and validate the echoed served release before using targeting-aware discovery.
- If release precision is absent, major-only, or 3.1-or-earlier, omit the 3.2 fields and fall back to retained legacy targeting filters or explicit brief prose; unknown fields may otherwise be silently ignored.
- Normalize the human request into intent, hard constraints, and follow-up changes before calling the seller.
- Preserve the buyer's business language in `brief`; do not collapse it into only keywords.
- Put typed constraints in `filters` so sellers can explain exclusions through `filter_diagnostics`.
- Put product characteristics in `filters` and exact delivery constraints in `targeting_overlay`.
- Use `required_overlay_support` only for dimensions whose values will be supplied later.
- Inspect every returned `targeting_resolution`; silence confirms an unchanged structured overlay, not prose interpretation.
- Keep `brief` out of `wholesale` mode.
- Persist the request tuple with the response so later `refine` calls and `wholesale_feed_version` comparisons are scoped correctly.

## Practice prompt

A buyer says:

> We need a six-week launch for Acme Meals' new family dinner kits. We want CTV or online video, only USD pricing, something suitable for parents with kids, and we need completion-rate reporting.
> We need a six-week US launch for Acme Meals' new family dinner kits. We want CTV or online video, only USD pricing, something suitable for parents with kids, ages 25–44, and we need completion-rate reporting. We will choose DMAs after planning.

Expected decomposition:

- Brief: family dinner kit launch, parent audience, suitable contexts, six-week launch.
- Filters: video-capable channel/format constraints, USD pricing, completion-rate reporting.
- Targeting overlay: US and ages 25–44.
- Required overlay support: Nielsen DMA selection later.
- Brand: Acme Meals domain or BrandRef.
21 changes: 19 additions & 2 deletions docs/learning/tracks/buyer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ How buyer agents orchestrate across multiple sales agents simultaneously: discov
<Card title="Targeting" icon="crosshairs" href="/docs/media-buy/advanced-topics/targeting">
Targeting options, audience overlays, and geo-targeting.
</Card>
<Card title="Buyer briefs" icon="filter" href="/docs/learning/supplements/buyer-briefs-and-get-products">
Decide what belongs in briefs, filters, current targeting, and future targeting support.
</Card>
<Card title="Version negotiation" icon="code-branch" href="/docs/reference/versioning#version-negotiation">
Declare `adcp_major_version` on requests; sellers respond with `VERSION_UNSUPPORTED` when incompatible.
</Card>
Expand All @@ -71,6 +74,8 @@ How buyer agents orchestrate across multiple sales agents simultaneously: discov
- **Order lifecycle** — `pending_creatives` → `pending_start` → `active`; check `valid_actions` from `get_media_buys` before acting. S1 covers the full state machine and recovery
- **Version negotiation** — declare `adcp_major_version` on every request; handle `VERSION_UNSUPPORTED` by selecting a compatible seller or downgrading the payload
- **Pricing selection** — products return `pricing_options[]`; buyer selects one via `pricing_option_id` in `create_media_buy`
- **Structured-first discovery** — use `filters` to decide which offers may be returned, `targeting_overlay` to constrain delivery, and `required_overlay_support` for dimensions selected on packages later
- **Resolution acceptance** — no resolution means an exact structured overlay; review `modifications` and brief-derived targeting before selecting an opaque configured `product_id`
- **Negotiated accountability** — for guaranteed buys, propose `measurement_terms` / `performance_standards`; seller accepts, adjusts, or returns `TERMS_REJECTED`. S1 covers the recovery patterns
- **Account required on updates** — `update_media_buy` takes `account` + `media_buy_id`; omitting `account` is a protocol error
- **Audience targeting** — `sync_audiences` for custom segments
Expand Down Expand Up @@ -249,8 +254,20 @@ New to running tool calls and reading JSON in a terminal? Do [A2b: Testing your

### What you'll build

<Note>
The targeting-aware discovery portion is a 3.2 assessment objective. The public
training seller will enable it after the 3.2 beta SDK release; follow
[issue #6199](https://github.com/adcontextprotocol/adcp/issues/6199). Until
then, validate this portion with schema fixtures rather than assuming the live
training runtime enforces unknown fields.
</Note>

- Account setup with `sync_accounts`
- Product discovery from at least 2 sellers
- Decomposition of a messy human request into `brief`, `filters`,
`targeting_overlay`, and `required_overlay_support`
- Acceptance/rejection of a disclosed targeting modification and verification
of effective package readback
- Media buy creation with targeting and budget — including a fresh UUID v4 `idempotency_key` per logical buy, and correct retry behavior that resends the identical payload with the same key on network failure (the mechanics of what the seller does with the key — replay, conflict, expired — are taught in [S1: Media buy](/docs/learning/specialist/media-buy))
- Creative sync with at least 1 format
- Campaign monitoring via delivery reporting
Expand Down Expand Up @@ -278,10 +295,10 @@ Review the [Compliance Catalog](/docs/building/verification/compliance-catalog)

| Dimension | Weight | What Addie evaluates |
|-----------|--------|---------------------|
| Specification quality | 20% | Can you specify a buying workflow in AdCP terms? |
| Specification quality | 20% | Can you decompose buyer intent into brief, offer filters, current targeting, and later-selectable support? |
| Schema compliance | 25% | Agent requests and responses validate against schemas |
| Error handling | 15% | Handles seller errors and async responses |
| Design rationale | 20% | Can you explain orchestration and buying strategy? |
| Design rationale | 20% | Can you explain targeting resolution, configured-product acceptance, orchestration, and buying strategy? |
| Extension ability | 20% | Can you extend the agent with new buying capabilities? |

Passing threshold: 70%.
Expand Down
Loading
Loading