@adcp/client 4.20.0 → 4.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/AGENTS.md +278 -0
  2. package/README.md +96 -61
  3. package/bin/adcp.js +342 -4
  4. package/dist/lib/agents/index.generated.d.ts +9 -1
  5. package/dist/lib/agents/index.generated.d.ts.map +1 -1
  6. package/dist/lib/agents/index.generated.js +12 -0
  7. package/dist/lib/agents/index.generated.js.map +1 -1
  8. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  9. package/dist/lib/core/SingleAgentClient.d.ts +2 -1
  10. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  11. package/dist/lib/core/SingleAgentClient.js +10 -1
  12. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  13. package/dist/lib/discovery/property-crawler.d.ts +4 -0
  14. package/dist/lib/discovery/property-crawler.d.ts.map +1 -1
  15. package/dist/lib/discovery/property-crawler.js +10 -2
  16. package/dist/lib/discovery/property-crawler.js.map +1 -1
  17. package/dist/lib/index.d.ts +9 -9
  18. package/dist/lib/index.d.ts.map +1 -1
  19. package/dist/lib/index.js +13 -5
  20. package/dist/lib/index.js.map +1 -1
  21. package/dist/lib/protocols/index.d.ts.map +1 -1
  22. package/dist/lib/protocols/index.js +8 -6
  23. package/dist/lib/protocols/index.js.map +1 -1
  24. package/dist/lib/protocols/mcp.d.ts.map +1 -1
  25. package/dist/lib/protocols/mcp.js +24 -11
  26. package/dist/lib/protocols/mcp.js.map +1 -1
  27. package/dist/lib/registry/cursor-store.d.ts +19 -0
  28. package/dist/lib/registry/cursor-store.d.ts.map +1 -0
  29. package/dist/lib/registry/cursor-store.js +44 -0
  30. package/dist/lib/registry/cursor-store.js.map +1 -0
  31. package/dist/lib/registry/index.d.ts +21 -3
  32. package/dist/lib/registry/index.d.ts.map +1 -1
  33. package/dist/lib/registry/index.js +94 -1
  34. package/dist/lib/registry/index.js.map +1 -1
  35. package/dist/lib/registry/property-registry.d.ts +57 -0
  36. package/dist/lib/registry/property-registry.d.ts.map +1 -0
  37. package/dist/lib/registry/property-registry.js +92 -0
  38. package/dist/lib/registry/property-registry.js.map +1 -0
  39. package/dist/lib/registry/sync.d.ts +4 -0
  40. package/dist/lib/registry/sync.d.ts.map +1 -1
  41. package/dist/lib/registry/sync.js +14 -0
  42. package/dist/lib/registry/sync.js.map +1 -1
  43. package/dist/lib/registry/types.d.ts +35 -2
  44. package/dist/lib/registry/types.d.ts.map +1 -1
  45. package/dist/lib/registry/types.generated.d.ts +349 -321
  46. package/dist/lib/registry/types.generated.d.ts.map +1 -1
  47. package/dist/lib/registry/types.generated.js +1 -1
  48. package/dist/lib/server/index.d.ts +2 -0
  49. package/dist/lib/server/index.d.ts.map +1 -1
  50. package/dist/lib/server/index.js +3 -1
  51. package/dist/lib/server/index.js.map +1 -1
  52. package/dist/lib/server/serve.d.ts +45 -0
  53. package/dist/lib/server/serve.d.ts.map +1 -0
  54. package/dist/lib/server/serve.js +86 -0
  55. package/dist/lib/server/serve.js.map +1 -0
  56. package/dist/lib/testing/agent-tester.d.ts +1 -1
  57. package/dist/lib/testing/agent-tester.d.ts.map +1 -1
  58. package/dist/lib/testing/agent-tester.js +10 -1
  59. package/dist/lib/testing/agent-tester.js.map +1 -1
  60. package/dist/lib/testing/client.d.ts.map +1 -1
  61. package/dist/lib/testing/client.js +3 -0
  62. package/dist/lib/testing/client.js.map +1 -1
  63. package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
  64. package/dist/lib/testing/compliance/comply.js +158 -203
  65. package/dist/lib/testing/compliance/comply.js.map +1 -1
  66. package/dist/lib/testing/compliance/storyboard-tracks.d.ts +24 -0
  67. package/dist/lib/testing/compliance/storyboard-tracks.d.ts.map +1 -0
  68. package/dist/lib/testing/compliance/storyboard-tracks.js +157 -0
  69. package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -0
  70. package/dist/lib/testing/compliance/types.d.ts +1 -1
  71. package/dist/lib/testing/compliance/types.d.ts.map +1 -1
  72. package/dist/lib/testing/index.d.ts +2 -1
  73. package/dist/lib/testing/index.d.ts.map +1 -1
  74. package/dist/lib/testing/index.js +26 -1
  75. package/dist/lib/testing/index.js.map +1 -1
  76. package/dist/lib/testing/orchestrator.d.ts +8 -0
  77. package/dist/lib/testing/orchestrator.d.ts.map +1 -1
  78. package/dist/lib/testing/orchestrator.js +11 -0
  79. package/dist/lib/testing/orchestrator.js.map +1 -1
  80. package/dist/lib/testing/scenarios/brand-rights.d.ts +23 -0
  81. package/dist/lib/testing/scenarios/brand-rights.d.ts.map +1 -0
  82. package/dist/lib/testing/scenarios/brand-rights.js +144 -0
  83. package/dist/lib/testing/scenarios/brand-rights.js.map +1 -0
  84. package/dist/lib/testing/scenarios/capabilities.d.ts.map +1 -1
  85. package/dist/lib/testing/scenarios/capabilities.js +11 -2
  86. package/dist/lib/testing/scenarios/capabilities.js.map +1 -1
  87. package/dist/lib/testing/scenarios/governance.d.ts.map +1 -1
  88. package/dist/lib/testing/scenarios/governance.js +5 -0
  89. package/dist/lib/testing/scenarios/governance.js.map +1 -1
  90. package/dist/lib/testing/scenarios/index.d.ts +2 -0
  91. package/dist/lib/testing/scenarios/index.d.ts.map +1 -1
  92. package/dist/lib/testing/scenarios/index.js +10 -2
  93. package/dist/lib/testing/scenarios/index.js.map +1 -1
  94. package/dist/lib/testing/scenarios/media-buy.d.ts.map +1 -1
  95. package/dist/lib/testing/scenarios/media-buy.js +22 -3
  96. package/dist/lib/testing/scenarios/media-buy.js.map +1 -1
  97. package/dist/lib/testing/scenarios/trusted-match.d.ts +22 -0
  98. package/dist/lib/testing/scenarios/trusted-match.d.ts.map +1 -0
  99. package/dist/lib/testing/scenarios/trusted-match.js +128 -0
  100. package/dist/lib/testing/scenarios/trusted-match.js.map +1 -0
  101. package/dist/lib/testing/storyboard/context.d.ts +34 -0
  102. package/dist/lib/testing/storyboard/context.d.ts.map +1 -0
  103. package/dist/lib/testing/storyboard/context.js +257 -0
  104. package/dist/lib/testing/storyboard/context.js.map +1 -0
  105. package/dist/lib/testing/storyboard/index.d.ts +15 -0
  106. package/dist/lib/testing/storyboard/index.d.ts.map +1 -0
  107. package/dist/lib/testing/storyboard/index.js +48 -0
  108. package/dist/lib/testing/storyboard/index.js.map +1 -0
  109. package/dist/lib/testing/storyboard/loader.d.ts +53 -0
  110. package/dist/lib/testing/storyboard/loader.d.ts.map +1 -0
  111. package/dist/lib/testing/storyboard/loader.js +114 -0
  112. package/dist/lib/testing/storyboard/loader.js.map +1 -0
  113. package/dist/lib/testing/storyboard/path.d.ts +29 -0
  114. package/dist/lib/testing/storyboard/path.d.ts.map +1 -0
  115. package/dist/lib/testing/storyboard/path.js +121 -0
  116. package/dist/lib/testing/storyboard/path.js.map +1 -0
  117. package/dist/lib/testing/storyboard/request-builder.d.ts +28 -0
  118. package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -0
  119. package/dist/lib/testing/storyboard/request-builder.js +410 -0
  120. package/dist/lib/testing/storyboard/request-builder.js.map +1 -0
  121. package/dist/lib/testing/storyboard/runner.d.ts +24 -0
  122. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -0
  123. package/dist/lib/testing/storyboard/runner.js +280 -0
  124. package/dist/lib/testing/storyboard/runner.js.map +1 -0
  125. package/dist/lib/testing/storyboard/task-map.d.ts +21 -0
  126. package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -0
  127. package/dist/lib/testing/storyboard/task-map.js +84 -0
  128. package/dist/lib/testing/storyboard/task-map.js.map +1 -0
  129. package/dist/lib/testing/storyboard/types.d.ts +156 -0
  130. package/dist/lib/testing/storyboard/types.d.ts.map +1 -0
  131. package/dist/lib/testing/storyboard/types.js +10 -0
  132. package/dist/lib/testing/storyboard/types.js.map +1 -0
  133. package/dist/lib/testing/storyboard/validations.d.ts +17 -0
  134. package/dist/lib/testing/storyboard/validations.d.ts.map +1 -0
  135. package/dist/lib/testing/storyboard/validations.js +166 -0
  136. package/dist/lib/testing/storyboard/validations.js.map +1 -0
  137. package/dist/lib/testing/types.d.ts +4 -1
  138. package/dist/lib/testing/types.d.ts.map +1 -1
  139. package/dist/lib/types/core.generated.d.ts +36 -23
  140. package/dist/lib/types/core.generated.d.ts.map +1 -1
  141. package/dist/lib/types/core.generated.js +1 -1
  142. package/dist/lib/types/schemas.generated.d.ts +1098 -770
  143. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  144. package/dist/lib/types/schemas.generated.js +163 -76
  145. package/dist/lib/types/schemas.generated.js.map +1 -1
  146. package/dist/lib/types/tools.generated.d.ts +314 -24
  147. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  148. package/dist/lib/utils/capabilities.d.ts +4 -1
  149. package/dist/lib/utils/capabilities.d.ts.map +1 -1
  150. package/dist/lib/utils/capabilities.js +25 -1
  151. package/dist/lib/utils/capabilities.js.map +1 -1
  152. package/dist/lib/utils/response-schemas.d.ts.map +1 -1
  153. package/dist/lib/utils/response-schemas.js +34 -3
  154. package/dist/lib/utils/response-schemas.js.map +1 -1
  155. package/dist/lib/utils/validate-user-agent.d.ts +8 -0
  156. package/dist/lib/utils/validate-user-agent.d.ts.map +1 -0
  157. package/dist/lib/utils/validate-user-agent.js +15 -0
  158. package/dist/lib/utils/validate-user-agent.js.map +1 -0
  159. package/dist/lib/version.d.ts +9 -3
  160. package/dist/lib/version.d.ts.map +1 -1
  161. package/dist/lib/version.js +10 -4
  162. package/dist/lib/version.js.map +1 -1
  163. package/docs/README.md +42 -0
  164. package/docs/guides/BUILD-AN-AGENT.md +292 -0
  165. package/docs/llms.txt +634 -0
  166. package/examples/README.md +106 -0
  167. package/examples/adcp.config.json +30 -0
  168. package/examples/basic-a2a.ts +76 -0
  169. package/examples/basic-mcp.ts +50 -0
  170. package/examples/batch-preview-test.ts +266 -0
  171. package/examples/conversation-client.ts +291 -0
  172. package/examples/debug-preview-response.ts +73 -0
  173. package/examples/debug-preview-with-logging.ts +50 -0
  174. package/examples/easy-config-demo.ts +242 -0
  175. package/examples/env-config.ts +51 -0
  176. package/examples/error-compliant-server.ts +237 -0
  177. package/examples/generative-creative-demo.ts +205 -0
  178. package/examples/inspect-card-formats.ts +161 -0
  179. package/examples/logger-usage.ts +165 -0
  180. package/examples/oauth-cli-example.ts +154 -0
  181. package/examples/pr78-async-patterns-demo.ts +247 -0
  182. package/examples/signals-agent.ts +162 -0
  183. package/examples/simple-getting-started.ts +225 -0
  184. package/examples/simple-protocol-demo.ts +75 -0
  185. package/examples/test-helpers-demo.ts +239 -0
  186. package/examples/zod-validation-example.ts +126 -0
  187. package/package.json +12 -2
  188. package/skills/adcp/SKILL.md +13 -2
  189. package/storyboards/audience_sync.yaml +199 -0
  190. package/storyboards/behavioral_analysis.yaml +244 -0
  191. package/storyboards/brand_rights.yaml +131 -0
  192. package/storyboards/creative_ad_server.yaml +171 -0
  193. package/storyboards/creative_sales_agent.yaml +169 -0
  194. package/storyboards/creative_template.yaml +306 -0
  195. package/storyboards/deterministic_testing.yaml +925 -0
  196. package/storyboards/error_compliance.yaml +231 -0
  197. package/storyboards/governance_content_standards.yaml +213 -0
  198. package/storyboards/governance_property_lists.yaml +372 -0
  199. package/storyboards/media_buy_catalog_creative.yaml +457 -0
  200. package/storyboards/media_buy_governance_escalation.yaml +467 -0
  201. package/storyboards/media_buy_guaranteed_approval.yaml +396 -0
  202. package/storyboards/media_buy_non_guaranteed.yaml +288 -0
  203. package/storyboards/media_buy_proposal_mode.yaml +369 -0
  204. package/storyboards/media_buy_seller.yaml +560 -0
  205. package/storyboards/media_buy_state_machine.yaml +254 -0
  206. package/storyboards/schema.yaml +65 -0
  207. package/storyboards/schema_validation.yaml +166 -0
  208. package/storyboards/si_session.yaml +384 -0
  209. package/storyboards/signal_marketplace.yaml +283 -0
  210. package/storyboards/signal_owned.yaml +211 -0
@@ -0,0 +1,306 @@
1
+ id: creative_template
2
+ version: "1.0.0"
3
+ title: "Creative template and transformation agent"
4
+ category: creative_template
5
+ summary: "Stateless creative agent that takes assets in, applies templates, and produces tags or rendered output."
6
+ platform_types:
7
+ - creative_transformer
8
+ - creative_library
9
+
10
+ track: creative
11
+ required_tools:
12
+ - build_creative
13
+ - list_creative_formats
14
+ narrative: |
15
+ You build a creative management or rich media platform — think Celtra, a format
16
+ conversion service, or any tool that defines ad templates and transforms input assets
17
+ into finished creatives. Your agent is stateless: every call is self-contained. The
18
+ caller passes assets inline with each request, and you return the result. There is no
19
+ creative library to sync to and no persistent state between calls.
20
+
21
+ A buyer agent connects to discover your templates, preview them with real brand assets,
22
+ and request fully built creatives for trafficking. This storyboard walks through that
23
+ flow step by step.
24
+
25
+ agent:
26
+ interaction_model: stateless_transform
27
+ capabilities:
28
+ - supports_transformation
29
+ examples:
30
+ - "Celtra"
31
+ - "Format conversion services"
32
+ - "Rich media template platforms"
33
+
34
+ caller:
35
+ role: buyer_agent
36
+ example: "Scope3 (DSP)"
37
+
38
+ prerequisites:
39
+ description: |
40
+ The caller needs a brand identity (brand.json with colors, fonts, logos) and creative
41
+ assets that match the format's requirements (images at the right dimensions, text at
42
+ the right lengths). The test kit provides these ingredients so you can test without
43
+ assembling them yourself.
44
+ test_kit: "test-kits/acme-outdoor.yaml"
45
+
46
+ phases:
47
+ - id: format_exposure
48
+ title: "Format discovery"
49
+ narrative: |
50
+ The buyer's first question is: what can your platform do? They call
51
+ list_creative_formats to discover your templates — the available ad formats,
52
+ what assets each one requires, what dimensions they render at, and what
53
+ variables (dynamic fields) they support.
54
+
55
+ For a Celtra-like platform, this is where your publisher templates (Yahoo
56
+ Lighthouse, custom slider units) and standard templates (300x250 banners,
57
+ responsive display) get exposed as AdCP-compliant format definitions.
58
+
59
+ steps:
60
+ - id: discover_formats
61
+ title: "Discover available formats"
62
+ narrative: |
63
+ A buyer agent asks: "What creative formats do you support?" This is
64
+ the entry point for any interaction with your agent. The response tells
65
+ the buyer what templates are available, what assets each one needs, and
66
+ what the output dimensions will be.
67
+ task: list_creative_formats
68
+ schema_ref: "creative/list-creative-formats-request.json"
69
+ response_schema_ref: "creative/list-creative-formats-response.json"
70
+ doc_ref: "/creative/task-reference/list_creative_formats"
71
+ comply_scenario: creative_sync
72
+ stateful: false
73
+ expected: |
74
+ Return your supported formats. Each format must include:
75
+ - format_id with your agent_url and a unique id
76
+ - Human-readable name and description
77
+ - Asset slots with types, roles, and requirements (dimensions, file sizes, mime types)
78
+ - Render dimensions (width/height per render)
79
+ - Variables array if the format supports dynamic fields (text, colors, images)
80
+
81
+ sample_request: {}
82
+
83
+ validations:
84
+ - check: response_schema
85
+ description: "Response matches list-creative-formats-response.json schema"
86
+ - check: field_present
87
+ path: "formats"
88
+ description: "Response contains a formats array"
89
+ - check: field_present
90
+ path: "formats[0].format_id.agent_url"
91
+ description: "Each format has a format_id with agent_url"
92
+ - check: field_present
93
+ path: "formats[0].assets"
94
+ description: "Each format defines its asset requirements"
95
+ - check: field_present
96
+ path: "formats[0].renders"
97
+ description: "Each format defines its render dimensions"
98
+
99
+ - id: filter_by_type
100
+ title: "Filter formats by type"
101
+ narrative: |
102
+ The buyer narrows the search. Maybe they only want display formats, or
103
+ they need formats that accept image assets at specific dimensions. This
104
+ tests that your agent handles filter parameters correctly.
105
+ task: list_creative_formats
106
+ schema_ref: "creative/list-creative-formats-request.json"
107
+ response_schema_ref: "creative/list-creative-formats-response.json"
108
+ doc_ref: "/creative/task-reference/list_creative_formats"
109
+ comply_scenario: creative_sync
110
+ stateful: false
111
+ expected: |
112
+ Return only formats matching the filter criteria. If no formats match,
113
+ return an empty formats array — not an error.
114
+
115
+ sample_request:
116
+ type: "display"
117
+ max_width: 728
118
+ max_height: 90
119
+
120
+ validations:
121
+ - check: response_schema
122
+ description: "Response matches schema"
123
+ - check: field_value
124
+ path: "formats[*].type"
125
+ description: "All returned formats are display type"
126
+
127
+ - id: preview
128
+ title: "Preview with real assets"
129
+ narrative: |
130
+ The buyer wants to see what the template looks like with actual content.
131
+ They pass a complete creative manifest inline — brand identity, assets,
132
+ and format reference — and your agent renders a preview.
133
+
134
+ This is where the stateless nature matters: the buyer doesn't sync assets
135
+ to your library first. Everything needed is in the request.
136
+
137
+ To test this, you need compatible "ingredients" — a brand.json and assets
138
+ that match your format's requirements. The test kit provides these.
139
+
140
+ steps:
141
+ - id: preview_creative
142
+ title: "Preview a creative"
143
+ narrative: |
144
+ The buyer has chosen a format from Phase 1 and assembled a manifest with
145
+ brand assets. They call preview_creative with the full manifest inline to
146
+ see how the template renders with real content.
147
+
148
+ For a Celtra-like platform, this is where the template gets populated with
149
+ the advertiser's images, copy, and brand colors, and a preview URL or HTML
150
+ snippet is returned.
151
+ task: preview_creative
152
+ schema_ref: "creative/preview-creative-request.json"
153
+ response_schema_ref: "creative/preview-creative-response.json"
154
+ doc_ref: "/creative/task-reference/preview_creative"
155
+ comply_scenario: creative_flow
156
+ stateful: false
157
+ expected: |
158
+ Return a preview render. The response should include:
159
+ - A preview URL (iframe-embeddable) and/or inline HTML
160
+ - Render dimensions matching the format spec
161
+ - An expiration timestamp (previews are ephemeral)
162
+
163
+ The preview should show the template populated with the provided assets —
164
+ not a placeholder or empty template.
165
+
166
+ sample_request:
167
+ request_type: "single"
168
+ creative_manifest:
169
+ format_id:
170
+ agent_url: "https://your-agent.example.com"
171
+ id: "display_300x250"
172
+ assets:
173
+ - asset_id: "image"
174
+ asset_type: "image"
175
+ url: "https://test-assets.adcontextprotocol.org/acme-outdoor/hero-300x250.jpg"
176
+ - asset_id: "click_url"
177
+ asset_type: "url"
178
+ url: "https://acme-outdoor.example.com/summer-sale"
179
+ - asset_id: "headline"
180
+ asset_type: "text"
181
+ text: "Summer Sale — 40% Off All Gear"
182
+ output_format: "url"
183
+ quality: "draft"
184
+
185
+ validations:
186
+ - check: response_schema
187
+ description: "Response matches preview-creative-response.json schema"
188
+ - check: field_present
189
+ path: "previews[0].renders[0].url"
190
+ description: "Preview includes a renderable URL"
191
+
192
+ - id: build
193
+ title: "Full build (transformation)"
194
+ narrative: |
195
+ Now the buyer needs a finished creative — a serving tag or rendered output they
196
+ can traffic in a media buy. They call build_creative with the same inline manifest
197
+ and a target format. Your agent applies the template and returns the output.
198
+
199
+ This is where the three tag generation models come in:
200
+ - Universal tags: a single tag that adapts to any environment
201
+ - Single-placement tags: scoped to specific dimensions
202
+ - Multi-placement tags: covering multiple sizes in one tag
203
+
204
+ The output is a creative manifest with the serving code in an HTML, JavaScript,
205
+ or VAST asset — ready for the buyer to traffic.
206
+
207
+ steps:
208
+ - id: build_creative
209
+ title: "Build a creative from assets"
210
+ narrative: |
211
+ The buyer passes assets inline along with a target format and asks your agent
212
+ to produce a finished creative. This is the core transformation: raw assets in,
213
+ serving tag out.
214
+
215
+ For a Celtra-like platform, this means applying the template, assembling the
216
+ rich media unit, and returning an ad tag the buyer can traffic.
217
+ task: build_creative
218
+ schema_ref: "media-buy/build-creative-request.json"
219
+ response_schema_ref: "media-buy/build-creative-response.json"
220
+ doc_ref: "/creative/task-reference/build_creative"
221
+ comply_scenario: creative_flow
222
+ stateful: false
223
+ expected: |
224
+ Return a creative manifest with the output creative. The response should include:
225
+ - A creative manifest with serving code (html, javascript, or vast asset)
226
+ - The format_id matching the target format
227
+ - Assets array with the generated output
228
+
229
+ The output should be a valid, traffickable creative — not a preview or placeholder.
230
+
231
+ sample_request:
232
+ creative_manifest:
233
+ format_id:
234
+ agent_url: "https://your-agent.example.com"
235
+ id: "display_300x250"
236
+ assets:
237
+ - asset_id: "image"
238
+ asset_type: "image"
239
+ url: "https://test-assets.adcontextprotocol.org/acme-outdoor/hero-300x250.jpg"
240
+ - asset_id: "click_url"
241
+ asset_type: "url"
242
+ url: "https://acme-outdoor.example.com/summer-sale"
243
+ - asset_id: "headline"
244
+ asset_type: "text"
245
+ text: "Summer Sale — 40% Off All Gear"
246
+ target_format_id:
247
+ agent_url: "https://your-agent.example.com"
248
+ id: "display_300x250"
249
+ brand:
250
+ domain: "acme-outdoor.example.com"
251
+
252
+ validations:
253
+ - check: response_schema
254
+ description: "Response matches build-creative-response.json schema"
255
+ - check: field_present
256
+ path: "creative_manifest.assets"
257
+ description: "Output manifest includes assets"
258
+ - check: field_present
259
+ path: "creative_manifest.format_id"
260
+ description: "Output manifest includes format_id"
261
+
262
+ - id: build_multi_format
263
+ title: "Build for multiple formats"
264
+ narrative: |
265
+ The buyer needs the same creative adapted to several sizes — 300x250, 728x90,
266
+ and 320x50. Instead of making three separate calls, they pass target_format_ids
267
+ (plural) and your agent returns manifests for each.
268
+
269
+ This tests the multi-format generation capability that makes template agents
270
+ valuable — build once, get all sizes.
271
+ task: build_creative
272
+ schema_ref: "media-buy/build-creative-request.json"
273
+ response_schema_ref: "media-buy/build-creative-response.json"
274
+ doc_ref: "/creative/task-reference/build_creative"
275
+ comply_scenario: creative_flow
276
+ stateful: false
277
+ expected: |
278
+ Return creative manifests for each requested format. If a format cannot be
279
+ produced, include it in the response with an error — don't fail the entire
280
+ request.
281
+
282
+ sample_request:
283
+ creative_manifest:
284
+ assets:
285
+ - asset_id: "image"
286
+ asset_type: "image"
287
+ url: "https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg"
288
+ - asset_id: "click_url"
289
+ asset_type: "url"
290
+ url: "https://acme-outdoor.example.com/summer-sale"
291
+ - asset_id: "headline"
292
+ asset_type: "text"
293
+ text: "Summer Sale — 40% Off All Gear"
294
+ target_format_ids:
295
+ - agent_url: "https://your-agent.example.com"
296
+ id: "display_300x250"
297
+ - agent_url: "https://your-agent.example.com"
298
+ id: "display_728x90"
299
+ - agent_url: "https://your-agent.example.com"
300
+ id: "display_320x50"
301
+ brand:
302
+ domain: "acme-outdoor.example.com"
303
+
304
+ validations:
305
+ - check: response_schema
306
+ description: "Response matches schema"