From 5ab9a9f12bb4fd0c51c1208ef5ff9b7b1fef6efe Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 1 Aug 2025 20:57:59 +0200 Subject: [PATCH 1/3] feat: align with signals agent spec and add get_signals endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename list_products to get_products across all documentation - Add optional get_signals endpoint for publishers to advertise available segments - Enable signals activation in create_media_buy targeting - Rename provided_signals to aee_signals for clarity 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- CLAUDE.md | 2 +- docs/media-buy/api-reference.md | 58 +++++++++++++++++++++++++++-- docs/media-buy/product-discovery.md | 18 ++++----- 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 452e43eb8c..3dee5bc38f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -86,7 +86,7 @@ Implementation details can be mentioned as: 5. **AI-Optimized**: Designed for AI agents ### What Exists vs What Doesn't -- ✅ `list_products` - discovers inventory +- ✅ `get_products` - discovers inventory - ❌ `discover_products` - doesn't exist - ❌ `get_avails` - removed in favor of direct purchase - ✅ `create_media_buy` - creates campaigns diff --git a/docs/media-buy/api-reference.md b/docs/media-buy/api-reference.md index 7456939699..9d97f3c62e 100644 --- a/docs/media-buy/api-reference.md +++ b/docs/media-buy/api-reference.md @@ -142,6 +142,7 @@ Creates a media buy from selected packages. "geo_country_any_of": ["US"], "geo_region_any_of": ["CA", "NY"], "audience_segment_any_of": ["3p:pet_owners"], + "signals": ["auto_intenders_q1_2025"], // Optional: Signal IDs from get_signals "frequency_cap": { "suppress_minutes": 30, "scope": "media_buy" @@ -671,7 +672,7 @@ Retrieves delivery data for all active media buys across all principals. **Response:** Same format as get_media_buy_delivery but includes all media buys. -### 16. list_products +### 16. get_products Lists available advertising products for the authenticated principal with optional natural language brief and filtering. @@ -797,12 +798,58 @@ Verify if required AEE dimensions are supported for a channel. Use this before creating a media buy to ensure the publisher can provide required AEE signals. +### 19. get_signals (Optional) + +Lists available audience segments and signals that the publisher can activate for targeting. This optional endpoint allows publishers to advertise the segments they have available through their data partnerships. + +**Request:** +```json +{ + "signal_type": "audience", // Optional: "audience", "contextual", "geographic", etc. + "category": "string", // Optional: Filter by category (e.g., "demographics", "interests") + "search": "string" // Optional: Natural language search for signals +} +``` + +**Response:** +```json +{ + "signals": [ + { + "signal_id": "auto_intenders_q1_2025", + "name": "Auto Intenders Q1 2025", + "description": "In-market for new vehicles in Q1 2025", + "type": "audience", + "category": "purchase_intent", + "size": { + "value": 2500000, + "unit": "individuals" // "individuals", "devices", or "households" + }, + "geography": ["US", "CA"], + "freshness": "2025-01-15", // Last update date + "provider": "LiveRamp", + "cost": { + "cpm": 2.50, + "revenue_share": 0.05, + "pricing_model": "both" // "cpm", "revenue_share", or "both" + } + } + ] +} +``` + +**Notes:** +- This is an optional endpoint for publishers who want to expose available segments +- The signal_id returned here can be used in create_media_buy's targeting.signals array +- Publishers may choose to expose all segments or only premium/differentiated ones +- Cost information helps buyers understand incremental data costs + ## Creative Macro Signal -The creative macro is a third type of provided signal from AEE, enabling dynamic creative customization. +The creative macro is a third type of AEE signal, enabling dynamic creative customization. -### AEE Provided Signals +### AEE Signals 1. **may_include** - Signals to include for targeting 2. **must_exclude** - Signals that must be excluded @@ -824,7 +871,7 @@ The AEE can then provide a creative_macro string in its response: { "should_bid": true, "bid_price": 5.50, - "provided_signals": { + "aee_signals": { "may_include": ["sports", "premium_user"], "must_exclude": ["competitor_xyz"], "creative_macro": "city:San Francisco|weather:sunny|segment:tech_professional" @@ -1136,6 +1183,9 @@ interface Targeting { audience_segment_any_of?: string[]; // ["1p:loyalty", "3p:auto_intenders"] audience_segment_none_of?: string[]; + // Signal-based targeting (from get_signals) + signals?: string[]; // ["auto_intenders_q1_2025", "high_income_households"] + // Media type targeting media_type_any_of?: string[]; // ["video", "audio", "display", "native"] media_type_none_of?: string[]; diff --git a/docs/media-buy/product-discovery.md b/docs/media-buy/product-discovery.md index 4d447b8474..cb212be97f 100644 --- a/docs/media-buy/product-discovery.md +++ b/docs/media-buy/product-discovery.md @@ -6,13 +6,13 @@ title: Product Discovery Product discovery is the foundation of the Media Buy Protocol, enabling AI agents to find relevant advertising inventory using natural language. This document explains the discovery lifecycle and how to implement the discovery tools. -## The Discovery Tool: `list_products` +## The Discovery Tool: `get_products` AdCP provides a single discovery tool that uses natural language to find relevant advertising inventory. ### How it Works -The `list_products` tool accepts a natural language brief and optional format filters to return matching products from the catalog. If no brief is provided, it returns all available products for the authenticated principal. +The `get_products` tool accepts a natural language brief and optional format filters to return matching products from the catalog. If no brief is provided, it returns all available products for the authenticated principal. **Request Options:** @@ -85,11 +85,11 @@ def get_product_catalog(): ### Step 2: Implement Natural Language Processing -The `list_products` tool needs to interpret natural language briefs: +The `get_products` tool needs to interpret natural language briefs: ```python @mcp.tool -def list_products(req: ListProductsRequest, context: Context) -> ListProductsResponse: +def get_products(req: GetProductsRequest, context: Context) -> GetProductsResponse: # Authenticate principal principal_id = _get_principal_id_from_context(context) @@ -203,7 +203,7 @@ The complete discovery workflow with format awareness: graph TD A[list_creative_formats] --> B[Identify available formats] B --> C[User provides brief + format filters] - C --> D[list_products] + C --> D[get_products] D --> E{Products found?} E -->|Yes| F[Review products] E -->|No| G[Generate custom products] @@ -230,7 +230,7 @@ Use format knowledge to filter products: ```javascript // Only discover products that accept standard audio formats -const products = await client.call_tool("list_products", { +const products = await client.call_tool("get_products", { brief: "Reach young adults interested in gaming", format_types: ["audio"], standard_formats_only: true @@ -310,7 +310,7 @@ Common error scenarios and handling: ```python @mcp.tool -def list_products(req: ListProductsRequest, context: Context) -> ListProductsResponse: +def get_products(req: GetProductsRequest, context: Context) -> GetProductsResponse: try: principal_id = _get_principal_id_from_context(context) except: @@ -342,7 +342,7 @@ test_briefs = [ ] for brief in test_briefs: - result = list_products(ListProductsRequest(brief=brief), context) + result = get_products(GetProductsRequest(brief=brief), context) assert len(result.products) > 0 print(f"Brief: {brief} -> Found {len(result.products)} products") ``` @@ -351,7 +351,7 @@ for brief in test_briefs: Discovery is just the first step. Ensure smooth transitions to the next phases: -1. **Discovery** → `list_products` finds relevant inventory +1. **Discovery** → `get_products` finds relevant inventory 2. **Purchase** → `create_media_buy` executes the campaign 4. **Creative** → `add_creative_assets` uploads assets 5. **Monitor** → Track delivery and optimize From af5952c10e59711857c5257fef47f1711ad60773 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 1 Aug 2025 21:00:59 +0200 Subject: [PATCH 2/3] refactor: reference signals protocol spec instead of duplicating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace duplicated get_signals specification with reference to get_audiences from Signals Discovery Protocol - Prevents documentation drift between protocols - Clarifies integration points between media buy and signals protocols 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- docs/media-buy/api-reference.md | 52 ++++++++------------------------- 1 file changed, 12 insertions(+), 40 deletions(-) diff --git a/docs/media-buy/api-reference.md b/docs/media-buy/api-reference.md index 9d97f3c62e..82cd1da849 100644 --- a/docs/media-buy/api-reference.md +++ b/docs/media-buy/api-reference.md @@ -798,51 +798,23 @@ Verify if required AEE dimensions are supported for a channel. Use this before creating a media buy to ensure the publisher can provide required AEE signals. -### 19. get_signals (Optional) +### 19. get_audiences (Optional) -Lists available audience segments and signals that the publisher can activate for targeting. This optional endpoint allows publishers to advertise the segments they have available through their data partnerships. +Publishers may optionally implement the `get_audiences` endpoint from the [Signals Discovery Protocol](../../signals-protocol-v1.md#get_audiences) to advertise available audience segments for targeting. -**Request:** -```json -{ - "signal_type": "audience", // Optional: "audience", "contextual", "geographic", etc. - "category": "string", // Optional: Filter by category (e.g., "demographics", "interests") - "search": "string" // Optional: Natural language search for signals -} -``` +**Purpose:** Allows buyers to discover what audience segments are available through the publisher's data partnerships. -**Response:** -```json -{ - "signals": [ - { - "signal_id": "auto_intenders_q1_2025", - "name": "Auto Intenders Q1 2025", - "description": "In-market for new vehicles in Q1 2025", - "type": "audience", - "category": "purchase_intent", - "size": { - "value": 2500000, - "unit": "individuals" // "individuals", "devices", or "households" - }, - "geography": ["US", "CA"], - "freshness": "2025-01-15", // Last update date - "provider": "LiveRamp", - "cost": { - "cpm": 2.50, - "revenue_share": 0.05, - "pricing_model": "both" // "cpm", "revenue_share", or "both" - } - } - ] -} -``` +**Implementation:** See the [Signals Discovery Protocol specification](../../signals-protocol-v1.md#get_audiences) for the complete interface definition. + +**Integration with Media Buy:** +- The `audience_id` returned by `get_audiences` can be used in the `targeting.signals` array when creating a media buy +- Publishers implementing this endpoint should ensure the audience IDs are compatible with their targeting systems +- Cost information in the response helps buyers understand incremental data costs **Notes:** -- This is an optional endpoint for publishers who want to expose available segments -- The signal_id returned here can be used in create_media_buy's targeting.signals array -- Publishers may choose to expose all segments or only premium/differentiated ones -- Cost information helps buyers understand incremental data costs +- This is an optional endpoint - publishers may choose to expose all, some, or no audience segments +- The protocol supports various audience types: owned, marketplace, and destination audiences +- Publishers should coordinate with their data providers on which segments to expose ## Creative Macro Signal From bd94934ae0b90af5186f44055d3daa537cfe584d Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 1 Aug 2025 21:08:18 +0200 Subject: [PATCH 3/3] feat: align with signals agent spec and add get_signals endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update signals protocol to use get_signals instead of get_audiences - Update API reference to properly reference get_signals - Make endpoint more general to support all signal types, not just audiences 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- docs/media-buy/api-reference.md | 12 ++++++------ signals-protocol-v1.md | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/media-buy/api-reference.md b/docs/media-buy/api-reference.md index 82cd1da849..f3051c61e7 100644 --- a/docs/media-buy/api-reference.md +++ b/docs/media-buy/api-reference.md @@ -798,21 +798,21 @@ Verify if required AEE dimensions are supported for a channel. Use this before creating a media buy to ensure the publisher can provide required AEE signals. -### 19. get_audiences (Optional) +### 19. get_signals (Optional) -Publishers may optionally implement the `get_audiences` endpoint from the [Signals Discovery Protocol](../../signals-protocol-v1.md#get_audiences) to advertise available audience segments for targeting. +Publishers may optionally implement the `get_signals` endpoint from the [Signals Discovery Protocol](../../signals-protocol-v1.md#get_signals) to advertise available signals for targeting. -**Purpose:** Allows buyers to discover what audience segments are available through the publisher's data partnerships. +**Purpose:** Allows buyers to discover what signals (audiences, contextual, geographic, etc.) are available through the publisher's data partnerships. -**Implementation:** See the [Signals Discovery Protocol specification](../../signals-protocol-v1.md#get_audiences) for the complete interface definition. +**Implementation:** See the [Signals Discovery Protocol specification](../../signals-protocol-v1.md#get_signals) for the complete interface definition. **Integration with Media Buy:** -- The `audience_id` returned by `get_audiences` can be used in the `targeting.signals` array when creating a media buy +- The signal IDs returned by `get_signals` can be used in the `targeting.signals` array when creating a media buy - Publishers implementing this endpoint should ensure the audience IDs are compatible with their targeting systems - Cost information in the response helps buyers understand incremental data costs **Notes:** -- This is an optional endpoint - publishers may choose to expose all, some, or no audience segments +- This is an optional endpoint - publishers may choose to expose all, some, or no signals - The protocol supports various audience types: owned, marketplace, and destination audiences - Publishers should coordinate with their data providers on which segments to expose diff --git a/signals-protocol-v1.md b/signals-protocol-v1.md index 8925ae0afc..d6f37b4d7b 100644 --- a/signals-protocol-v1.md +++ b/signals-protocol-v1.md @@ -73,9 +73,9 @@ Each MCP session is authenticated as one of: ## Protocol Specification -### get_audiences +### get_signals -Discovers relevant audiences based on a marketing specification. +Discovers relevant signals (audiences, contextual, geographic, etc.) based on a marketing specification. #### Request @@ -141,7 +141,7 @@ Activates an audience for use on a specific platform/seat. ```json { - "segment_id": "string", // From get_audiences (required) + "segment_id": "string", // From get_signals (required) "platform": "string", // Required "seat": "string", // Optional "options": { @@ -264,7 +264,7 @@ Reports usage data for billing reconciliation. ## Typical Flow -1. **Discovery**: Use `get_audiences` to find relevant audiences +1. **Discovery**: Use `get_signals` to find relevant signals 2. **Review**: Check `deployment.is_live` status 3. **Activate**: If not live, use `activate_audience` 4. **Monitor**: Use `check_audience_status` to track activation