Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .changeset/tricky-ideas-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

docs: Document property_features field for governance agent discovery in adagents.json
133 changes: 129 additions & 4 deletions docs/governance/property/adagents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ The file must be valid JSON with UTF-8 encoding and return HTTP 200 status.
- **`domain`** *(optional)*: Primary domain of managing entity
- **`seller_id`** *(optional)*: Seller ID from IAB Tech Lab sellers.json
- **`tag_id`** *(optional)*: TAG Certified Against Fraud ID
- **`privacy_policy_url`** *(optional)*: URL to entity's privacy policy for consumer consent flows

**`properties`** *(optional)*: Array of properties covered by this file (canonical property definitions)

Expand All @@ -78,6 +79,14 @@ The file must be valid JSON with UTF-8 encoding and return HTTP 200 status.

**`last_updated`** *(optional)*: ISO 8601 timestamp of last modification

**`property_features`** *(optional)*: Array of governance agents that provide data about properties in this file
- **`url`** *(required)*: Agent's API endpoint URL (governance agent implementing property governance tasks)
- **`name`** *(required)*: Human-readable name of the vendor/agent (e.g., "Scope3", "TAG", "OneTrust")
- **`features`** *(required)*: Array of feature IDs this agent provides (e.g., `["carbon_score", "gdpr_compliant"]`)
- **`publisher_id`** *(optional)*: Publisher's identifier at this agent (for lookup)

This field enables **governance agent discovery** - buyers can find which agents have compliance, sustainability, or quality data for properties without querying every possible agent.

## URL Reference Pattern

For publishers with complex infrastructure or CDN distribution, `adagents.json` can reference an authoritative URL instead of containing the full structure inline.
Expand Down Expand Up @@ -357,7 +366,8 @@ Large network using tags for grouping efficiency:
"email": "adops@meta.com",
"domain": "meta.com",
"seller_id": "pub-meta-12345",
"tag_id": "12345"
"tag_id": "12345",
"privacy_policy_url": "https://www.meta.com/privacy/policy"
},
"properties": [
{
Expand Down Expand Up @@ -458,6 +468,121 @@ Different agents for different channels:
}
```

### Example 3: Publisher with Governance Agent References

Publishers can declare which governance agents have data about their properties using `property_features`. This enables buyers to discover where to get compliance, sustainability, and quality data.

```json
{
"$schema": "https://adcontextprotocol.org/schemas/v2/adagents.json",
"contact": {
"name": "Premium News Publisher",
"email": "adops@news.example.com",
"domain": "news.example.com"
},
"properties": [
{
"property_id": "news_main",
"property_type": "website",
"name": "News Example",
"identifiers": [
{"type": "domain", "value": "news.example.com"}
],
"tags": ["premium", "news"],
"publisher_domain": "news.example.com"
}
],
"tags": {
"premium": {
"name": "Premium Properties",
"description": "High-quality, brand-safe properties"
},
"news": {
"name": "News Properties",
"description": "News and journalism content"
}
},
"authorized_agents": [
{
"url": "https://sales.news.example.com",
"authorized_for": "All news properties",
"authorization_type": "property_tags",
"property_tags": ["news"]
}
],
"property_features": [
{
"url": "https://api.scope3.com",
"name": "Scope3",
"features": ["carbon_score", "sustainability_grade"],
"publisher_id": "pub_news_12345"
},
{
"url": "https://api.tagtoday.net",
"name": "TAG",
"features": ["tag_certified_against_fraud", "tag_brand_safety_certified"]
},
{
"url": "https://api.onetrust.com",
"name": "OneTrust",
"features": ["gdpr_compliant", "tcf_registered", "ccpa_compliant"],
"publisher_id": "ot_news_67890"
}
],
"last_updated": "2025-01-10T18:00:00Z"
}
```

**Why this works**:
- Publishers declare relationships with governance agents upfront
- Buyers discover governance agents by reading adagents.json (no need to query every possible agent)
- The `publisher_id` field helps agents look up the publisher's data efficiently
- Feature IDs tell buyers what data types are available without querying

## Governance Agent Discovery

The `property_features` field solves a key discovery problem: how does a buyer know which governance agents have data about a given property?

```mermaid
sequenceDiagram
participant Buyer as Buyer Agent
participant PubDomain as Publisher Domain
participant Scope3 as Scope3 Agent
participant OneTrust as OneTrust Agent

Buyer->>PubDomain: GET /.well-known/adagents.json
PubDomain-->>Buyer: adagents.json with property_features

Note over Buyer: Extract governance agents from property_features

par Query governance agents
Buyer->>Scope3: list_property_features
Scope3-->>Buyer: Available features (carbon_score, etc.)
and
Buyer->>OneTrust: list_property_features
OneTrust-->>Buyer: Available features (gdpr_compliant, etc.)
end

Note over Buyer: Create property lists on each governance agent

Buyer->>Scope3: create_property_list(filters, brand_manifest)
Buyer->>OneTrust: create_property_list(filters, brand_manifest)
```

### When to Use property_features

| Scenario | Use property_features? |
|----------|------------------------|
| Publisher has carbon scoring from Scope3 | ✅ Yes |
| Publisher is TAG certified | ✅ Yes |
| Publisher tracks consent via OneTrust | ✅ Yes |
| Publisher self-reports brand safety | ❌ No - use property tags |
| Sales agent provides quality data | ❌ No - that's agent capability |

### Vendor Extensions

Governance agents can include vendor-specific data in feature definitions via an `ext` block. See [list_property_features](/docs/governance/property/tasks/list_property_features#vendor-extensions) for details.

## Fetching and Validating

### Using the AdAgents.json Builder
Expand Down Expand Up @@ -620,14 +745,14 @@ The Python library handles validation automatically when fetching - if the adage

After implementing adagents.json validation:

1. **Integrate with Product Discovery**: Use [`get_products`](../../media-buy/task-reference/get_products) to discover inventory
2. **Validate at Purchase**: Check authorization before calling [`create_media_buy`](../../media-buy/task-reference/create_media_buy)
1. **Integrate with Product Discovery**: Use [`get_products`](/docs/media-buy/task-reference/get_products) to discover inventory
2. **Validate at Purchase**: Check authorization before calling [`create_media_buy`](/docs/media-buy/task-reference/create_media_buy)
3. **Cache Property Mappings**: Store resolved properties for efficient validation
4. **Monitor Authorization**: Track validation success rates and unauthorized attempts

## Learn More

- [AdCP Basics: Authorized Properties](https://bokonads.com/p/adcp-basics-authorized-properties) - Accessible introduction to AdCP authorization
- [list_authorized_properties](../../media-buy/task-reference/list_authorized_properties) - Discover publisher domains an agent represents
- [list_authorized_properties](/docs/media-buy/task-reference/list_authorized_properties) - Discover publisher domains an agent represents
- [Property Schema](https://adcontextprotocol.org/schemas/v2/core/property.json) - Property definition structure
- [AdAgents.json Builder](https://adcontextprotocol.org/adagents) - Web-based validator and creator
136 changes: 68 additions & 68 deletions docs/governance/property/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@ Property Governance standardizes how advertising properties (websites, apps, CTV

## Overview

Property Governance addresses four distinct concerns:
Property Governance addresses five distinct concerns:

| Concern | Question | Owner | Mechanism |
|---------|----------|-------|-----------|
| **Property Identity** | What properties exist? | Publishers | `adagents.json` properties array |
| **Sales Authorization** | Who can sell this property? | Publishers | `adagents.json` authorized_agents |
| **Governance Agent Discovery** | Who has data about this property? | Publishers | `adagents.json` property_features |
| **Property Data** | What do we know about this property? | Data providers | Governance agents via `list_property_features` |
| **Property Selection** | Which properties meet my requirements? | Buyers | Property lists with filters |

The first two are **publisher-side declarations** via adagents.json. The last two are **buyer-side operations** that consume property data from governance agents.
The first three are **publisher-side declarations** via adagents.json. The last two are **buyer-side operations** that consume property data from governance agents.

## Publisher Side: adagents.json

Publishers declare their properties and authorize sales agents via `/.well-known/adagents.json`:
Publishers declare their properties, authorize sales agents, and reference governance agents via `/.well-known/adagents.json`:

```json
{
Expand All @@ -44,11 +45,43 @@ Publishers declare their properties and authorize sales agents via `/.well-known
"authorization_type": "property_ids",
"property_ids": ["example_site"]
}
],
"property_features": [
{
"url": "https://api.scope3.com",
"name": "Scope3",
"features": ["carbon_score", "sustainability_grade"]
},
{
"url": "https://api.onetrust.com",
"name": "OneTrust",
"features": ["gdpr_compliant", "tcf_registered"]
}
]
}
```

See the [adagents.json Tech Spec](./adagents) for complete documentation.
### Governance Agent Discovery via property_features

The `property_features` array solves a key discovery problem: **how does a buyer know which governance agents have data about a given property?**

Without `property_features`, buyers would need to query every possible governance agent to find out who has compliance, sustainability, or quality data. With `property_features`, publishers declare these relationships upfront:

| Field | Purpose |
|-------|---------|
| `url` | Governance agent's API endpoint |
| `name` | Human-readable agent name (e.g., "Scope3", "TAG", "OneTrust") |
| `features` | Feature IDs this agent provides (e.g., `carbon_score`, `gdpr_compliant`) |
| `publisher_id` | Optional identifier for looking up this publisher at the agent |

**Example use cases:**
- **Sustainability**: Publisher declares Scope3 tracks their carbon emissions
- **Compliance**: Publisher declares OneTrust manages their consent data
- **Certification**: Publisher declares TAG has verified their fraud prevention

Buyers read `property_features` from adagents.json, then query only the relevant governance agents for detailed data.

See the [adagents.json Tech Spec](/docs/governance/property/adagents) for complete documentation including examples and the discovery workflow.

## Buyer Side: Property Data and Selection

Expand Down Expand Up @@ -113,8 +146,14 @@ A buyer agent typically works with **multiple governance agents** (consent, bran

```mermaid
flowchart TB
subgraph Publisher["PUBLISHER (adagents.json)"]
P1["properties: identity"]
P2["authorized_agents: sales auth"]
P3["property_features: governance refs"]
end

subgraph Buyer["BUYER AGENT"]
B1[Source of truth for compliant list]
B1[Discovers governance agents from adagents.json]
B2[Aggregates results from specialized agents]
B3[Issues auth_tokens for sellers]
end
Expand All @@ -130,66 +169,24 @@ flowchart TB
SE2[Uses cached lists for bid-time decisions]
end

Publisher -->|property_features discovery| Buyer
Buyer -->|create_property_list + webhooks| CA
Buyer -->|create_property_list + webhooks| S3
Buyer -->|create_property_list + webhooks| BS

Buyer -->|get_property_list with auth_token| Seller
```

## Campaign Lifecycle

Property governance operates across three distinct timing contexts. The key principle: **all governance evaluation happens at setup time**, with bid-time decisions using only cached data.

```mermaid
sequenceDiagram
participant O as Orchestrator
participant G as Governance Agent
participant D as Decisioning Platform

rect rgb(240, 248, 255)
Note over O,D: Phase 1: Campaign Planning (minutes-hours)
O->>G: create_property_list(filters, brand_manifest)
G-->>O: list_id, auth_token
O->>D: Share list_id + auth_token
D->>G: get_property_list(list_id, auth_token, resolve=true)
G-->>D: identifiers[] (pass/fail list, no scores)
D->>G: Register webhook for list updates
D->>D: Cache locally (optionally as AXE segments)
end

rect rgb(255, 248, 240)
Note over O,D: Phase 2: Bid Time (under 100ms, NO governance calls)
D->>D: Check domain against cached allowlist
Note right of D: May use AXE axei/axex segments<br/>or direct domain lookup
D->>D: Pass → bid, Fail → skip
end

rect rgb(248, 255, 240)
Note over O,D: Phase 3: Monitoring (during flight)
G-->>D: Webhook: list changed (counts only)
D->>G: get_property_list(list_id, auth_token, resolve=true)
G-->>D: Updated identifiers[]
D->>D: Update cached allowlist
end
```

### Phase 1: Campaign Planning

During campaign setup, the orchestrator creates property lists on governance agents with filters and brand manifests. The governance agent evaluates properties and returns a **pass/fail list of identifiers** (no raw scores are exposed). The orchestrator shares the `list_id` and `auth_token` with the decisioning platform, which fetches and caches the resolved list.

### Phase 2: Bid Time

At bid time, the decisioning platform uses **only its local cache**—no calls to governance agents. Latency requirements (under 100ms) make real-time API calls impractical. The decisioning platform may implement this cache as:

- **Direct domain lookup**: In-memory set of approved domains
- **AXE segments**: Cache domains as `axei` (include) or `axex` (exclude) segments for impression-level filtering

The choice of caching mechanism is implementation-specific; the protocol only requires that bid-time decisions use cached data.

### Phase 3: Monitoring
### The Complete Flow

During campaign flight, governance agents continue evaluating properties. When a property's compliance status changes, the agent sends a webhook notification to registered subscribers. The webhook contains **change counts only** (not scores or reasons)—the decisioning platform must call `get_property_list` to fetch the updated list and refresh its cache.
1. **Publisher declares** properties, sales agents, AND governance agents in `adagents.json`
2. **Buyer discovers** governance agents by reading `property_features` from adagents.json
3. **Buyer queries** each governance agent's `list_property_features` for detailed capabilities
4. **Buyer creates** property lists on each governance agent with filters and brand manifests
5. **Governance agents evaluate** properties and notify buyer via webhooks when lists change
6. **Buyer aggregates** results into a final compliant list
7. **Buyer shares** property list reference with sellers (with auth token)
8. **Seller caches** resolved list for bid-time decisions

## Sharing Property Lists with Sellers

Expand Down Expand Up @@ -251,31 +248,34 @@ Both protocols operate on properties but serve different purposes:

### Discovery

- **[list_property_features](./tasks/list_property_features)**: Discover what data a governance agent can provide about properties
- **[list_property_features](/docs/governance/property/tasks/list_property_features)**: Discover what data a governance agent can provide about properties

### Property List Management

- **[create_property_list](./tasks/property_lists#create_property_list)**: Create a new property list on a governance agent
- **[get_property_list](./tasks/property_lists#get_property_list)**: Retrieve resolved properties (with caching guidance)
- **[update_property_list](./tasks/property_lists#update_property_list)**: Modify filters or base properties
- **[delete_property_list](./tasks/property_lists#delete_property_list)**: Remove a property list
- **[create_property_list](/docs/governance/property/tasks/property_lists#create_property_list)**: Create a new property list on a governance agent
- **[get_property_list](/docs/governance/property/tasks/property_lists#get_property_list)**: Retrieve resolved properties (with caching guidance)
- **[update_property_list](/docs/governance/property/tasks/property_lists#update_property_list)**: Modify filters or base properties
- **[delete_property_list](/docs/governance/property/tasks/property_lists#delete_property_list)**: Remove a property list

## Getting Started

**Publishers:**
1. Create `/.well-known/adagents.json` with property definitions
2. Authorize sales agents for your properties
3. Declare governance agents in `property_features` (Scope3 for carbon, OneTrust for consent, TAG for certification, etc.)

**Buyers:**
1. Subscribe to governance agents for property data
2. Create property lists on each governance agent with filters and brand manifests
3. Aggregate results into a final compliant list
4. Share property list references with sellers (with auth tokens)
1. Discover governance agents by reading `property_features` from publishers' adagents.json files
2. Query each governance agent's `list_property_features` for capabilities
3. Create property lists on relevant governance agents with filters and brand manifests
4. Aggregate results into a final compliant list
5. Share property list references with sellers (with auth tokens)

**Governance Agent Implementers:**
1. Implement `list_property_features` to advertise your capabilities
2. Implement property list CRUD operations
3. Support webhooks to notify buyers when evaluations change
4. See the [Protocol Specification](./specification) for implementation details
4. Work with publishers to get listed in their `property_features`
5. See the [Protocol Specification](/docs/governance/property/specification) for implementation details

See the [Protocol Specification](./specification) for detailed implementation guidance.
See the [Protocol Specification](/docs/governance/property/specification) for detailed implementation guidance.
Loading