TheDocumentation Index
Fetch the complete documentation index at: https://docs.adcontextprotocol.org/llms.txt
Use this file to discover all available pages before exploring further.
adagents.json file provides a standardized way for publishers to declare their properties and authorize sales agents. This is the foundation of Property Governance - it defines what properties exist and who can sell them.
Unified declaration model
adagents.json serves as the declaration mechanism for both property authorization and signal data provider registration. A single file at /.well-known/adagents.json can declare both properties and signals top-level fields simultaneously.
properties) and declares signal catalogs (via signals). The two namespaces are independent: authorization for property sales does not grant signal access, and signal registration does not imply property authorization.
See Signal data providers for the signals-side documentation.
Why adagents.json instead of ads.txt
ads.txt answers a narrower question: is this seller present on the publisherβs list, and is the relationship labeled DIRECT or RESELLER?
That is useful, but it is too flat for many modern publisher sales models. It does not tell buyers:
- which property is covered
- which placements are covered
- whether the path is direct, delegated, or network-mediated
- whether the authorization is country-limited or time-bounded
- whether a network-managed slot is the same thing as a publisher-managed premium placement
adagents.json is designed to carry that structure. It lets publishers declare property identity, placement identity, delegation type, scoped authorization, and publisher-defined grouping tags in one place.
| Question | ads.txt | adagents.json |
|---|---|---|
| Is this seller declared at all? | Yes | Yes |
| Which property is covered? | No | Yes |
| Which placement is covered? | No | Yes |
| Can the publisher group inventory into governed buckets? | No | Yes, via placement_tags |
| Can authorization vary by country or time window? | No | Yes |
| Can the path be described as direct, delegated, or network-mediated? | Very weakly | Yes, via delegation_type |
Where does sellers.json fit?
In programmatic,sellers.json is hosted by the seller/exchange and declares which publishers they represent. AdCP handles this through brand.json instead of a separate file. An operator declares properties in their brand.json using the relationship field, which uses the same values as delegation_type: direct, delegated, or ad_network. This creates the same bilateral verification pattern:
| Programmatic | AdCP equivalent | Purpose |
|---|---|---|
ads.txt (publisher) | adagents.json with delegation_type (publisher) | βThese agents are authorized, hereβs the relationshipβ |
sellers.json (seller) | brand.json properties with relationship (operator) | βI sell for these publishers, hereβs howβ |
delegation_type and relationship values should match. See ad networks for how this works in practice.
The field is called
delegation_type in adagents.json and relationship in brand.json. The names differ because they describe the same commercial arrangement from different perspectives β the publisher delegates authority (delegation_type), the operator declares its relationship to the property (relationship). The values are the same: direct, delegated, ad_network.File Location
Publishers must host theadagents.json file at:
Basic Structure
The file must be valid JSON with UTF-8 encoding and return HTTP 200 status.Schema Fields
$schema (optional): JSON Schema reference for validation
contact (optional): Contact info for entity managing this file
name(required): Name of managing entity (may be publisher or third-party)email(optional): Contact email for questions/issuesdomain(optional): Primary domain of managing entityseller_id(optional): Seller ID from IAB Tech Lab sellers.jsontag_id(optional): TAG Certified Against Fraud IDprivacy_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)
supported_channels(optional): Advertising channels this property supports (e.g.,["display", "olv", "social"]). See Media Channel Taxonomy.
collections (optional): Collections produced or distributed by this publisher
- Products reference these via
collectionsselectors withpublisher_domainandcollection_ids - Useful when authorization needs to be scoped to specific series, podcasts, streams, or recurring content programs
placements (optional): Canonical placement definitions for the properties in this file
- Products SHOULD reuse these
placement_idvalues when declaringplacements - Reusing a registered
placement_idmeans the product is referring to the same semantic placement, not inventing a different one with the same ID - Placement definitions can include
tagsfor grouping,property_idsorproperty_tagsfor property linkage, and optionalformat_idsfor canonical format support - Authorization entries can narrow scope to specific
placement_ids - Authorization entries can also use
placement_tagsfor governed placement groupings such asprogrammatic,direct_only, ormanaged_by_riverline - Useful for expressing distinctions like βavailable via this agent only for homepage native feedβ or βonly for pre-rollβ
tags (optional): Tag metadata providing human-readable context and enabling efficient grouping
placement_tags (optional): Metadata for publisher-defined placement tags
- Provides human-readable definitions for placement tag values used in
placements[*].tagsandauthorized_agents[*].placement_tags - These are publisher-local concepts, not a global taxonomy
authorized_agents (required): Array of authorized sales agents
url(required): Agentβs API endpoint URLauthorized_for(required): Human-readable authorization descriptionauthorization_type(required): Discriminator naming which selector field carries the scope. One ofproperty_ids,property_tags,inline_properties,publisher_properties(for properties) orsignal_ids,signal_tags(for signal providers). The corresponding selector field must be present and non-empty β see Authorization Patterns below.delegation_type(optional): Commercial relationship for this path:direct,delegated, orad_networkcollections(optional): Additional collection selectors that narrow authorization to specific content programsplacement_ids(optional): Placement IDs from the top-levelplacementsarray that narrow authorization to specific placementsplacement_tags(optional): Publisher-defined placement tags that narrow authorization to governed placement groupscountries(optional): ISO 3166-1 alpha-2 country codes limiting where the authorization applieseffective_from/effective_until(optional): Time window for the authorizationexclusive(optional): Whether this is the publisherβs sole authorized path for the scoped inventory slicesigning_keys(optional): Publisher-attested public keys buyers can pin when verifying signed agent responseslast_updated(optional): ISO 8601 timestamp when thisauthorized_agents[]entry last changed. Independent of the file-levellast_updated. Advisory β enables validators to skip unchanged entries on partial walks. See managed-networks security for the conditional-refresh protocol it enables.- Additional fields: Depends on authorization_type (see patterns below)
revoked_publisher_domains (optional, managed-network use): Top-level array of publisher domains explicitly removed from a managed networkβs authoritative file. Each entry has publisher_domain, revoked_at (ISO 8601), and optional reason. Validators MUST treat any listed domain as no-longer-authorized regardless of where else it appears in the file. See Publisher revocation for the operational lifecycle and validator-side durability rule.
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/agentfeatures(required): Array of feature IDs this agent provides (e.g.,["carbon_score", "mfa_score"])publisher_id(optional): Publisherβs identifier at this agent (for lookup)
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.
When to Use URL References
- CDN Distribution: Serve authorization data from a global CDN for better performance
- Centralized Management: Single source of truth across multiple domains
- Large Files: When authorization data is too large for inline embedding
- Dynamic Updates: When authorization needs frequent updates without touching domain files
URL Reference Structure
Requirements
- HTTPS Required: The
authoritative_locationmust use HTTPS - No Nested References: The authoritative file cannot itself be a URL reference (prevents infinite loops)
- Same Schema: The authoritative file must be a valid inline adagents.json structure
- Single Hop: Only one level of URL indirection is allowed
Discovery fallback: ads.txt managerdomain
When https://{publisher}/.well-known/adagents.json returns 404, validators MAY attempt a compatibility fallback via https://{publisher}/ads.txt:
- Read
ads.txtand parsemanagerdomainentries.- Accepted form:
MANAGERDOMAIN=example.com(IAB directive form only). - Key matching is case-insensitive (
MANAGERDOMAIN,managerdomain, etc.).
- Accepted form:
- If one or more eligible managerdomain entries remain, use the last eligible entry in file order and attempt
https://{managerdomain}/.well-known/adagents.json. - If that manager file validates and explicitly scopes authorization to the source publisher domain, treat it as the discovered authorization source for this lookup.
Safety rules for this fallback
-
One hop only: maximum depth is exactly one (
publisher -> managerdomain). Do not chain managerdomain lookups. -
Cycle detection required: if
managerdomainpoints to a visited domain, ignore it. -
#noagentsopt-out: if a managerdomain line has a trailing comment containing the tokennoagents(case-insensitive), clients MUST ignore that managerdomain for adagents discovery. Example:MANAGERDOMAIN=example.com #NOAGENTS. -
Explicit publisher scoping required: a manager-hosted
adagents.jsonMUST positively name the source publisher domain in apublisher_domainfield that is reachable from at least oneauthorized_agents[]entry. βReachableβ means one of the following paths resolves to the source domain:- Per-agent paths. The agent entry directly carries the publisher domain under
publisher_properties[].publisher_domain, insidepublisher_properties[].publisher_domains[](the compact managed-network form), or undercollections[].publisher_domain. - Property-level paths. The agent entry references one or more top-level
properties[]entries by ID (property_ids) or by tag (property_tags), and at least one resolved property carries apublisher_domainmatching the source. This is the shape used in production by Mediavine and other managed networks where a property declares itspublisher_domainonce and many agents reference it indirectly.
inline_propertiesselector whose inline properties omitpublisher_domain, or a top-levelproperty_tagsselector whose resolved top-level properties carry no matchingpublisher_domain. If no reachablepublisher_domainfield matches the source, fallback MUST fail closed. The attack this protects against is implicit scoping β authorization that does not name the publisher anywhere the manager has to type the domain. Indirection throughproperties[].publisher_domainis safe because the manager has positively spelled the publisherβs domain in the same manifest; the gate filters to properties whosepublisher_domainmatches the source before considering the reference. - Per-agent paths. The agent entry directly carries the publisher domain under
-
No success by silence: if the manager lookup fails, treat the publisher as missing
adagents.json(same as no fallback).
/.well-known/adagents.json location.
Example Use Case: Multi-Domain Publisher
A publisher with multiple domains can maintain one authoritative file: On each domain (https://domain1.com/.well-known/adagents.json, https://domain2.com/.well-known/adagents.json, etc.):
https://cdn.publisher.com/adagents/v2/adagents.json):
Validation Behavior
When AdCP validators encounter a URL reference:- Fetch Reference: Retrieve the file at
/.well-known/adagents.json - Detect Reference: Check for
authoritative_locationfield - Validate URL: Ensure
authoritative_locationis HTTPS and valid - Fetch Authoritative: Retrieve content from
authoritative_location - Prevent Loops: Reject if authoritative file is also a reference
- Validate Structure: Validate the authoritative file as normal inline structure
Caching Recommendations
- Cache reference files for 24 hours minimum
- Cache authoritative files separately with their own TTL
- Use
last_updatedtimestamp to detect when cache should be invalidated - Implement exponential backoff for failed fetches
Cache-Control on the origin.
Authorization Patterns
AdCP supports four authorization patterns, each optimized for different use cases:Pattern 1: Property IDs (Direct References)
Best for: Specific, enumerable property lists. Direct and unambiguous. Structure:property_ids array. The properties must be defined in the top-level properties array.
Pattern 2: Property Tags (Efficient Grouping)
Best for: Large networks where one tag can reference hundreds/thousands of properties. Provides grouping efficiency without listing every property ID. Key Insight: Tags are not just βhuman-readable metadataβ - theyβre a performance optimization. A publisher with 500 properties can use one tag to authorize all of them, rather than listing 500 property IDs. Structure:tags array in each property definition.
Pattern 3: Inline Properties
Best for: Small, specific property sets without top-level property declarations. Structure:properties array. Useful when each agent has unique property definitions.
Pattern 4: Publisher Property References
Best for: Third-party agents representing multiple publishers. Single source of truth for property definitions. Structure:publisher_domain points to the publisher, and selection_type determines how to resolve properties (by_id or by_tag).
Compact form for managed networks (publisher_domains): when the same predicate applies to many publishers β the canonical managed-network shape β replace the singular publisher_domain with the plural publisher_domains array. Each publisher_properties[] entry takes exactly one of publisher_domain or publisher_domains; both are equivalent for resolution and both satisfy the managerdomain fallback safety rule for every listed domain.
The compact form is available on selection_type: "all" and "by_tag" only. It is intentionally NOT available on selection_type: "by_id": property IDs are publisher-scoped, and fanning the same ID set across N publishersβ files would silently authorize whichever inventory happens to share an ID at each publisher. Use one publisher_properties[] entry per publisher when each publisherβs ID set differs. Validators MUST reject by_id selectors that include publisher_domains[].
Validators MUST reject any publisher_properties[] entry that includes both publisher_domain and publisher_domains, and MUST reject any entry that includes neither. Implementations MAY mix the two forms across entries β for example, use the compact form for the bulk of represented publishers and a singular-form entry for an outlier publisher with a different tag predicate.
publisher_domains[] is resolved independently and in parallel against that publisherβs adagents.json:
- Resolution is consumer-side, not publish-side. The manager file MUST NOT inline copies of each represented publisherβs properties; consumers (validators, buyer agents indexing the file) fetch each listed publisherβs own
adagents.jsonto resolve the selector predicate. The manager file is the authorization declaration; the per-publisher files are the property catalog. - If a listed publisherβs
adagents.jsonis unreachable (404, 5xx, timeout, fails its own validation), the selector resolves to the empty set for that publisher only β the entry remains valid for all other listed publishers. Consumers MUST NOT treat a single unreachable publisher as poisoning the rest of the compact entry. - If a listed publisherβs
adagents.jsoncarries no properties matching the predicate (no entries with the named tag), the selector resolves to the empty set for that publisher. Same partial-resolution rule applies. - Resolution caching follows each publisherβs own cache policy on their
adagents.json, independently. A consumer SHOULD NOT extend or shorten one publisherβs cache TTL based on observations of another publisher in the same compact entry.
Authorization Qualifiers
The fourauthorization_type patterns above answer which inventory an agent can sell. The optional qualifiers below answer how that inventory is being made available.
delegation_type
direct: The publisher treats this endpoint as a direct way to buy from them, even if a third party operates the software behind the scenesdelegated: The agent is authorized to sell on the publisherβs behalfad_network: The inventory is sold through a network/package sales path rather than as the publisherβs direct endpoint
collections
Use collections when authorization should only apply to inventory associated with specific content programs. This is especially useful for CTV, streaming, podcasting, and creator inventory where the same property can carry many collections with different commercial arrangements.
placement_ids
Use placement_ids to narrow authorization to canonical placements published in this same adagents.json. This is the field that lets a publisher say βthis agent is authorized for MSN homepage native feed, but not for the entire propertyβ or βthis network can sell pre-roll but not host-read sponsorships.β
Canonical placement definitions can also carry:
tagsfor grouping placements across properties and productsproperty_idsorproperty_tagsto answer βwhat placements are on property X?β and βwhat properties is placement Y on?βformat_idsto answer βwhat formats does this placement support?β without relying entirely on product-local placement definitions
placement_tags
Use placement_tags when authorization should apply to a governed placement group rather than a hand-maintained list of placement IDs. This is useful for commercial access patterns such as:
programmaticdirect_onlypublisher_managedmanaged_by_taboola
placement_tags metadata the same way property tags are documented in top-level tags.
signing_keys
Use signing_keys when the publisher wants to pin the public keys an authorized agent is allowed to sign with. This avoids trusting key discovery from the agent domain alone.
- These are publisher-attested trust anchors, not just convenience metadata
- Buyers should verify signed agent responses against the pinned keys in
adagents.json - If an agent domain is compromised, pinned keys prevent the attacker from silently swapping both the endpoint and its advertised keys
signing_keys for any authorized agent whose delegated scopes include mutating operations β any AdCP task that writes state on behalf of the publisher. In the 3.x catalog this means the media-buy task set (create_media_buy, update_media_buy, sync_creatives, update_performance_index) and any future task flagged as mutating in the media-buy task reference. Read-only discovery tasks (get_products, get_signals, list_creative_formats) are out of scope for this requirement. Leaving signing_keys empty for a mutating-scope authorization reduces the trust chain to counterparty-controlled jwks_uri discovery and forfeits the publisherβs pin as a cross-check.
Verifier requirement: if the publisherβs adagents.json entry for an agent contains signing_keys, the verifier MUST reject any signature whose keyid is not in that pinned set, regardless of jwks_uri contents. The pin is authoritative; the agent-hosted JWKS is advisory and MUST NOT override it.
Key rotation and cache semantics. To keep the pin usable across rotations without opening a DoS-by-rotation window:
- Verifiers SHOULD cache the pinned
signing_keysfor at most theCache-Controlmax-agethe publisher serves onadagents.json, defaulting to one hour when no directive is present. Longer caching risks rejecting a legitimate rotated key. - On encountering an unknown
keyid, the verifier MUST force-refresh the publisherβsadagents.json(bypassing cache) before final rejection. This prevents a stale cache from locking out a legitimately rotated key. - Publishers MAY carry overlapping keys in
signing_keysduring a rotation window so verifiers can accept signatures produced under either the old or the new key. The pinned set is unordered: presence in the set is sufficient for acceptance. Operators SHOULD remove the retired key from the pin once they are confident no in-flight traffic is still signing with it (hours, not days).
adagents.json can rewrite the pin itself). First-ever retrieval of adagents.json is TLS-trust-only; the R-1 root-of-trust / key-transparency work (tracked in specs/registry-change-feed.md Β§Feed-event content signing) is the track that will strengthen this boundary.
A follow-up is tracked to promote signing_keys from optional to required at the schema level for mutating-scope authorizations; the prose requirement above is the normative floor until that schema change lands.
countries
Use ISO 3166-1 alpha-2 country codes to constrain authorization geographically. This avoids ambiguous regional shorthands such as βLATAMβ or βEMEAβ and gives buyer agents a precise machine-readable scope.
effective_from / effective_until
Use these fields for time-bounded rights such as seasonal exclusives, windowed syndication, or temporary delegated sales agreements.
exclusive
Set exclusive: true when this agent is the publisherβs sole authorized path for the scoped slice of inventory. Leave it absent or set it to false when multiple agents are authorized concurrently.
Example: Scoped Delegation
adagents.json now provides a canonical publisher-level placement registry. Products still declare their own placements, but they SHOULD reuse the publisherβs registered placement_id values when the placement is part of that registry. Reusing a placement ID means the product is inheriting that placementβs identity; the product can narrow format_ids, preserve or narrow placement tags, or add operational detail, but it should not redefine the placement into something incompatible.
Domain Matching Rules
For website properties with domain identifiers, AdCP follows web conventions:Base Domain (example.com)
Matches domain plus standard web subdomains:
- β
example.com - β
www.example.com(standard web) - β
m.example.com(standard mobile) - β
subdomain.example.com(requires explicit authorization)
Specific Subdomain (subdomain.example.com)
Matches only that exact subdomain:
- β
subdomain.example.com - β All other domains/subdomains
Wildcard (*.example.com)
Matches ALL subdomains but NOT base:
- β Any subdomain
- β
example.com(base domain requires separate authorization)
Real-World Examples
Example 1: Meta Network (Tag-Based)
Large network using tags for grouping efficiency:meta_network) authorizes all properties without listing individual property IDs. As Meta adds properties, they just tag them - no need to update agent authorization.
Example 2: CNN (Channel Segmentation)
Different agents for different channels:Example 3: Publisher with Governance Agent References
Publishers can declare which governance agents have data about their properties usingproperty_features. This enables buyers to discover where to get sustainability, quality, and suitability data.
- Publishers declare relationships with governance agents upfront
- Buyers discover governance agents by reading adagents.json (no need to query every possible agent)
- The
publisher_idfield helps agents look up the publisherβs data efficiently - Feature IDs tell buyers what data types are available without querying
Governance Agent Discovery
Theproperty_features field solves a key discovery problem: how does a buyer know which governance agents have data about a given property?
When to Use property_features
| Scenario | Use property_features? |
|---|---|
| Publisher has carbon scoring from a sustainability vendor | β Yes |
| Publisher has MFA score measured by a quality vendor | β Yes |
| Publisher has content classification from a suitability vendor | β Yes |
| Publisher self-reports brand suitability | β 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 anext block. See get_adcp_capabilities for details.
Fetching and Validating
Using the AdAgents.json Builder
The easiest way to validate or create an adagents.json file is using the AdAgents.json Builder web tool. It provides:- Domain validation (fetches and checks
/.well-known/adagents.json) - Structure validation against the JSON schema
- Agent card endpoint verification (checks if agent URLs respond correctly)
- Guided file creation with proper formatting
Programmatic Validation
For programmatic validation, use the validation API:https://{domain}/.well-known/adagents.json, validates its structure, follows URL references if present, and optionally checks agent card endpoints.
Using AdCP Client Libraries
The AdCP client libraries provide built-in validation and authorization checking:AdagentsValidationError.
Best Practices
1. Use Appropriate Authorization Pattern
- Property IDs: Small, enumerable lists (< 20 properties)
- Property Tags: Large networks (100+ properties)
- Inline Properties: Simple cases without top-level properties
- Publisher Properties: Third-party agents representing multiple publishers
2. Cache Files Appropriately
- Cache for 24 hours minimum
- Use
last_updatedtimestamp to detect staleness - Handle 404 as βno fileβ (not an error - proceed without validation)
- Implement retry logic with exponential backoff for network errors
3. Validate Structure
- Validate against JSON schema before processing
- Check required fields exist (
authorized_agentsarray) - Verify authorization scope matches product claims
- Cross-reference with seller.json if available
4. Handle Missing Files Gracefully
- 404 status = No file present (not an authorization failure)
- Absence of file does not mean agent is unauthorized
- Use adagents.json as verification, not requirement
5. Handle Per-Property Validation Failures Gracefully
File-level failures (unparseable JSON, missing required top-levelauthorized_agents) MUST abort processing for that domain β the file is unusable. Per-property validation failures are a separate tier: a single property object in an otherwise-valid file may omit identifiers or another required field due to a publisher-side templating error or a partial write.
Per-property validation failures MUST NOT prevent processing of remaining properties in the same file. Treat a non-conforming property as absent from the array β never as a reason to abort the run:
- Skip the non-conforming property
- Log a warning including the source domain, the propertyβs index in the array, and the reason (e.g.,
missing required field: identifiers) - Continue processing all remaining properties in the file
properties array, inline properties inside authorized_agents[*].properties (the inline_properties authorization type), and properties fetched and resolved from remote domains during publisher_properties resolution.
Next Steps
After implementing adagents.json validation:- Integrate with Product Discovery: Use
get_productsto discover inventory - Validate at Purchase: Check authorization before calling
create_media_buy - Cache Property Mappings: Store resolved properties for efficient validation
- Monitor Authorization: Track validation success rates and unauthorized attempts
Learn More
- AdCP Basics: Authorized Properties - Accessible introduction to AdCP authorization
- get_adcp_capabilities - Discover agent capabilities and portfolio
- Property Schema - Property definition structure
- AdAgents.json Builder - Web-based validator and creator