> ## Documentation Index
> Fetch the complete documentation index at: https://agenticadvertisingorg-snap-format-preview-links.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Provider Guide

> Publish signal definitions as a data provider using adagents.json. Define signal value types, authorize signal agents, and enable AI-driven audience discovery and verification through AdCP.

# Data Provider Guide

This guide explains how data providers publish signal definitions via `adagents.json` `signals[]`, enabling AI agents to discover, verify authorization, and activate signals for advertising campaigns.

## The Problem

Data providers (Pinnacle Data, Meridian Analytics, Apex Segments, etc.) own valuable audience and contextual data, but integrating with the growing ecosystem of AI-powered advertising agents presents challenges:

**Discovery is fragmented.** Each signals agent (Luminary Data, Nova DSP, etc.) needs custom integrations to know what signals you offer. There's no standard way for an AI agent to ask "what automotive purchase intent signals does Pinnacle Data have?"

**Authorization is opaque.** When a buyer receives a signal from a signals agent, they can't verify that the agent is actually authorized to resell it. They have to trust the intermediary.

**Signal semantics are inconsistent.** Without standardized definitions, an AI agent can't know whether "auto\_intenders" is a binary segment, a propensity score, or a multi-value category—making it impossible to construct proper targeting expressions.

**Scaling requires N×M integrations.** Every data provider needs custom integrations with every signals agent. This doesn't scale.

## The Solution

Published signal definitions solve these problems by letting data providers publish machine-readable descriptions of their signals at a well-known URL. This enables:

* **Discovery**: AI agents can find signals via natural language ("find automotive purchase intent signals") or structured lookup
* **Authorization verification**: Buyers can verify authorization by checking the data provider's domain directly
* **Typed targeting**: Signal definitions include value types (binary, categorical, numeric) so agents can construct correct targeting expressions
* **Scalable partnerships**: Authorize agents once in `adagents.json`; as you add signals, authorized agents automatically have access

## Overview

Data providers own audience and contextual data (purchase intent, demographics, behavioral segments). The `signals[]` publishing model lets you publish your signals in a standardized format that:

* Enables discovery via natural language queries
* Provides authorization verification for agents
* Describes signal characteristics (binary, categorical, numeric)
* Supports tag-based grouping for efficient authorization

This follows the same pattern as publishers declaring properties - instead of "what ad placements exist," you're declaring "what signals exist."

## The Parallel Pattern

| Publishers                              | Data Providers                            |
| --------------------------------------- | ----------------------------------------- |
| Declare **properties** (websites, apps) | Declare **signals** (audiences, segments) |
| Authorize agents to **sell inventory**  | Authorize agents to **resell signals**    |
| Use `property_ids` / `property_tags`    | Use `signal_ids` / `signal_tags`          |
| Buyers verify via `publisher_domain`    | Buyers verify via `data_provider_domain`  |

Both use `/.well-known/adagents.json` as the publishing mechanism. A single `adagents.json` file can declare both `properties` and `signals` simultaneously — see [Unified declaration model](/docs/governance/property/adagents#unified-declaration-model).

## File Location

Data providers host their published signal definitions at:

```
https://your-domain.com/.well-known/adagents.json
```

Following [RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615) well-known URI conventions.

## Basic Structure

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/adagents.json",
  "contact": {
    "name": "Pinnacle Auto Data",
    "email": "partnerships@pinnacle-auto-data.com",
    "domain": "pinnacle-auto-data.com"
  },
  "signals": [
    {
      "id": "likely_ev_buyers",
      "name": "Likely EV Buyers",
      "description": "Consumers modeled as likely to purchase an electric vehicle in the next 12 months",
      "value_type": "binary",
      "tags": ["automotive", "green"]
    }
  ],
  "signal_tags": {
    "automotive": {
      "name": "Automotive Signals",
      "description": "Vehicle-related audience segments"
    },
    "green": {
      "name": "Green/Sustainability",
      "description": "Environmentally-conscious consumer segments"
    }
  },
  "authorized_agents": [
    {
      "url": "https://signals-agent.example.com",
      "authorized_for": "All automotive signals",
      "authorization_type": "signal_tags",
      "signal_tags": ["automotive"]
    }
  ],
  "last_updated": "2025-01-15T10:00:00Z"
}
```

## Signal Definition

Each signal in the `signals` array describes a targetable segment:

The signal definition is not itself a `signal_ref`. In `adagents.json`, the hosting domain supplies the namespace, so the definition only needs its local `id`. A media-buy product that makes this provider-published signal selectable points back to it with `signal_ref: { "scope": "data_provider", "data_provider_domain": "<this adagents.json domain>", "signal_id": "<signals[].id>" }`. If a seller publishes its own `signals[]`, the seller can be the data-provider domain for these references; `scope: "data_provider"` means adagents.json-resolved, not necessarily third-party.

### Required Fields

| Field        | Type   | Description                                                                      |
| ------------ | ------ | -------------------------------------------------------------------------------- |
| `id`         | string | Unique identifier within your published `signals[]`. Pattern: `^[a-zA-Z0-9_-]+$` |
| `name`       | string | Human-readable signal name                                                       |
| `value_type` | enum   | Data type: `binary`, `categorical`, or `numeric`                                 |

### Optional Fields

| Field                   | Type   | Description                                                                                                                                                                                                |
| ----------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `description`           | string | Detailed description of what this signal represents                                                                                                                                                        |
| `tags`                  | array  | Tags for grouping (lowercase, alphanumeric: `^[a-z0-9_-]+$`)                                                                                                                                               |
| `allowed_values`        | array  | For categorical signals: valid values                                                                                                                                                                      |
| `range`                 | object | For numeric signals: `{ min, max, unit }`                                                                                                                                                                  |
| `restricted_attributes` | array  | Restricted attribute categories this signal touches (e.g., `["health_data"]`). Enables structural governance matching.                                                                                     |
| `policy_categories`     | array  | Policy categories this signal is sensitive for (e.g., `["children_directed"]`). Enables structural governance matching.                                                                                    |
| `taxonomy`              | object | External taxonomy metadata for discovery, review, and translation. Does not change `value_type` or package targeting grammar.                                                                              |
| `data_sources`          | array  | IAB Data Transparency Standard-aligned source categories used to compile the signal.                                                                                                                       |
| `methodology`           | enum   | How membership or attribute values were determined: `observed`, `declared`, `derived`, `inferred`, or `modeled`.                                                                                           |
| `modeling`              | object | Required when `methodology` is `modeled` or `audience_expansion` is `true`. Includes seed source, training jurisdictions, AI risk class, and disclosure notes.                                             |
| `countries`             | array  | ISO 3166-1 alpha-2 countries where the signal is applicable.                                                                                                                                               |
| `consent_basis`         | array  | GDPR Article 6 lawful basis or consent basis for processing this signal's data. Use `countries`, `policy_categories`, and disclosure fields for non-GDPR obligations.                                      |
| `data_subject_rights`   | object | Per-signal rights-routing channels and commitments for access, erasure, objection, and related requests. Use this when routing or SLA varies by signal, upstream source, or custom/private signal context. |

### Definition Enrichment

Use enrichment fields when buyers, sellers, governance agents, or regulators need more than a name and value type:

| Purpose                 | Fields                                                                                                                    | When to use                                                                                                                                                                                                                                                                                                                                                                                    |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Discovery and taxonomy  | `taxonomy`, `taxonomy.values`, `taxonomy.value_mappings`, `taxonomy.parent_match_behavior`                                | The signal maps to an external audience, content, retail-media, or provider-owned taxonomy. For categorical signals, `value_mappings` maps each package-targeting `allowed_values[]` string to a stable taxonomy node; each mapping value should match an `allowed_values[]` entry.                                                                                                            |
| Source and methodology  | `data_sources`, `methodology`, `segmentation_criteria`, `criteria_url`, `refresh_cadence`, `lookback_window`, `onboarder` | The provider wants DTS-style transparency. `onboarder` is required for offline or public-record sources.                                                                                                                                                                                                                                                                                       |
| Modeling and disclosure | `modeling`, `audience_expansion`, `device_expansion`                                                                      | Required when `methodology` is `modeled` or `audience_expansion` is `true`. `device_expansion` is for deterministic cross-device expansion; probabilistic cross-device inference should use modeling. `modeling.training_data_jurisdictions` must be non-empty. If `modeling.disclosure.required` is `true`, `modeling.disclosure.jurisdictions` is required.                                  |
| Privacy and governance  | `countries`, `consent_basis`, `restricted_attributes`, `policy_categories`, `art9_basis`                                  | The signal may be jurisdictionally limited, policy-sensitive, or subject to special-category review.                                                                                                                                                                                                                                                                                           |
| Rights routing          | `data_subject_rights`                                                                                                     | Rights requests route differently by signal or upstream source. Each routing block must include at least one channel supporting one or more of access, erasure, or objection. `response_sla_days` is the maximum response time for the declared channels. Signal definitions do not declare Global Privacy Control support, and consumers must not infer GPC handling from this routing block. |

```json theme={null}
{
  "id": "vehicle_ownership",
  "name": "Current vehicle ownership",
  "description": "Declared or inferred current household vehicle ownership.",
  "value_type": "categorical",
  "allowed_values": ["luxury_ev", "luxury_non_ev", "mid_range", "economy", "none"],
  "taxonomy": {
    "ref": "https://taxonomy.example.com/audience/v1",
    "version": "1.0",
    "values": [
      { "id": "auto.vehicle_ownership", "path": "Automotive > Vehicle ownership" }
    ],
    "value_mappings": [
      {
        "value": "luxury_ev",
        "taxonomy_value_id": "auto.vehicle_ownership.luxury_ev",
        "path": "Automotive > Vehicle ownership > Luxury EV"
      }
    ],
    "parent_match_behavior": "exact_only"
  },
  "data_sources": ["online_survey", "transaction"],
  "methodology": "derived",
  "subject_type": "household",
  "resolution_method": "mixed",
  "countries": ["US"],
  "consent_basis": ["consent"],
  "data_subject_rights": {
    "channels": [
      {
        "rights": ["access", "erasure", "objection"],
        "url": "https://privacy.pinnacle-data.example/requests",
        "countries": ["US"]
      }
    ],
    "response_sla_days": 30
  }
}
```

Taxonomy parent nodes do not imply targeting expansion by themselves. If `parent_match_behavior` is `descendants_supported`, the seller may expand known, version-pinned parent nodes internally, typically by ORing children in its execution system. Package targeting still uses the signal's declared `value_type`.

### Publishing large definition resources

Provider-published `adagents.json` is the authoritative definition surface, but
large external resources do not need to be duplicated in every `get_signals`
listing. For large taxonomies, long segmentation criteria, or
jurisdiction-specific disclosure text, publish stable pointers such as `taxonomy.ref`,
`criteria_url`, and `modeling.disclosure.jurisdictions[].disclosure_url`; use
`taxonomy.etag` when the taxonomy has its own freshness validator. For
provider-published public signals, the `signal_ref` already points to the
authoritative definition: fetch the provider's `/.well-known/adagents.json`
(following `authoritative_location` when present) and select the matching
`signals[].id`. Buyers cache the fetched `adagents.json` document by resolved
authoritative URL plus the existing `catalog_etag`, HTTP `ETag`/`Last-Modified`,
or a bounded TTL; clients must not key signal-definition caches by validator
alone. No signal-specific validator is required. Signal agents can then return
compact discovery listings while buyers fetch the full definition only when they
need the deeper review context.

## Signal Value Types

### Binary Signals

User either matches or doesn't. Most common type.

```json theme={null}
{
  "id": "likely_ev_buyers",
  "name": "Likely EV Buyers",
  "value_type": "binary",
  "tags": ["automotive", "purchase_intent"]
}
```

**Targeting**: Include or exclude users matching this signal.

### Categorical Signals

User has one of several possible values.

```json theme={null}
{
  "id": "vehicle_ownership",
  "name": "Current Vehicle Ownership",
  "value_type": "categorical",
  "allowed_values": ["luxury_ev", "luxury_non_ev", "mid_range", "economy", "none"]
}
```

**Targeting**: Target users with specific values (e.g., "users who own a luxury EV or luxury non-EV").

### Numeric Signals

User has a score or measurement within a range.

```json theme={null}
{
  "id": "purchase_propensity",
  "name": "Auto Purchase Propensity",
  "value_type": "numeric",
  "range": {
    "min": 0,
    "max": 1,
    "unit": "score"
  }
}
```

**Targeting**: Target users within a value range (e.g., "propensity score > 0.7").

## Authorization Patterns

### Pattern 1: Signal IDs (Direct References)

Authorize specific signals by ID:

Here `signal_ids` means local catalog IDs from this `adagents.json` `signals[]` array, not the deprecated `SignalId` object used by older Signals Protocol payloads.

```json theme={null}
{
  "authorized_agents": [
    {
      "url": "https://premium-agent.example.com",
      "authorized_for": "Premium automotive signals only",
      "authorization_type": "signal_ids",
      "signal_ids": ["likely_ev_buyers", "luxury_auto_intenders"]
    }
  ]
}
```

**Best for**: Specific, limited signal sets. Fine-grained control.

### Pattern 2: Signal Tags (Efficient Grouping)

Authorize all signals with certain tags:

```json theme={null}
{
  "authorized_agents": [
    {
      "url": "https://full-signal-agent.example.com",
      "authorized_for": "All automotive signals",
      "authorization_type": "signal_tags",
      "signal_tags": ["automotive"]
    }
  ]
}
```

**Best for**: Large signal sets. As you add signals with the tag, agents automatically get access.

## Signal Tags

The `signal_tags` object provides metadata for tags used in signals:

```json theme={null}
{
  "signal_tags": {
    "automotive": {
      "name": "Automotive Signals",
      "description": "Vehicle ownership, purchase intent, and service signals"
    },
    "premium": {
      "name": "Premium Signals",
      "description": "High-value segments with enhanced pricing"
    }
  }
}
```

**Why define tags?**

* Human-readable context for buyers exploring your signal definitions
* Enables efficient authorization ("all premium signals")
* Groups related signals for easier discovery

## How Buyers Use Your Signal Definitions

### 1. Discovery

Buyers call `get_signals` on a signals agent. The agent may use your published definitions for:

* Natural language matching ("find automotive purchase intent signals")
* Structured lookup by `signal_ref`

### 2. Authorization Verification

When a buyer receives a signal, they can verify authorization:

```json theme={null}
{
  "signal_ref": {
    "scope": "data_provider",
    "data_provider_domain": "pinnacle-auto-data.com",
    "signal_id": "likely_ev_buyers"
  }
}
```

The buyer fetches `https://pinnacle-auto-data.com/.well-known/adagents.json` and checks:

1. Does the signal exist in the `signals` array?
2. Is the signals agent in `authorized_agents`?
3. Does the authorization cover this signal (by ID or tag)?

### 3. Targeting

Based on `value_type`, buyers construct targeting expressions:

```json theme={null}
// Binary targeting
{
  "signal_ref": { "scope": "data_provider", "data_provider_domain": "pinnacle-auto-data.com", "signal_id": "likely_ev_buyers" },
  "value_type": "binary",
  "value": true
}

// Categorical targeting
{
  "signal_ref": { "scope": "data_provider", "data_provider_domain": "pinnacle-auto-data.com", "signal_id": "vehicle_ownership" },
  "value_type": "categorical",
  "values": ["luxury_ev", "luxury_non_ev"]
}

// Numeric targeting
{
  "signal_ref": { "scope": "data_provider", "data_provider_domain": "pinnacle-auto-data.com", "signal_id": "purchase_propensity" },
  "value_type": "numeric",
  "min_value": 0.7
}
```

## Local and External Signal References

Not all signals come from third-party data providers. Sellers and publishers can also define their own signals - custom models, first-party data, or composite segments - the same way they define other named resources in `adagents.json`. When those signals are meant to be portable and externally referenceable, publish them in the `signals` array and reference them from products with `scope: "data_provider"` using the seller's own publishing domain. When they are only meaningful within one product/package context, expose them only as product-local `signal_targeting_options` with `scope: "product"`.

