Skip to content

feat(aao): inverse-lookup endpoint — given agent_url, return authorizing publishers #4823

@bokelley

Description

@bokelley

Background

The AdCP Python SDK currently exposes two authorization-check primitives:

  • Push (publisher → agent): verify_agent_authorization(adagents_data, agent_url, ...) — given a parsed adagents.json, is this agent listed?
  • Pull, with caller-supplied list (agent → known publishers): fetch_agent_authorizations(agent_url, publisher_domains=[...]) (adcp-client-python adagents.py:1306) — caller passes a list of publisher_domains, SDK fetches each one and returns the subset that authorize the agent.

Neither answers the question every sales agent operator actually needs at sync time:

"What publishers have authorized my agent?"

Today operators have to either (a) maintain the publisher_domain list manually and call fetch_agent_authorizations against it, or (b) crawl the open web. Both are infeasible at scale.

Concrete trigger

Raptive (managed by CafeMedia, ~6,800 owned-and-operated domains) all delegate authorization to a single cafemedia.com adagents.json via either ads.txt MANAGERDOMAIN=cafemedia.com or adagents.json authoritative_location. The SDK's chain-following discovery handles per-domain verification correctly — but for a sales-agent operator onboarding Raptive, there's no way to discover the 6,800-domain set without either:

  1. Asking CafeMedia to hand over a spreadsheet (manual, stale)
  2. Building a per-domain bulk-import UI (papers over the missing primitive)
  3. Crawling DNS / ads.txt across the web

The AAO directory at agenticadvertising.org is already indexing publisher adagents.json files. It has the inverse map — it just doesn't expose it.

Proposal

Define an AAO directory inverse-lookup endpoint and add the corresponding SDK client function.

Endpoint shape (strawman)

GET https://{aao_directory}/v1/agents/{agent_url_encoded}/publishers
GET https://{aao_directory}/v1/agents/{agent_url_encoded}/publishers?since={iso8601}  # incremental sync

Response:

{
  "agent_url": "https://sales-agent.example.com",
  "directory_indexed_at": "2026-05-19T12:00:00Z",
  "publishers": [
    {
      "publisher_domain": "cooking.com",
      "discovery_method": "ads_txt_managerdomain",
      "manager_domain": "cafemedia.com",
      "authorized_properties_count": 12,
      "total_properties_count": 12,
      "status": "authorized",
      "last_verified_at": "2026-05-19T08:00:00Z"
    },
    {
      "publisher_domain": "wsj.com",
      "discovery_method": "direct",
      "authorized_properties_count": 47,
      "total_properties_count": 200,
      "status": "authorized",
      "last_verified_at": "2026-05-19T10:00:00Z"
    }
  ],
  "next_cursor": null
}

Mirrors the existing discovery_method / manager_domain fields on AdAgentsValidationResult so operators get the same provenance they already use for direct verification.

Status semantics

Reuse PublisherPartnerStatusKind-style discriminators that consumers like the Prebid Sales Agent already implement against:

  • authorized — typed binding resolves to ≥1 property
  • unbound — bare entry, top-level properties present (permissive resolution)
  • pending — agent listed but selector resolves to nothing, or not listed but file is fetchable

Excludes unreachable and no_properties — the directory only indexes publishers whose adagents.json was successfully fetched and references the agent.

Out of scope

  • Authentication on the directory (publishers are public; if rate-limiting is needed, key on agent_url with a public key proof — separate RFC)
  • Cross-directory federation
  • Push notification of new authorizations (poll-based v1 is fine)

Work items

  • Define endpoint shape in the AAO directory portion of the spec (path, params, response schema)
  • Define how discovery_method = ads_txt_managerdomain interacts with the salesagent#377-style warning that manager-domain authorizations must verify the source publisher is named in the manager's adagents.json
  • Companion SDK feature request in adcp-client-pythonfetch_agent_authorizations_from_directory(agent_url, directory_url, ...)

References

  • Salesagent issue blocking on this: prebid/salesagent#511 — being closed in favor of this upstream solve
  • Existing per-domain pull API: adcp/adagents.py:1306 fetch_agent_authorizations
  • Existing single-domain discover-and-validate with provenance: adcp/adagents.py:676 validate_adagents_domain

Metadata

Metadata

Assignees

No one assigned

    Labels

    brandIssue concerns the brand protocol domainclaude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.enhancementNew feature or requestneeds-wg-reviewBlocked on a working-group decision — surface in WG meeting agendasrfcProtocol change — auto-adds to roadmap board

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Shipped

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions