diff --git a/.changeset/format-assets-produced-by.md b/.changeset/format-assets-produced-by.md new file mode 100644 index 0000000000..896468d018 --- /dev/null +++ b/.changeset/format-assets-produced-by.md @@ -0,0 +1,9 @@ +--- +"adcontextprotocol": minor +--- + +Add `produced_by` enum to `format.assets[]` slots to distinguish buyer-provided inputs from creative-agent-generated outputs. + +`produced_by: 'buyer'` (default, backward-compatible) means the buyer provides the asset in `build_creative` input requests. `produced_by: 'build_creative'` means the creative agent generates the asset in the response; buyers MUST NOT include it in input requests, and implementations MUST reject requests that supply a value for such a slot. + +Added to both `baseIndividualAsset` and `baseGroupAsset` definitions. Resolves conformance ambiguity in adapters that currently declare output slots using `required: false` because no better discriminator existed. Closes #4021. diff --git a/static/schemas/source/core/format.json b/static/schemas/source/core/format.json index b5f43fae7a..08235ebbed 100644 --- a/static/schemas/source/core/format.json +++ b/static/schemas/source/core/format.json @@ -23,7 +23,14 @@ }, "required": { "type": "boolean", - "description": "Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory." + "default": false, + "description": "Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory. Only applies to buyer-provided slots (produced_by: 'buyer')." + }, + "produced_by": { + "type": "string", + "enum": ["buyer", "build_creative"], + "default": "buyer", + "description": "Who produces this asset. 'buyer' (default) means the buyer provides this asset in build_creative input requests. 'build_creative' means the creative agent generates this asset in the response; buyers MUST NOT include it in input requests, and implementations MUST reject build_creative requests that supply a value for this slot." }, "overlays": { "type": "array", @@ -31,7 +38,14 @@ "items": { "$ref": "/schemas/core/overlay.json" } } }, - "required": ["item_type", "asset_id", "asset_type", "required"] + "required": ["item_type", "asset_id", "asset_type", "required"], + "if": { + "properties": { "produced_by": { "const": "build_creative" } }, + "required": ["produced_by"] + }, + "then": { + "properties": { "required": { "const": false } } + } }, "baseGroupAsset": { "type": "object", @@ -46,16 +60,29 @@ }, "required": { "type": "boolean", - "description": "Whether this asset is required within each repetition of the group", + "description": "Whether this asset is required within each repetition of the group. Only applies to buyer-provided slots (produced_by: 'buyer').", "default": false }, + "produced_by": { + "type": "string", + "enum": ["buyer", "build_creative"], + "default": "buyer", + "description": "Who produces this asset. 'buyer' (default) means the buyer provides this asset in build_creative input requests. 'build_creative' means the creative agent generates this asset in the response; buyers MUST NOT include it in input requests, and implementations MUST reject build_creative requests that supply a value for this slot." + }, "overlays": { "type": "array", "description": "Publisher-controlled elements rendered on top of buyer content at this asset's position (e.g., carousel navigation arrows, slide indicators). Creative agents should avoid placing critical content within overlay bounds.", "items": { "$ref": "/schemas/core/overlay.json" } } }, - "required": ["asset_id", "asset_type", "required"] + "required": ["asset_id", "asset_type", "required"], + "if": { + "properties": { "produced_by": { "const": "build_creative" } }, + "required": ["produced_by"] + }, + "then": { + "properties": { "required": { "const": false } } + } } }, "properties": { @@ -195,7 +222,7 @@ }, "assets": { "type": "array", - "description": "Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory.", + "description": "Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory. Use 'produced_by' to distinguish slots the buyer provides in build_creative requests ('buyer', default) from slots the creative agent generates in the response ('build_creative').", "items": { "oneOf": [ {