Use `signal_ref` for `get_signals`, media-buy product targeting, and package-level buy-time targeting:

| Reference                                                                                                                                    | Meaning                                                                             |
| -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `{ "scope": "product", "signal_id": "high_intent_shoppers" }`                                                                                | Product-local signal option, meaningful inside the selected product/package context |
| `{ "scope": "data_provider", "data_provider_domain": "pinnacle-data.example", "signal_id": "auto_intenders" }`                               | Signal defined in a data provider's published adagents.json `signals[]`             |
| `{ "scope": "signal_source", "signal_source_url": "https://signals.example/.well-known/adcp/signals", "signal_id": "custom_model_run_123" }` | Source-native signal not published in upstream adagents.json `signals[]`            |

```json theme={null}
{
  "signal_ref": { "scope": "product", "signal_id": "custom_auto_intenders" },
  "value_type": "binary",
  "value": true
}
```

```json theme={null}
{
  "signal_ref": {
    "scope": "data_provider",
    "data_provider_domain": "pinnacle-data.example",
    "signal_id": "auto_intenders"
  },
  "value_type": "binary",
  "value": true
}
```

The older `signal_id.source` shape is deprecated and retained only for backwards compatibility with older Signals Protocol clients. New discovery, activation, and media-buy targeting surfaces use `signal_ref`. For product-local signals exposed on both `get_products` and a product-contextual `get_signals` response, `signal_ref.signal_id` MUST match across both surfaces.

