Skip to content

feat: spec-conformant way to authorize an agent for all listed properties (+ builder/validator support) #4478

Description

@bokelley

Problem

Publishers in production routinely ship adagents.json files where authorized_agents[] entries carry only {url, authorized_for} — no authorization_type, no selector. Examples from the wild include wonderstruck.org and Raptive's published files. These files don't satisfy any branch of the schema's oneOf (every variant requires authorization_type + a matching selector), but the publisher's intent is unambiguous: "this agent is authorized for everything I list."

Today the AdCP ecosystem has three answers to that intent and none are good:

  1. Strict per the schema (Python SDK's get_properties_by_agent): resolves to []. Products can't bind to the publisher even though the file looks "valid" to humans.
  2. Permissive by accident (JS SDK, today): attributes all top-level properties[] to every listed agent regardless of authorization_type. Works operationally, drifts from the schema, indistinguishable from a buggy implementation.
  3. Local shim (salesagent): we just added explicit permissive fallback (see salesagent#377). It works but every consumer will reimplement this differently — and the spec hasn't acknowledged what they're working around.

The root cause is that the spec has no first-class way to say "authorize agent X for everything I list" without enumerating it via property_ids / property_tags / inline properties. Publishers reach for the shortest expression of intent, which produces bare entries.

Proposed fix

Add a spec-conformant authorization variant whose meaning is "agent is authorized for every property in the file's top-level properties[] array." Two reasonable shapes:

Option A — new authorization_type value:

{
  "url": "https://wonderstruck.sales-agent.scope3.com",
  "authorized_for": "Display banners",
  "authorization_type": "all_top_level_properties"
}

Schema adds a 7th oneOf variant: {required: [url, authorized_for, authorization_type]} where authorization_type is constrained to the literal "all_top_level_properties". No selector field needed — the top-level properties[] is the implicit selector.

Option B — explicit all_properties: true selector:

{
  "url": "https://wonderstruck.sales-agent.scope3.com",
  "authorized_for": "Display banners",
  "authorization_type": "all_properties",
  "all_properties": true
}

Symmetric with the other variants (each variant has a selector field that names the binding). Arguably uglier but consistent.

I think A is cleaner — there's no useful payload beyond the discriminator itself, so a paired selector field is dead weight. Either way, the value of having this is that bare-entry behavior gets a name and a stable spec citation, so SDKs can stop divining intent.

Companion: builder UX

The AAO builder at agenticadvertising.org/publisher should default to producing typed entries. Concretely:

  • When a publisher adds an agent to their adagents.json, the wizard should prompt: "Which properties is this agent authorized for? (a) All of them, (b) Specific IDs, (c) By tag, (d) Inline list."
  • "(a) All of them" produces the new spec-conformant shape from this proposal.
  • Bare-entry output should not be possible from the builder.

Companion: validator

Companion to adcp#4476 (validator currently reports schema-invalid files as valid: true). Once this proposal lands:

  • Bare entries become a soft warning: "This entry uses the legacy bare shape. Spec-conformant equivalent: authorization_type: 'all_top_level_properties'. Still resolves the same way under permissive SDK modes — see adcp-client-python#711."
  • Bare entries are no longer flagged as invalid (since the new variant gives them a clean migration target), but they're not silently passed either.

The combination is: publishers who want "authorize for everything" have a typed expression they can use, the validator nudges legacy files toward it, and SDKs can stop carrying permissive fallbacks indefinitely (we'd close adcp-client-python #711 once both SDKs support the new variant and the long tail of legacy files has migrated).

Cross-references

  • adcp-client-python #711 — Python SDK permissive resolver (operational stopgap; would be deprecated once this lands)
  • adcp-client #1721 — JS SDK per-agent resolution gap (related: needs both strict and permissive modes until new variant ships)
  • adcp#4476 — strict validator behavior
  • salesagent#377 — operator-facing UI model that surfaced the gap

Willing to PR

Happy to PR the schema change and a docs patch if the team agrees on the direction (and lands on A vs B).

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions