You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Successor to #6656 (closed) — the one mechanism from that RFC's triage that all three expert reviews converged on as spec-ready ("clean accepted_verifiers precedent, non-breaking") and that the follow-up split (#6749, #6750) did not carry. Filed standalone. This RFC makes no authority claim: campaign governance ("spend approval") remains the buyer's split-authority infrastructure; the ask is operational — acceptance criteria over an integration counterparty the seller is otherwise assigned without any say.
Amended 2026-08-22 per triage and review comments: declaration rehomed to adcp.governance_enforcement (the governance block is gated on governance protocol support); acceptance restructured as a typed any_of matcher union; the verification matcher fully specified (with URL-only V1 named as an acceptable resolution); account scoping resolved as advisory-capabilities / authoritative-sync_governance; rejected-binding hygiene and non-discrimination MUSTs added; the delegated-intervention recovery case added to Motivation.
Motivation
Grounding: citations from the repo at 17cb0f59776a0ecc68dd912dc43b640442002d74 (main, 2026-08-21); re-verify at implementation time.
The binding is buyer-initiated; the seller's role is to persist, call, and comply.docs/accounts/tasks/sync_governance.mdx:
"Sync the governance agent endpoint for specific accounts. The seller persists the agent and calls it via check_governance during media buy lifecycle events."
The task's Authorization section verifies the buyer's authority over the account; no surface exists for the seller to accept or decline the binding itself.
The seller is a forced integration counterparty, and sends it sensitive data. Under docs/governance/campaign/specification.mdx § Seller enforcement, a seller advertising governance enforcement MUST verify tokens against the bound agent and, for online_execution_check tasks, MUST call check_governance with its computed planned_delivery — its delivery parameters for the buy — and MUST NOT proceed on denial. Availability, latency, and data handling of the bound agent sit directly on the seller's execution path.
The bound agent controls recovery, not just checks.resumes_execution is a governed trigger (static/schemas/source/media-buy/control-media-buy-request.json, x-governed-commitment), and the unreachable-gate default is halt — docs/governance/campaign/specification.mdx:
"If the governance agent is unreachable (timeout, network error), the seller MUST NOT proceed with the media buy. … reject the media buy with a GOVERNANCE_UNAVAILABLE error if the agent remains unreachable."
The safe-by-design consequence: pausing is always possible, but un-pausing a media buy requires the bound agent to be reachable and responsive. An unavailable or slow agent leaves paused inventory stranded on the seller's books — in delegated or emergency-intervention scenarios, at exactly the worst moment — and the seller had no say in the counterparty whose availability determines when its inventory can resume delivering.
The spec already treats agent data-handling as a trust decision — for the buyer only. The same specification section:
"Operators who treat shopping intent as commercially sensitive SHOULD choose governance agents whose data-handling posture they trust."
The seller sends planned_delivery to the same agent and gets no equivalent choice. The trust advice exists; only one of the two parties transmitting sensitive data to the agent can act on it.
The precedent is exact. Creative governance already solves this shape: static/schemas/source/core/creative-policy.json (accepted_verifiers — "The seller is the verifier-of-record: it is the seller, not the buyer, that decides which agent it will call"), with the typed rejection PROVENANCE_VERIFIER_NOT_ACCEPTED in static/schemas/source/enums/error-code.json, and URL matching governed by docs/reference/url-canonicalization.mdx. There, the seller calls an agent chosen by the ecosystem and declares which it accepts; here, the seller calls an agent chosen by the buyer and declares nothing.
Problem
A buyer binds a governance agent to the account via sync_governance. The agent may be operated by anyone — including the buyer itself or a vendor whose data handling, availability record, or jurisdiction the seller cannot accept (e.g. for where its planned_delivery data lands, or whose uptime its paused inventory depends on).
The seller's choices are: integrate and transmit regardless, or refuse the account commercially — an off-protocol, all-or-nothing lever. There is no typed, auditable way to say "we accept AAO-verified operators" or "these endpoints".
Every future binding change repeats the same silent imposition: sync_governance re-syncs are processed, not negotiated, and the seller learns operational problems (an unreachable or slow agent stalling its execution checks — or its resumes) only in production.
Scope
One mechanism — declaration plus binding-time enforcement. No change to check_governance, token verification, threading, or any check-time wire shape.
Acceptance declaration — on adcp.governance_enforcement
The seller declares acceptance criteria inside the existing cross-roleadcp.governance_enforcement capability (static/schemas/source/protocol/get-adcp-capabilities-response.json — "Cross-role declaration that this agent enforces buyer-provided governance authorization when performing consequential tasks"). The acceptance declaration is a parameter of that enforcement claim — I enforce governance, against agents I accept — and, being cross-role, remains available to any seller role if governed commitments expand beyond media buying. It is deliberately not placed in the governance capabilities block, which is gated on governance in supported_protocols and therefore unavailable to ordinary sellers — the RFC's entire audience.
Acceptance is a typed any_of union of matcher objects — a binding is acceptable when any matcher accepts it:
The union is permissive by construction: a binding satisfying any one matcher MUST be accepted. NOTE: adding matchers widens acceptance — an agent_url entry plus a verification entry accepts more agents than either alone. Implementers wanting conjunctive restriction express it inside a single matcher, not across entries. The discriminated kind union makes this composition visible to validators and SDKs and is the extension point for future matcher kinds.
agent_url matcher (V1 floor): exact-match allowlisting under the canonicalization rules of docs/reference/url-canonicalization.mdx — the same rules that already govern accepted_verifiers comparisons.
verification matcher: deterministic contract — registry (authoritative lookup endpoint), role (required agent role in the registry), adcp_version (applicable version), verification_modes (accepted modes), max_age_seconds (freshness bound on cached verification state). If verification cannot be resolved (registry unreachable, stale beyond max_age_seconds with no refresh), the binding attempt fails with GOVERNANCE_UNAVAILABLE-class retryable semantics — the same principle the spec already applies to an unreachable agent at check time — and MUST NOT be reported as a definitive GOVERNANCE_AGENT_NOT_ACCEPTED. Acceptable alternative resolution: land V1 with the agent_url matcher only and sever the verification matcher to a follow-up RFC once registry governance is settled; either outcome satisfies this RFC.
Non-discrimination: declared acceptance criteria MUST reflect objective, non-discriminatory eligibility standards (operator verification status, data-handling certification, availability commitments) — not commercial leverage over particular counterparties.
Enforcement at sync_governance
A sync_governance call naming an agent outside the seller's acceptance fails with the typed error GOVERNANCE_AGENT_NOT_ACCEPTED (mirroring PROVENANCE_VERIFIER_NOT_ACCEPTED), carrying the applicable acceptance criteria in error.details so the buyer can select a compliant agent without out-of-band discovery.
Scoping — advisory declaration, authoritative response.get_adcp_capabilities has no account input, so the capabilities declaration is a seller-wide advisory default for discovery. The sync_governance response is authoritative per account: a seller MAY reject a binding on account-specific grounds (e.g. a regulated-category account requiring stricter criteria), carrying the account-applicable criteria in the error details. This mirrors the discovery-advisory / response-authoritative pattern RFC: structured seller acceptance-policy discovery backed by the policy registry #6749 establishes for acceptance policies.
Rejected-binding hygiene. A rejected binding MUST NOT be persisted, MUST NOT be contacted, and its credentials MUST NOT be echoed in any response or log surface.
Stability. Absent declaration = accept any (today's behavior, unchanged). An already-synced binding is unaffected by a later declaration change until the next sync_governance — no retroactive invalidation, the same stability rule as other capability declarations.
No seller authority over spend approval: the buyer still chooses the agent; the seller's declaration only bounds which choices it can integrate with — exactly as accepted_verifiers bounds creative verifiers.
No new obligations for sellers that declare nothing.
Alternatives considered
Do nothing. The seller's only lever over an imposed integration counterparty remains refusing the account commercially; data-handling trust stays a one-sided SHOULD; recovery availability stays an unpriced dependency.
Parallel agents[] / criteria[] fields with prose-defined OR(this RFC's originally filed shape). Rejected per review: the permissive composition is invisible in the schema, and implementers expecting additive restriction would misconfigure silently. The any_of matcher union expresses the same semantics structurally.
Criteria-only (no URL allowlist). More neutral — avoids sellers hard-pinning vendors — but blocks the legitimate "we have an integration/DPA with these two operators" case, and a bare criteria string is not deterministic without the full verification contract. Both matcher kinds are specified instead.
Handle out-of-band (commercial contracts). Where it lives today; leaves no typed error, nothing in capabilities for buyers to discover before attempting a binding, and no interoperable vocabulary across sellers.
Full mutual agreement on the binding. The heavyweight form; deliberately out of scope per the spend-approval framing — the buyer's approval infrastructure is the buyer's to choose within the seller's declared acceptance bounds.
Compatibility impact
Non-breaking; changeset class MINOR. New optional object on the existing cross-role adcp.governance_enforcement capability; one additive error-code enum entry (GOVERNANCE_AGENT_NOT_ACCEPTED — visible to strict validators); the unresolvable-verification path reuses GOVERNANCE_UNAVAILABLE-class semantics rather than adding a code (final code choice per maintainers). sync_governance behavior changes only for sellers that declare acceptance; defaults are unchanged for everyone else.
Files affected (as of 17cb0f5 — re-verify at implementation)
static/schemas/source/protocol/get-adcp-capabilities-response.json — accepted_governance_agents on adcp.governance_enforcement
static/schemas/source/account/sync-governance-response.json — typed rejection path with criteria in details
Motivation
Grounding: citations from the repo at
17cb0f59776a0ecc68dd912dc43b640442002d74(main, 2026-08-21); re-verify at implementation time.The binding is buyer-initiated; the seller's role is to persist, call, and comply.
docs/accounts/tasks/sync_governance.mdx:The task's Authorization section verifies the buyer's authority over the account; no surface exists for the seller to accept or decline the binding itself.
The seller is a forced integration counterparty, and sends it sensitive data. Under
docs/governance/campaign/specification.mdx§ Seller enforcement, a seller advertising governance enforcement MUST verify tokens against the bound agent and, foronline_execution_checktasks, MUST callcheck_governancewith its computedplanned_delivery— its delivery parameters for the buy — and MUST NOT proceed on denial. Availability, latency, and data handling of the bound agent sit directly on the seller's execution path.The bound agent controls recovery, not just checks.
resumes_executionis a governed trigger (static/schemas/source/media-buy/control-media-buy-request.json,x-governed-commitment), and the unreachable-gate default is halt —docs/governance/campaign/specification.mdx:The safe-by-design consequence: pausing is always possible, but un-pausing a media buy requires the bound agent to be reachable and responsive. An unavailable or slow agent leaves paused inventory stranded on the seller's books — in delegated or emergency-intervention scenarios, at exactly the worst moment — and the seller had no say in the counterparty whose availability determines when its inventory can resume delivering.
The spec already treats agent data-handling as a trust decision — for the buyer only. The same specification section:
The seller sends
planned_deliveryto the same agent and gets no equivalent choice. The trust advice exists; only one of the two parties transmitting sensitive data to the agent can act on it.The precedent is exact. Creative governance already solves this shape:
static/schemas/source/core/creative-policy.json(accepted_verifiers— "The seller is the verifier-of-record: it is the seller, not the buyer, that decides which agent it will call"), with the typed rejectionPROVENANCE_VERIFIER_NOT_ACCEPTEDinstatic/schemas/source/enums/error-code.json, and URL matching governed bydocs/reference/url-canonicalization.mdx. There, the seller calls an agent chosen by the ecosystem and declares which it accepts; here, the seller calls an agent chosen by the buyer and declares nothing.Problem
sync_governance. The agent may be operated by anyone — including the buyer itself or a vendor whose data handling, availability record, or jurisdiction the seller cannot accept (e.g. for where itsplanned_deliverydata lands, or whose uptime its paused inventory depends on).sync_governancere-syncs are processed, not negotiated, and the seller learns operational problems (an unreachable or slow agent stalling its execution checks — or its resumes) only in production.Scope
One mechanism — declaration plus binding-time enforcement. No change to
check_governance, token verification, threading, or any check-time wire shape.Acceptance declaration — on
adcp.governance_enforcementThe seller declares acceptance criteria inside the existing cross-role
adcp.governance_enforcementcapability (static/schemas/source/protocol/get-adcp-capabilities-response.json— "Cross-role declaration that this agent enforces buyer-provided governance authorization when performing consequential tasks"). The acceptance declaration is a parameter of that enforcement claim — I enforce governance, against agents I accept — and, being cross-role, remains available to any seller role if governed commitments expand beyond media buying. It is deliberately not placed in thegovernancecapabilities block, which is gated ongovernanceinsupported_protocolsand therefore unavailable to ordinary sellers — the RFC's entire audience.Acceptance is a typed
any_ofunion of matcher objects — a binding is acceptable when any matcher accepts it:{ "adcp": { "governance_enforcement": { "accepted_governance_agents": { "any_of": [ { "kind": "agent_url", "agent_url": "https://governance.neutral-operator.example" }, { "kind": "verification", "registry": "https://registry.agenticadvertising.org", "role": "governance", "adcp_version": "3.2", "verification_modes": ["spec"], "max_age_seconds": 86400 } ] } } } }Normative semantics:
agent_urlentry plus averificationentry accepts more agents than either alone. Implementers wanting conjunctive restriction express it inside a single matcher, not across entries. The discriminatedkindunion makes this composition visible to validators and SDKs and is the extension point for future matcher kinds.agent_urlmatcher (V1 floor): exact-match allowlisting under the canonicalization rules ofdocs/reference/url-canonicalization.mdx— the same rules that already governaccepted_verifierscomparisons.verificationmatcher: deterministic contract —registry(authoritative lookup endpoint),role(required agent role in the registry),adcp_version(applicable version),verification_modes(accepted modes),max_age_seconds(freshness bound on cached verification state). If verification cannot be resolved (registry unreachable, stale beyondmax_age_secondswith no refresh), the binding attempt fails withGOVERNANCE_UNAVAILABLE-class retryable semantics — the same principle the spec already applies to an unreachable agent at check time — and MUST NOT be reported as a definitiveGOVERNANCE_AGENT_NOT_ACCEPTED. Acceptable alternative resolution: land V1 with theagent_urlmatcher only and sever theverificationmatcher to a follow-up RFC once registry governance is settled; either outcome satisfies this RFC.Enforcement at
sync_governanceA
sync_governancecall naming an agent outside the seller's acceptance fails with the typed errorGOVERNANCE_AGENT_NOT_ACCEPTED(mirroringPROVENANCE_VERIFIER_NOT_ACCEPTED), carrying the applicable acceptance criteria inerror.detailsso the buyer can select a compliant agent without out-of-band discovery.get_adcp_capabilitieshas no account input, so the capabilities declaration is a seller-wide advisory default for discovery. Thesync_governanceresponse is authoritative per account: a seller MAY reject a binding on account-specific grounds (e.g. a regulated-category account requiring stricter criteria), carrying the account-applicable criteria in the error details. This mirrors the discovery-advisory / response-authoritative pattern RFC: structured seller acceptance-policy discovery backed by the policy registry #6749 establishes for acceptance policies.sync_governance— no retroactive invalidation, the same stability rule as other capability declarations.Non-goals
accepted_verifiersbounds creative verifiers.Alternatives considered
agents[]/criteria[]fields with prose-defined OR (this RFC's originally filed shape). Rejected per review: the permissive composition is invisible in the schema, and implementers expecting additive restriction would misconfigure silently. Theany_ofmatcher union expresses the same semantics structurally.Compatibility impact
Non-breaking; changeset class MINOR. New optional object on the existing cross-role
adcp.governance_enforcementcapability; one additive error-code enum entry (GOVERNANCE_AGENT_NOT_ACCEPTED— visible to strict validators); the unresolvable-verification path reusesGOVERNANCE_UNAVAILABLE-class semantics rather than adding a code (final code choice per maintainers).sync_governancebehavior changes only for sellers that declare acceptance; defaults are unchanged for everyone else.Files affected (as of
17cb0f5— re-verify at implementation)static/schemas/source/protocol/get-adcp-capabilities-response.json—accepted_governance_agentsonadcp.governance_enforcementstatic/schemas/source/account/sync-governance-response.json— typed rejection path with criteria in detailsstatic/schemas/source/enums/error-code.json—GOVERNANCE_AGENT_NOT_ACCEPTEDdocs/reference/url-canonicalization.mdx— new row foraccepted_governance_agents.any_of[].agent_urlvs bound agent URLdocs/accounts/tasks/sync_governance.mdx— acceptance semantics, hygiene rules, advisory/authoritative scopingdocs/governance/campaign/specification.mdx/safety-model.mdx— one-paragraph updates where the binding is describedReviewer checklist
Related
static/schemas/source/core/creative-policy.jsonaccepted_verifiers/PROVENANCE_VERIFIER_NOT_ACCEPTED— the exact precedent;docs/reference/url-canonicalization.mdx— the matching rules reused here.