## Complete Example

A full `adagents.json` signal definition set for an automotive data provider:

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/adagents.json",
  "contact": {
    "name": "Pinnacle Auto Data",
    "email": "partnerships@pinnacle-auto-data.com",
    "domain": "pinnacle-auto-data.com"
  },
  "signals": [
    {
      "id": "likely_ev_buyers",
      "name": "Likely EV Buyers",
      "description": "Consumers modeled as likely to purchase an electric vehicle in the next 12 months based on vehicle registration, financial, and behavioral data",
      "value_type": "binary",
      "tags": ["automotive", "premium"]
    },
    {
      "id": "vehicle_ownership",
      "name": "Current Vehicle Ownership",
      "description": "Current vehicle category owned by the consumer",
      "value_type": "categorical",
      "allowed_values": ["luxury_ev", "luxury_non_ev", "mid_range", "economy", "none"],
      "tags": ["automotive"]
    },
    {
      "id": "purchase_propensity",
      "name": "Auto Purchase Propensity",
      "description": "Likelihood score of purchasing any new vehicle in the next 6 months",
      "value_type": "numeric",
      "range": { "min": 0, "max": 1, "unit": "score" },
      "tags": ["automotive"]
    }
  ],
  "signal_tags": {
    "automotive": {
      "name": "Automotive Signals",
      "description": "Vehicle-related audience segments"
    },
    "premium": {
      "name": "Premium Signals",
      "description": "High-value premium audience segments with enhanced pricing"
    }
  },
  "authorized_agents": [
    {
      "url": "https://luminary-data.com/.well-known/adcp/signals",
      "authorized_for": "All Pinnacle automotive signals via Luminary Data",
      "authorization_type": "signal_tags",
      "signal_tags": ["automotive"]
    },
    {
      "url": "https://nova-dsp.com/.well-known/adcp/signals",
      "authorized_for": "Pinnacle premium signals only",
      "authorization_type": "signal_ids",
      "signal_ids": ["likely_ev_buyers"]
    }
  ],
  "last_updated": "2025-01-15T10:00:00Z"
}
```

## Location data provider example

A geo/mobility provider's published signal definitions use the same structure but with location-specific signals. Here's the `signals` array for a provider publishing foot traffic and mobility data:

```json theme={null}
{
  "signals": [
    {
      "id": "store_visitors",
      "name": "Store Visitors",
      "description": "Consumers who visited a specified retail location in the past 30 days based on opted-in mobile device data",
      "value_type": "binary",
      "tags": ["geo", "foot_traffic"]
    },
    {
      "id": "visit_frequency",
      "name": "Location Visit Frequency",
      "description": "Monthly visit count to a specified location category",
      "value_type": "numeric",
      "range": { "min": 0, "max": 30, "unit": "visits_per_month" },
      "tags": ["geo", "frequency"]
    },
    {
      "id": "commute_pattern",
      "name": "Commute Pattern",
      "description": "Categorized daily commute behavior based on observed travel patterns",
      "value_type": "categorical",
      "allowed_values": ["urban_transit", "suburban_driver", "remote_worker", "hybrid"],
      "tags": ["geo", "behavioral"]
    }
  ]
}
```

Note how the three value types map to different geo concepts: `binary` for yes/no store visitation, `numeric` for visit frequency with a meaningful range, and `categorical` for classified mobility behavior.

## Identity / demographic provider example

An identity company's published signal definitions can include consumer segments derived from financial records, surveys, and public data. Note: these are **targeting segments**, not raw data. Credit-derived signals may carry regulatory obligations (FCRA) — consult your compliance team before publishing.

```json theme={null}
{
  "signals": [
    {
      "id": "household_income",
      "name": "Household Income Tier",
      "description": "Modeled household income bracket based on financial and demographic indicators",
      "value_type": "categorical",
      "allowed_values": ["under_50k", "50k_75k", "75k_100k", "100k_150k", "150k_250k", "over_250k"],
      "tags": ["demographic", "income"]
    },
    {
      "id": "life_stage",
      "name": "Life Stage",
      "description": "Life stage classification derived from demographic and behavioral indicators",
      "value_type": "categorical",
      "allowed_values": ["young_adult", "early_career", "established_family", "empty_nester", "retired"],
      "tags": ["demographic", "life_stage"]
    },
    {
      "id": "credit_active",
      "name": "Active Credit Seeker",
      "description": "Consumer has actively applied for new credit products in the past 90 days",
      "value_type": "binary",
      "tags": ["financial", "in_market", "credit"]
    }
  ]
}
```

Identity companies often also provide cross-device identity graphs, but identity resolution as a service (matching Device A to Person B) is not yet part of the AdCP protocol. See the [signals ecosystem guide](/docs/signals/ecosystem#identity-companies) for more on this boundary.

## Retail media provider example

Retailers have first-party purchase data that doubles as high-value targeting signals. A retail media network can publish signals alongside its properties in the same `adagents.json`:

```json theme={null}
{
  "signals": [
    {
      "id": "category_buyer",
      "name": "Category Buyer",
      "description": "Purchased in the specified product category within the past 90 days",
      "value_type": "categorical",
      "allowed_values": ["electronics", "home", "beauty", "grocery", "fashion"],
      "tags": ["retail", "purchase"]
    },
    {
      "id": "purchase_frequency",
      "name": "Monthly Purchase Frequency",
      "description": "Number of purchases in a product category over the trailing 90 days",
      "value_type": "numeric",
      "range": { "min": 0, "max": 50, "unit": "purchases" },
      "tags": ["retail", "frequency"]
    },
    {
      "id": "new_to_brand",
      "name": "New to Brand",
      "description": "Consumer has no prior purchase history with the specified brand in the trailing 12 months",
      "value_type": "binary",
      "tags": ["retail", "conquest"]
    }
  ]
}
```

Retail signals are especially valuable because they're deterministic — based on actual purchases, not modeled behavior. See the [signals ecosystem guide](/docs/signals/ecosystem#retail-media-networks) for the dual-role pattern (publisher + data provider).

## Validation

Use the [AdAgents.json Builder](https://agenticadvertising.org/adagents/builder) to validate your published signal definitions, or validate programmatically:

```bash theme={null}
curl -X POST https://adcontextprotocol.org/api/adagents/validate \
  -H "Content-Type: application/json" \
  -d '{"domain": "your-domain.com"}' | jq '.data.validation'
```

The validator checks:

* Required fields (`id`, `name`, `value_type` for each signal)
* ID patterns (alphanumeric with underscores/hyphens)
* Tag consistency (tags used in signals should be defined in `signal_tags`)
* Authorization references (signal\_ids/signal\_tags should reference existing signals/tags)

## Best Practices

### 1. Use Descriptive IDs

```json theme={null}
// Good
{ "id": "likely_ev_buyers" }
{ "id": "household_income_150k_plus" }

// Avoid
{ "id": "seg_12345" }
{ "id": "a1b2c3" }
```

### 2. Provide Complete Metadata

Include `description` so buyers understand what each signal represents.

### 3. Use Tags for Scalability

As your signal set grows, tags enable efficient authorization without listing every signal ID.

### 4. Document Value Types Clearly

For categorical signals, always include `allowed_values`. For numeric signals, include `range` with `unit`.

### 5. Keep Files Updated

Update `last_updated` timestamp when signals change. Buyers cache these files - stale data causes authorization failures.

## Declaring governance metadata

Signal definitions support two optional fields that enable structural governance matching: `restricted_attributes` and `policy_categories`. When declared, governance agents can match signals against a campaign plan's restrictions deterministically instead of relying on semantic inference from signal names.

### restricted\_attributes

Declare which GDPR Article 9 special categories of personal data a signal touches. Values: `racial_ethnic_origin`, `political_opinions`, `religious_beliefs`, `trade_union_membership`, `health_data`, `sex_life_sexual_orientation`, `genetic_data`, `biometric_data`.

```json theme={null}
{
  "id": "chronic_condition_hh",
  "name": "Chronic Condition Households",
  "description": "Households with modeled indicators of chronic health conditions",
  "value_type": "binary",
  "tags": ["health", "demographic"],
  "restricted_attributes": ["health_data"]
}
```

When a campaign plan declares `restricted_attributes: ["health_data"]`, a governance agent blocks this signal without needing to interpret the description.

### policy\_categories

Declare which policy categories a signal is sensitive for. Policy categories group related regulatory regimes — `children_directed` covers COPPA, UK AADC, and GDPR Article 8. Values are registry-defined category IDs.

```json theme={null}
{
  "id": "kids_cartoon_fans",
  "name": "Kids Cartoon Fans",
  "description": "Children aged 6-12 who watch animated content",
  "value_type": "binary",
  "tags": ["entertainment", "children"],
  "policy_categories": ["children_directed"]
}
```

### Combining both fields

A signal can declare both when it touches restricted personal data and is relevant to a specific regulatory regime:

```json theme={null}
{
  "id": "fertility_intent",
  "name": "Fertility Intent",
  "description": "Consumers researching fertility treatments",
  "value_type": "binary",
  "tags": ["health", "life_stage"],
  "restricted_attributes": ["health_data"],
  "policy_categories": ["pharmaceutical_advertising"]
}
```

Without governance metadata, a governance agent must infer sensitivity from signal names — this is fragile and produces false positives. Declared attributes enable deterministic matching.

### Relationship to the Policy Registry

Signal definitions declare `policy_categories` and `restricted_attributes` using the same vocabulary as the [Policy Registry](/docs/governance/policy-registry). These fields enable governance agents to match signal metadata against policy entries during campaign validation.

| Signal field            | Registry equivalent                                                                                               | Purpose                                                                                                           |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `policy_categories`     | `policy_categories` on [policy entries](/docs/governance/policy-registry#policy-category-definitions)             | Declares which regulatory regimes the signal touches (e.g., `children_directed`, `health_wellness`)               |
| `restricted_attributes` | `restricted_attributes` on [policy categories](/docs/governance/policy-registry#restricted-attribute-definitions) | Declares which GDPR Article 9 special categories the signal touches (e.g., `health_data`, `racial_ethnic_origin`) |

Values MUST match the canonical definitions in the Policy Registry. See [policy category definitions](/docs/governance/policy-registry#policy-category-definitions) for the full list of valid `policy_categories` values and [restricted attribute definitions](/docs/governance/policy-registry#restricted-attribute-definitions) for valid `restricted_attributes` values.

## Integration with get\_adcp\_capabilities

Signal agents advertise available data providers via `get_adcp_capabilities`:

```json theme={null}
{
  "signals": {
    "data_provider_domains": ["pinnacle-auto-data.com", "meridian-analytics.com", "apex-segments.com"]
  }
}
```

This tells buyers which data providers' published signal definitions the agent can access.

## Next Steps

1. **Create your adagents.json** with your published signal definitions
2. **Host at** `/.well-known/adagents.json` on your domain
3. **Validate** using the AdAgents.json Builder
4. **Partner with signals agents** who will resell your data
5. **Add agents to authorized\_agents** as partnerships are established

## Related Documentation

* [Signals Protocol Overview](/docs/signals/overview) - How signals work in AdCP
* [get\_signals Task](/docs/signals/tasks/get_signals) - Signal discovery API
* [activate\_signal Task](/docs/signals/tasks/activate_signal) - Signal activation API
* [adagents.json Tech Spec](/docs/governance/property/adagents) - Full adagents.json reference (property-focused)
