build_creative accepts inputs the buyer attaches to a build: a selected build capability, render configuration, and — over time — pointers to context the buyer wants the production to honor. This page defines the contract those inputs share so each new pointer inherits it instead of relitigating governance. The one distinction that matters is whether an input is an enforced capability input the agent validates and gates on, or an advisory context pointer that informs production but does not hard-block it at the AdCP layer.
The boundary is deliberate and matches the rest of the protocol: capabilities are declared, not gated, and the default is exposure, not coercion. An input gates only when it is a typed contract the agent owns end to end — a render configuration that drives a paid render. Everything else steers.
Two classes of buyer-attached input
| Enforced capability input | Advisory context pointer | |
|---|---|---|
| Examples | transformer_id, config | signal_ref (#5240), evaluator (#5241), rights / provenance pointers |
| Status | Normative now | Rights/provenance advisory now; signal/evaluator are RFCs |
| What it does | Selects and parameterizes the build; the agent MUST validate it | Informs or steers production toward buyer context |
| On bad/unknown input | Reject with a field-attributed error | Does not hard-block at the AdCP layer |
| Where enforcement lives | The creative agent, at build time | Elsewhere — the credential layer, trafficking-compatibility checks, or the seller’s own verification |
Enforced capability input — transformer_id + config
A transformer_id selects an account-scoped transformer (discovered via list_transformers) to perform the build. One transformer per call; target_format_id / target_format_ids MUST be a subset of the transformer’s output_format_ids. Render configuration goes in config.
config is a typed bag keyed by each param’s field from the transformer’s params[]. It gates, and it gates correctly: per build_creative, the creative agent MUST reject unknown keys and out-of-range values with field-attributed errors rather than silently ignoring them — config drives a paid render. Vendor-specific knobs that are not declared params go in ext, not here. The schema leaves the object open because legal keys are dynamic per transformer, so strict validation is a normative agent obligation.
This is the only buyer-attached input that hard-blocks a build at the AdCP layer, and it is the right one to: config is a contract the creative agent owns, priced per account, and a mis-keyed value would charge for the wrong render. The agent declares creative.supports_transformers to expose this surface, and transformer and build_variant are registered x-entity types.
Advisory context pointers — signal_ref, evaluator, rights / provenance
Advisory pointers carry buyer context the production SHOULD honor — an audience signal, an evaluator’s preference, a rights or provenance reference. They inform or steer; they MUST NOT hard-block production at the AdCP layer. Where enforcement exists for the thing a pointer names, it lives in the layer that owns it, not in build_creative:
- Rights / provenance — enforced by the credential layer (
generation_credentialsat synthesis,rights_constraint.verification_urlfor live revocation), not by the buyer’s pointer. - Signals (#5240) — where enforcement exists, it lives in trafficking-compatibility checks.
- Evaluators (#5241) — explore-and-rank guidance, surfaced as
recommended/rankon leaves; not a gate.
sync_creatives status is “a UI hint and polling-scheduling signal — not a spend-authorization gate.” keep_mode is the same shape on the request side — advisory only, it does not change what is returned or billed.
Shared shape
Every buyer-attached input — enforced or advisory — inherits the same three-part shape. This is normative for transformers today and is the pattern future pointers reuse:-
Account-scoped discovery. Options are discovered, not guessed.
list_transformersis account-scoped, brief-filterable, and paginated, with anexpand_paramsmode that enumerates an account’s configured option values (for example, the voices provisioned for that account). There is no separate options endpoint — enumeration is a mode of the one discovery task. A future pointer’s catalog is discovered the same way. -
Per-account pricing. Capabilities carry
pricing_options(reusingvendor-pricing-option.json) resolved per account, echoed per leaf in the result, and reconciled viareport_usage. An output that matches no pricing option and has no unscoped default surfacesUNPRICEABLE_OUTPUT. -
Result envelope with a stable leaf anchor.
build_creativereturns each produced leaf with its ownbuild_variant_id— a namespace distinct from apreview_id(preview), a servedvariant_id(delivery), and the call-levelbuild_creative_id. Lineage, refinement parentage, and the build→delivery learning join all key on this leaf id, and each leaf carries its own pricing receipt. This is the anchor an evaluator’s scores or a signal’s targeting attach to when those pointers land. The response-shape contract and per-leaf field mechanics live in thebuild_creativetask reference.
Rights are advisory at the pointer; enforcement is the credential
A rights or provenance reference attached to a build is an advisory / audit pointer. It does not authorize the build at the AdCP layer, and the creative agent is not obligated to validate a rights token against it. A transformer’svoice_synthesis_ref[].rights_id says this directly:
This is provenance metadata only, not a build_creative rights token.Enforcement for rights already ships, and it lives in the credential layer — not at the buyer’s pointer:
generation_credentialsare provider-enforced at synthesis. The rights agent coordinates with the provider to issue a scoped credential; the provider validatesrights_keyat generation time and is the gatekeeper. The credential is required on the acquired branch ofacquire_rights.rights_constraint.verification_urlis the live-revocation channel: downstream participants (SSPs, verification vendors) hit it to confirm a grant is active before serving — HTTP 200 if active, 404 if revoked. (approval_statusis a manifest-time snapshot, not a live value.)creative-manifestrights[]travels with the creative as informational metadata: “For v1, rights constraints are informational metadata — the buyer/orchestrator manages creative lifecycle against these terms.”
verify_agent.agent_url MUST be a canonicalized match of one of the seller’s published creative_policy.accepted_verifiers[]; off-list URLs are rejected with PROVENANCE_VERIFIER_NOT_ACCEPTED. That rejection is the seller enforcing its own allowlist before any outbound call — not the buyer’s pointer gating the build. The buyer’s attached results are supplementary; a seller that requires verification runs its own detection rather than trusting them.
Settled position vs. #5261. A proposal to treat buyer-attached
rights_tokens[] as a hard creative-agent gate is resolved against this page. Hard-gating at the buyer pointer re-invents the generation_credentials enforcement that already ships at the synthesis layer plus verification_url live revocation at the serve layer. The pointer stays advisory; enforcement stays in the credential layer. The one real gap is structural, not a missing gate: voice_synthesis carries provider / voice_id / settings but no rights_id back-reference today. Adding that back-reference is a forward item — it would extend the advisory/audit trail, not introduce a build-time gate.Forward pointers (not yet normative)
The following advisory pointers belong to this contract’s second class but are not yet in the schema. They are referenced here by governance class only — no fields are defined.- Signal-driven creative fan-out (#5240, RFC). A buyer fans out over
signal_conditions: SignalTargeting[]onbuild_creative, producing one creative group per condition, each tagged with thesignal_conditionit is FOR. Advisory at the AdCP layer; trafficking-compatibility (a sun creative MUST NOT serve into a rain-targeted package) is enforced sales-side viaSIGNAL_TARGETING_INCOMPATIBLE. #5240 reuses the existing signals-domainSignalTargeting/signal-ref.json— no new creative-contextsignal_refis minted — so the creative’s condition and the sales-side package targeting share onesignal_refidentity.
evaluator/evaluator_id(#5241, RFC). A creative evaluator/oracle the buyer attaches so the agent can explore and rank alternatives (thebest_of_ndimension is where it would plug in, surfacingrecommended/rankon leaves). Advisory — a preference signal, not a gate. No evaluator schema exists yet.
config.