Repository navigation
Description
Problem
sync_creatives assignment_operations has had assign, unassign and replace since 3.2, and 3.3 adds merge. Only merge has a capability flag (creative.supports_assignment_merge). Nothing says whether a seller accepts assignment_operations at all, or which operations. A buyer finds out by sending one and being refused with UNSUPPORTED_FEATURE.
That gap now matters more, because 3.3 points buyers at replace. #8404, which shipped as #8488, added creative.live_updates and CREATIVE_LIVE_UPDATE_UNSUPPORTED. The code's recovery and suggestion both say "sync the change as a new creative_id and swap it in on each live package with an assignment_operations replace". The RFC assumed replace "already exists in 3.2". It exists in the schema, but a seller may refuse it, and none can declare that it accepts it.
We hit this in production. Our own managed sales agent refused live creative changes with advice to send an assignment_operations replace, while it refused every assignment_operations request. A buyer that follows the advice is refused again. Over 10 and 11 November 2026, that pairing fed about 5,000 refused calls from three logical operations. We have fixed our agent's advice. The protocol still recommends a recovery that a conforming seller may not support.
Proposal
- Declare the operations. Add
creative.assignment_operationstoget_adcp_capabilities: an array of the operations the agent accepts insync_creativesassignment_operations(assign,unassign,replace,merge). When it is absent, the agent accepts none, and buyers MUST NOT sendassignment_operations.supports_assignment_mergestays as it is for compatibility, and SHOULD agree with whethermergeis listed. - Tie live updates to replace. A seller that declares
creative.live_updatesMUST also listreplace, becauseCREATIVE_LIVE_UPDATE_UNSUPPORTEDis only useful when the swap it recommends works. Alternatively, keep the two independent and make the code's recovery conditional: "swap it in withreplacewhen the seller lists it; otherwise the change needs a new package or buy". - A suggestion names only what the agent accepts. Add a general rule to
core/error.json: an error'ssuggestion, and the recovery text of acorrectableerror, SHOULD name only an operation or field the agent declares or the schema requires it to accept. That lets a buyer agent follow a correctable refusal without risking a second refusal.
Open questions
update_media_buy: should the same declaration covercreative_assignmentsreplace semantics onupdate_media_buy? Many sellers can attach creatives but cannot take one off a package.- Point 2: require
replacefrom sellers that declarecreative.live_updates, or make the code's recovery conditional on it?
Why now
Proposed for 3.3. 3.3 is in beta. creative.live_updates is marked experimental. Settling which recovery it points at, before sellers start declaring it, avoids a rule buyers can't rely on.
Related: #8404 and #8488 (live creative updates), #8746 (activate_at on assign and replace, which also assumes replace support), #8647 (capability for creatives sent without a package assignment).
Activity
fix(schema): address review of declared assignment operations
test(storyboards): pin compact_direct_buy_lifecycle at 9 steps on /sales