@adcp/client 4.22.0 → 4.23.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.
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/serve.d.ts +32 -4
- package/dist/lib/server/serve.d.ts.map +1 -1
- package/dist/lib/server/serve.js +12 -4
- package/dist/lib/server/serve.js.map +1 -1
- package/dist/lib/testing/compliance/comply.d.ts +22 -5
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
- package/dist/lib/testing/compliance/comply.js +242 -276
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/index.d.ts +1 -0
- package/dist/lib/testing/compliance/index.d.ts.map +1 -1
- package/dist/lib/testing/compliance/index.js +6 -1
- package/dist/lib/testing/compliance/index.js.map +1 -1
- package/dist/lib/testing/compliance/platform-storyboards.d.ts +44 -0
- package/dist/lib/testing/compliance/platform-storyboards.d.ts.map +1 -0
- package/dist/lib/testing/compliance/platform-storyboards.js +230 -0
- package/dist/lib/testing/compliance/platform-storyboards.js.map +1 -0
- package/dist/lib/testing/compliance/storyboard-tracks.d.ts +2 -9
- package/dist/lib/testing/compliance/storyboard-tracks.d.ts.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.js +4 -44
- package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.d.ts.map +1 -1
- package/dist/lib/testing/index.js +6 -1
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/types/core.generated.d.ts +241 -2
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js +1 -1
- package/dist/lib/types/schemas.generated.d.ts +3380 -3154
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +220 -115
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/tools.generated.d.ts +267 -74
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/docs/guides/BUILD-AN-AGENT.md +5 -3
- package/docs/llms.txt +48 -32
- package/examples/signals-agent.ts +3 -2
- package/package.json +1 -1
- package/storyboards/audience_sync.yaml +18 -29
- package/storyboards/behavioral_analysis.yaml +40 -72
- package/storyboards/brand_rights.yaml +172 -75
- package/storyboards/campaign_governance_conditions.yaml +187 -0
- package/storyboards/campaign_governance_delivery.yaml +231 -0
- package/storyboards/campaign_governance_denied.yaml +135 -0
- package/storyboards/capability_discovery.yaml +106 -0
- package/storyboards/content_standards.yaml +251 -0
- package/storyboards/creative_ad_server.yaml +108 -16
- package/storyboards/creative_lifecycle.yaml +284 -0
- package/storyboards/creative_sales_agent.yaml +2 -6
- package/storyboards/creative_template.yaml +1 -5
- package/storyboards/error_compliance.yaml +105 -108
- package/storyboards/media_buy_catalog_creative.yaml +6 -4
- package/storyboards/media_buy_governance_escalation.yaml +9 -5
- package/storyboards/media_buy_guaranteed_approval.yaml +9 -7
- package/storyboards/media_buy_non_guaranteed.yaml +7 -6
- package/storyboards/media_buy_proposal_mode.yaml +9 -8
- package/storyboards/media_buy_seller.yaml +153 -165
- package/storyboards/media_buy_state_machine.yaml +100 -99
- package/storyboards/property_governance.yaml +239 -0
- package/storyboards/schema.yaml +2 -2
- package/storyboards/schema_validation.yaml +58 -51
- package/storyboards/si_session.yaml +99 -317
- package/storyboards/signal_marketplace.yaml +6 -5
- package/storyboards/signal_owned.yaml +5 -5
- package/storyboards/social_platform.yaml +274 -0
- package/storyboards/governance_content_standards.yaml +0 -213
- package/storyboards/governance_property_lists.yaml +0 -372
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
id: creative_lifecycle
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
title: "Creative lifecycle"
|
|
4
|
+
category: creative_lifecycle
|
|
5
|
+
summary: "Full creative lifecycle on a stateful platform: sync multiple creatives, list with filtering, build and preview across formats, observe status transitions."
|
|
6
|
+
track: creative
|
|
7
|
+
required_tools:
|
|
8
|
+
- list_creative_formats
|
|
9
|
+
|
|
10
|
+
narrative: |
|
|
11
|
+
You run a creative platform with a persistent library — an ad server, creative management
|
|
12
|
+
platform, or publisher that accepts and stores creative assets. A buyer agent pushes
|
|
13
|
+
multiple creatives in different formats, queries the library, builds serving tags, previews
|
|
14
|
+
renderings, and monitors creative status as assets move through your review pipeline.
|
|
15
|
+
|
|
16
|
+
This storyboard covers the complete creative lifecycle from the buyer's perspective:
|
|
17
|
+
uploading assets, browsing the library, building deliverables across formats, and
|
|
18
|
+
observing status transitions as creatives move from pending_review through to accepted.
|
|
19
|
+
|
|
20
|
+
The individual creative storyboards (template, ad server, sales agent) cover specific
|
|
21
|
+
interaction models. This storyboard tests the full lifecycle across multiple creatives
|
|
22
|
+
and formats on a single platform.
|
|
23
|
+
|
|
24
|
+
agent:
|
|
25
|
+
interaction_model: stateful_preloaded
|
|
26
|
+
capabilities:
|
|
27
|
+
- has_creative_library
|
|
28
|
+
- supports_transformation
|
|
29
|
+
examples:
|
|
30
|
+
- "Innovid"
|
|
31
|
+
- "Flashtalking"
|
|
32
|
+
- "CM360"
|
|
33
|
+
- "Creative management platforms"
|
|
34
|
+
|
|
35
|
+
caller:
|
|
36
|
+
role: buyer_agent
|
|
37
|
+
example: "Pinnacle Agency (buyer)"
|
|
38
|
+
|
|
39
|
+
prerequisites:
|
|
40
|
+
description: |
|
|
41
|
+
The caller needs creative assets in multiple formats (display, video, native) and
|
|
42
|
+
a brand identity. The test kit provides sample assets at standard ad dimensions.
|
|
43
|
+
test_kit: "test-kits/acme-outdoor.yaml"
|
|
44
|
+
|
|
45
|
+
phases:
|
|
46
|
+
- id: discover_formats
|
|
47
|
+
title: "Discover accepted formats"
|
|
48
|
+
narrative: |
|
|
49
|
+
Before pushing any creatives, the buyer discovers what formats your platform accepts.
|
|
50
|
+
This determines which assets to prepare and what dimensions and specs to target.
|
|
51
|
+
|
|
52
|
+
steps:
|
|
53
|
+
- id: list_formats
|
|
54
|
+
title: "List creative formats"
|
|
55
|
+
narrative: |
|
|
56
|
+
The buyer calls list_creative_formats to discover what your platform accepts.
|
|
57
|
+
The response defines format specs: dimensions, asset requirements, mime types,
|
|
58
|
+
and any platform-specific constraints.
|
|
59
|
+
task: list_creative_formats
|
|
60
|
+
schema_ref: "creative/list-creative-formats-request.json"
|
|
61
|
+
response_schema_ref: "creative/list-creative-formats-response.json"
|
|
62
|
+
doc_ref: "/creative/task-reference/list_creative_formats"
|
|
63
|
+
comply_scenario: creative_lifecycle
|
|
64
|
+
stateful: false
|
|
65
|
+
expected: |
|
|
66
|
+
Return all creative formats your platform accepts:
|
|
67
|
+
- format_id with your agent_url and unique id
|
|
68
|
+
- Asset requirements (dimensions, file sizes, mime types)
|
|
69
|
+
- Render dimensions
|
|
70
|
+
- At least two formats (e.g., display and video)
|
|
71
|
+
|
|
72
|
+
sample_request: {}
|
|
73
|
+
|
|
74
|
+
validations:
|
|
75
|
+
- check: response_schema
|
|
76
|
+
description: "Response matches list-creative-formats-response.json schema"
|
|
77
|
+
- check: field_present
|
|
78
|
+
path: "formats"
|
|
79
|
+
description: "Response contains formats array"
|
|
80
|
+
|
|
81
|
+
- id: sync_multiple
|
|
82
|
+
title: "Sync multiple creatives"
|
|
83
|
+
narrative: |
|
|
84
|
+
The buyer pushes three creatives in different formats to your platform: a display
|
|
85
|
+
banner, a video spot, and a native card. Your platform validates each creative
|
|
86
|
+
against its format specs and returns per-creative status.
|
|
87
|
+
|
|
88
|
+
steps:
|
|
89
|
+
- id: sync_creatives
|
|
90
|
+
title: "Push three creatives in different formats"
|
|
91
|
+
narrative: |
|
|
92
|
+
The buyer syncs three creatives simultaneously: a 300x250 display banner, a 30s
|
|
93
|
+
video spot, and a native content card. Your platform validates each against its
|
|
94
|
+
format specs and returns per-creative action and status.
|
|
95
|
+
task: sync_creatives
|
|
96
|
+
schema_ref: "creative/sync-creatives-request.json"
|
|
97
|
+
response_schema_ref: "creative/sync-creatives-response.json"
|
|
98
|
+
doc_ref: "/creative/task-reference/sync_creatives"
|
|
99
|
+
comply_scenario: creative_lifecycle
|
|
100
|
+
stateful: true
|
|
101
|
+
expected: |
|
|
102
|
+
Accept and validate all three creatives:
|
|
103
|
+
- Per-creative action: created
|
|
104
|
+
- Per-creative status: accepted or pending_review
|
|
105
|
+
- Validation results for each creative
|
|
106
|
+
- Platform-assigned IDs if applicable
|
|
107
|
+
|
|
108
|
+
sample_request:
|
|
109
|
+
account:
|
|
110
|
+
brand:
|
|
111
|
+
domain: "acmeoutdoor.com"
|
|
112
|
+
operator: "pinnacle-agency.com"
|
|
113
|
+
creatives:
|
|
114
|
+
- creative_id: "display_trail_pro_300x250"
|
|
115
|
+
name: "Trail Pro 3000 - Display 300x250"
|
|
116
|
+
format_id:
|
|
117
|
+
agent_url: "https://your-platform.example.com"
|
|
118
|
+
id: "display_300x250"
|
|
119
|
+
assets:
|
|
120
|
+
- asset_id: "image"
|
|
121
|
+
asset_type: "image"
|
|
122
|
+
url: "https://cdn.pinnacle-agency.example/trail-pro-300x250.png"
|
|
123
|
+
mime_type: "image/png"
|
|
124
|
+
- creative_id: "video_30s_trail_pro"
|
|
125
|
+
name: "Trail Pro 3000 - 30s Video"
|
|
126
|
+
format_id:
|
|
127
|
+
agent_url: "https://your-platform.example.com"
|
|
128
|
+
id: "video_30s"
|
|
129
|
+
assets:
|
|
130
|
+
- asset_id: "video"
|
|
131
|
+
asset_type: "video"
|
|
132
|
+
url: "https://cdn.pinnacle-agency.example/trail-pro-30s.mp4"
|
|
133
|
+
mime_type: "video/mp4"
|
|
134
|
+
- creative_id: "native_trail_pro"
|
|
135
|
+
name: "Trail Pro 3000 - Native Card"
|
|
136
|
+
format_id:
|
|
137
|
+
agent_url: "https://your-platform.example.com"
|
|
138
|
+
id: "native_content"
|
|
139
|
+
assets:
|
|
140
|
+
- asset_id: "image"
|
|
141
|
+
asset_type: "image"
|
|
142
|
+
url: "https://cdn.pinnacle-agency.example/trail-pro-native.png"
|
|
143
|
+
mime_type: "image/png"
|
|
144
|
+
- asset_id: "headline"
|
|
145
|
+
asset_type: "text"
|
|
146
|
+
content: "Trail Pro 3000 — Built for the Summit"
|
|
147
|
+
|
|
148
|
+
validations:
|
|
149
|
+
- check: response_schema
|
|
150
|
+
description: "Response matches sync-creatives-response.json schema"
|
|
151
|
+
- check: field_present
|
|
152
|
+
path: "results"
|
|
153
|
+
description: "Response contains per-creative results"
|
|
154
|
+
|
|
155
|
+
- id: list_and_filter
|
|
156
|
+
title: "List creatives with filtering"
|
|
157
|
+
narrative: |
|
|
158
|
+
The buyer queries the creative library to see their synced creatives. First a broad
|
|
159
|
+
list, then filtered by format. This verifies the library correctly stores and indexes
|
|
160
|
+
the pushed creatives.
|
|
161
|
+
|
|
162
|
+
steps:
|
|
163
|
+
- id: list_all
|
|
164
|
+
title: "List all creatives in library"
|
|
165
|
+
narrative: |
|
|
166
|
+
The buyer calls list_creatives with no filters to see all creatives in the
|
|
167
|
+
library for their account. The response includes the three creatives synced
|
|
168
|
+
in the previous phase.
|
|
169
|
+
task: list_creatives
|
|
170
|
+
schema_ref: "creative/list-creatives-request.json"
|
|
171
|
+
response_schema_ref: "creative/list-creatives-response.json"
|
|
172
|
+
doc_ref: "/creative/task-reference/list_creatives"
|
|
173
|
+
comply_scenario: creative_lifecycle
|
|
174
|
+
stateful: true
|
|
175
|
+
expected: |
|
|
176
|
+
Return creatives in the library:
|
|
177
|
+
- creatives array containing the synced items
|
|
178
|
+
- Each creative includes: creative_id, name, format_id, status
|
|
179
|
+
- At least three creatives from the sync phase
|
|
180
|
+
|
|
181
|
+
sample_request:
|
|
182
|
+
account:
|
|
183
|
+
brand:
|
|
184
|
+
domain: "acmeoutdoor.com"
|
|
185
|
+
operator: "pinnacle-agency.com"
|
|
186
|
+
|
|
187
|
+
validations:
|
|
188
|
+
- check: response_schema
|
|
189
|
+
description: "Response matches list-creatives-response.json schema"
|
|
190
|
+
- check: field_present
|
|
191
|
+
path: "creatives"
|
|
192
|
+
description: "Response contains creatives array"
|
|
193
|
+
|
|
194
|
+
- id: list_filtered
|
|
195
|
+
title: "List creatives filtered by format"
|
|
196
|
+
narrative: |
|
|
197
|
+
The buyer lists creatives filtered to a specific format (display only). The
|
|
198
|
+
response should only include creatives matching that format.
|
|
199
|
+
task: list_creatives
|
|
200
|
+
schema_ref: "creative/list-creatives-request.json"
|
|
201
|
+
response_schema_ref: "creative/list-creatives-response.json"
|
|
202
|
+
doc_ref: "/creative/task-reference/list_creatives"
|
|
203
|
+
comply_scenario: creative_lifecycle
|
|
204
|
+
stateful: true
|
|
205
|
+
expected: |
|
|
206
|
+
Return only creatives matching the format filter:
|
|
207
|
+
- creatives array filtered to display format
|
|
208
|
+
- Should include display_trail_pro_300x250 but not video or native
|
|
209
|
+
|
|
210
|
+
sample_request:
|
|
211
|
+
account:
|
|
212
|
+
brand:
|
|
213
|
+
domain: "acmeoutdoor.com"
|
|
214
|
+
operator: "pinnacle-agency.com"
|
|
215
|
+
filters:
|
|
216
|
+
format_ids:
|
|
217
|
+
- agent_url: "https://your-platform.example.com"
|
|
218
|
+
id: "display_300x250"
|
|
219
|
+
|
|
220
|
+
validations:
|
|
221
|
+
- check: response_schema
|
|
222
|
+
description: "Response matches list-creatives-response.json schema"
|
|
223
|
+
- check: field_present
|
|
224
|
+
path: "creatives"
|
|
225
|
+
description: "Response contains filtered creatives"
|
|
226
|
+
|
|
227
|
+
- id: build_and_preview
|
|
228
|
+
title: "Build and preview across formats"
|
|
229
|
+
narrative: |
|
|
230
|
+
The buyer builds serving tags and previews renderings for the synced creatives.
|
|
231
|
+
This tests multi-format output: a display tag, a VAST tag for video, and a
|
|
232
|
+
native rendering preview.
|
|
233
|
+
|
|
234
|
+
steps:
|
|
235
|
+
- id: preview_display
|
|
236
|
+
title: "Preview the display creative"
|
|
237
|
+
narrative: |
|
|
238
|
+
The buyer calls preview_creative for the display banner to see how it renders
|
|
239
|
+
in the platform's environment before going live.
|
|
240
|
+
task: preview_creative
|
|
241
|
+
schema_ref: "creative/preview-creative-request.json"
|
|
242
|
+
response_schema_ref: "creative/preview-creative-response.json"
|
|
243
|
+
doc_ref: "/creative/task-reference/preview_creative"
|
|
244
|
+
comply_scenario: creative_flow
|
|
245
|
+
stateful: true
|
|
246
|
+
expected: |
|
|
247
|
+
Return a preview of the display creative:
|
|
248
|
+
- preview_url: rendered preview the buyer can inspect
|
|
249
|
+
- render_dimensions: matches the 300x250 format
|
|
250
|
+
- status: preview available
|
|
251
|
+
|
|
252
|
+
sample_request:
|
|
253
|
+
creative_id: "display_trail_pro_300x250"
|
|
254
|
+
|
|
255
|
+
validations:
|
|
256
|
+
- check: response_schema
|
|
257
|
+
description: "Response matches preview-creative-response.json schema"
|
|
258
|
+
|
|
259
|
+
- id: build_video_tag
|
|
260
|
+
title: "Build a VAST tag for the video creative"
|
|
261
|
+
narrative: |
|
|
262
|
+
The buyer builds a serving tag for the video creative. The platform produces
|
|
263
|
+
a VAST-compatible tag that the buyer can traffic to ad servers.
|
|
264
|
+
task: build_creative
|
|
265
|
+
schema_ref: "creative/build-creative-request.json"
|
|
266
|
+
response_schema_ref: "creative/build-creative-response.json"
|
|
267
|
+
doc_ref: "/creative/task-reference/build_creative"
|
|
268
|
+
comply_scenario: creative_flow
|
|
269
|
+
stateful: true
|
|
270
|
+
expected: |
|
|
271
|
+
Return a built serving tag for the video creative:
|
|
272
|
+
- tag: VAST-compatible serving tag or URL
|
|
273
|
+
- format: matches the video format
|
|
274
|
+
- creative_id: matches the requested creative
|
|
275
|
+
|
|
276
|
+
sample_request:
|
|
277
|
+
creative_id: "video_30s_trail_pro"
|
|
278
|
+
output_format:
|
|
279
|
+
agent_url: "https://your-platform.example.com"
|
|
280
|
+
id: "vast_30s"
|
|
281
|
+
|
|
282
|
+
validations:
|
|
283
|
+
- check: response_schema
|
|
284
|
+
description: "Response matches build-creative-response.json schema"
|
|
@@ -3,14 +3,10 @@ version: "1.0.0"
|
|
|
3
3
|
title: "Sales agent with creative capabilities"
|
|
4
4
|
category: creative_sales_agent
|
|
5
5
|
summary: "Stateful sales agent that accepts pushed creative assets and renders them in its environment."
|
|
6
|
-
platform_types:
|
|
7
|
-
- retail_media
|
|
8
|
-
- social_platform
|
|
9
|
-
|
|
10
6
|
track: creative
|
|
11
7
|
required_tools:
|
|
12
8
|
- sync_creatives
|
|
13
|
-
|
|
9
|
+
|
|
14
10
|
narrative: |
|
|
15
11
|
You run a publisher platform, retail media network, or other sell-side system that
|
|
16
12
|
accepts creative assets from buyers. The buyer pushes assets or catalog items to your
|
|
@@ -122,7 +118,7 @@ phases:
|
|
|
122
118
|
- check: response_schema
|
|
123
119
|
description: "Response matches sync-creatives-response.json schema"
|
|
124
120
|
- check: field_present
|
|
125
|
-
path: "
|
|
121
|
+
path: "results[0].action"
|
|
126
122
|
description: "Each creative has an action (created/updated)"
|
|
127
123
|
|
|
128
124
|
- id: preview
|
|
@@ -3,14 +3,10 @@ version: "1.0.0"
|
|
|
3
3
|
title: "Creative template and transformation agent"
|
|
4
4
|
category: creative_template
|
|
5
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
6
|
track: creative
|
|
11
7
|
required_tools:
|
|
12
8
|
- build_creative
|
|
13
|
-
|
|
9
|
+
|
|
14
10
|
narrative: |
|
|
15
11
|
You build a creative management or rich media platform — think Celtra, a format
|
|
16
12
|
conversion service, or any tool that defines ad templates and transforms input assets
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
id: error_compliance
|
|
2
2
|
version: "1.0.0"
|
|
3
3
|
title: "Error handling and compliance"
|
|
4
|
-
category:
|
|
5
|
-
track: error_handling
|
|
4
|
+
category: error_compliance
|
|
6
5
|
summary: "Validates that agents return properly structured AdCP errors with correct codes, recovery hints, and transport bindings."
|
|
7
|
-
|
|
6
|
+
track: error_handling
|
|
8
7
|
required_tools:
|
|
9
8
|
- get_products
|
|
10
9
|
|
|
@@ -33,6 +32,12 @@ caller:
|
|
|
33
32
|
role: buyer_agent
|
|
34
33
|
example: "Compliance test harness"
|
|
35
34
|
|
|
35
|
+
prerequisites:
|
|
36
|
+
description: |
|
|
37
|
+
No special prerequisites. The storyboard sends intentionally invalid requests
|
|
38
|
+
to test error handling.
|
|
39
|
+
test_kit: "test-kits/acme-outdoor.yaml"
|
|
40
|
+
|
|
36
41
|
phases:
|
|
37
42
|
- id: error_responses
|
|
38
43
|
title: "Error responses for invalid input"
|
|
@@ -46,16 +51,19 @@ phases:
|
|
|
46
51
|
title: "Reject negative budget"
|
|
47
52
|
narrative: |
|
|
48
53
|
A negative budget is never valid. The agent must reject this with INVALID_REQUEST
|
|
49
|
-
or BUDGET_TOO_LOW and a correctable recovery hint
|
|
54
|
+
or BUDGET_TOO_LOW and a correctable recovery hint.
|
|
50
55
|
task: create_media_buy
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
schema_ref: "media-buy/create-media-buy-request.json"
|
|
57
|
+
response_schema_ref: "media-buy/create-media-buy-response.json"
|
|
58
|
+
doc_ref: "/media-buy/task-reference/create_media_buy"
|
|
59
|
+
comply_scenario: error_handling
|
|
53
60
|
stateful: false
|
|
54
61
|
expected: |
|
|
55
62
|
Reject the request with an error containing:
|
|
56
63
|
- code: INVALID_REQUEST or BUDGET_TOO_LOW
|
|
57
64
|
- recovery: correctable
|
|
58
65
|
- field: packages[0].budget (optional but recommended)
|
|
66
|
+
|
|
59
67
|
sample_request:
|
|
60
68
|
idempotency_key: "error-test-negative-budget"
|
|
61
69
|
start_time: "2026-05-01T00:00:00Z"
|
|
@@ -64,10 +72,11 @@ phases:
|
|
|
64
72
|
- product_id: "test-product"
|
|
65
73
|
budget: -500
|
|
66
74
|
pricing_option_id: "test-pricing"
|
|
75
|
+
|
|
67
76
|
validations:
|
|
68
|
-
- check:
|
|
69
|
-
|
|
70
|
-
description: "
|
|
77
|
+
- check: field_present
|
|
78
|
+
path: "errors"
|
|
79
|
+
description: "Response contains an error for negative budget"
|
|
71
80
|
|
|
72
81
|
- id: nonexistent_product
|
|
73
82
|
title: "Reject nonexistent product ID"
|
|
@@ -75,157 +84,145 @@ phases:
|
|
|
75
84
|
The buyer references a product ID that does not exist on this platform.
|
|
76
85
|
The agent should return PRODUCT_NOT_FOUND or INVALID_REQUEST.
|
|
77
86
|
task: create_media_buy
|
|
78
|
-
|
|
79
|
-
|
|
87
|
+
schema_ref: "media-buy/create-media-buy-request.json"
|
|
88
|
+
response_schema_ref: "media-buy/create-media-buy-response.json"
|
|
89
|
+
doc_ref: "/media-buy/task-reference/create_media_buy"
|
|
90
|
+
comply_scenario: error_handling
|
|
80
91
|
stateful: false
|
|
81
92
|
expected: |
|
|
82
|
-
Reject the request with
|
|
93
|
+
Reject the request with:
|
|
83
94
|
- code: PRODUCT_NOT_FOUND or INVALID_REQUEST
|
|
84
95
|
- recovery: correctable
|
|
96
|
+
|
|
85
97
|
sample_request:
|
|
86
98
|
idempotency_key: "error-test-nonexistent-product"
|
|
87
99
|
start_time: "2026-05-01T00:00:00Z"
|
|
88
100
|
end_time: "2026-05-31T23:59:59Z"
|
|
89
101
|
packages:
|
|
90
|
-
- product_id: "
|
|
91
|
-
budget:
|
|
92
|
-
pricing_option_id: "
|
|
102
|
+
- product_id: "nonexistent-product-id-xyz"
|
|
103
|
+
budget: 10000
|
|
104
|
+
pricing_option_id: "test-pricing"
|
|
105
|
+
|
|
93
106
|
validations:
|
|
94
|
-
- check:
|
|
95
|
-
|
|
96
|
-
description: "
|
|
107
|
+
- check: field_present
|
|
108
|
+
path: "errors"
|
|
109
|
+
description: "Response contains an error for nonexistent product"
|
|
97
110
|
|
|
98
111
|
- id: missing_fields
|
|
99
|
-
title: "
|
|
112
|
+
title: "Reject empty get_products request"
|
|
100
113
|
narrative: |
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
114
|
+
Send a get_products request with no brief and no buying_mode. The agent should
|
|
115
|
+
either return products (treating it as a catalog browse) or return an error
|
|
116
|
+
requesting the missing brief.
|
|
104
117
|
task: get_products
|
|
105
|
-
|
|
118
|
+
schema_ref: "media-buy/get-products-request.json"
|
|
119
|
+
response_schema_ref: "media-buy/get-products-response.json"
|
|
120
|
+
doc_ref: "/media-buy/task-reference/get_products"
|
|
121
|
+
comply_scenario: error_handling
|
|
106
122
|
stateful: false
|
|
107
123
|
expected: |
|
|
108
|
-
Either
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
124
|
+
Either return products (treating empty request as browse) or return a
|
|
125
|
+
structured error requesting the missing brief. Both are valid.
|
|
126
|
+
|
|
127
|
+
sample_request:
|
|
128
|
+
brand:
|
|
129
|
+
domain: "acmeoutdoor.com"
|
|
130
|
+
|
|
113
131
|
validations:
|
|
114
132
|
- check: response_schema
|
|
115
|
-
description: "Response is
|
|
133
|
+
description: "Response is either valid products or a structured error"
|
|
116
134
|
|
|
117
|
-
- id:
|
|
118
|
-
title: "Reject
|
|
135
|
+
- id: reversed_dates_error
|
|
136
|
+
title: "Reject reversed dates with error code"
|
|
119
137
|
narrative: |
|
|
120
|
-
|
|
121
|
-
|
|
138
|
+
Send a create_media_buy with end_time before start_time and verify the error
|
|
139
|
+
response includes the correct code and recovery classification.
|
|
122
140
|
task: create_media_buy
|
|
123
|
-
|
|
124
|
-
|
|
141
|
+
schema_ref: "media-buy/create-media-buy-request.json"
|
|
142
|
+
response_schema_ref: "media-buy/create-media-buy-response.json"
|
|
143
|
+
doc_ref: "/media-buy/task-reference/create_media_buy"
|
|
144
|
+
comply_scenario: error_handling
|
|
125
145
|
stateful: false
|
|
126
146
|
expected: |
|
|
127
|
-
Reject
|
|
128
|
-
|
|
129
|
-
- recovery: correctable
|
|
130
|
-
- field: end_time (optional but recommended)
|
|
147
|
+
Reject with INVALID_REQUEST and correctable recovery.
|
|
148
|
+
|
|
131
149
|
sample_request:
|
|
132
150
|
idempotency_key: "error-test-reversed-dates"
|
|
133
|
-
start_time: "2026-
|
|
134
|
-
end_time: "2026-
|
|
151
|
+
start_time: "2026-12-31T00:00:00Z"
|
|
152
|
+
end_time: "2026-01-01T00:00:00Z"
|
|
135
153
|
packages:
|
|
136
154
|
- product_id: "test-product"
|
|
137
|
-
budget:
|
|
155
|
+
budget: 10000
|
|
138
156
|
pricing_option_id: "test-pricing"
|
|
157
|
+
|
|
139
158
|
validations:
|
|
140
|
-
- check:
|
|
141
|
-
|
|
142
|
-
description: "
|
|
159
|
+
- check: field_present
|
|
160
|
+
path: "errors"
|
|
161
|
+
description: "Response contains an error for reversed dates"
|
|
143
162
|
|
|
144
163
|
- id: error_structure
|
|
145
|
-
title: "Error
|
|
164
|
+
title: "Error structure compliance"
|
|
146
165
|
narrative: |
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
Optional fields: recovery (transient|correctable|terminal), retry_after (non-negative
|
|
150
|
-
number), field (string), suggestion (string). Non-standard codes must use the X_ prefix.
|
|
166
|
+
Validates that error responses follow the AdCP error structure with required
|
|
167
|
+
and optional fields.
|
|
151
168
|
|
|
152
169
|
steps:
|
|
153
170
|
- id: validate_error_shape
|
|
154
|
-
title: "Validate error
|
|
171
|
+
title: "Validate error response structure"
|
|
155
172
|
narrative: |
|
|
156
|
-
|
|
157
|
-
code and message
|
|
158
|
-
|
|
173
|
+
Trigger an error and inspect the response structure. The adcp_error object
|
|
174
|
+
must have code and message. Optional fields include recovery, retry_after,
|
|
175
|
+
field, and suggestion.
|
|
159
176
|
task: create_media_buy
|
|
160
|
-
|
|
161
|
-
|
|
177
|
+
schema_ref: "media-buy/create-media-buy-request.json"
|
|
178
|
+
response_schema_ref: "media-buy/create-media-buy-response.json"
|
|
179
|
+
doc_ref: "/media-buy/task-reference/create_media_buy"
|
|
180
|
+
comply_scenario: error_codes
|
|
162
181
|
stateful: false
|
|
163
182
|
expected: |
|
|
164
|
-
Error
|
|
165
|
-
- code:
|
|
166
|
-
- message:
|
|
167
|
-
- recovery:
|
|
168
|
-
|
|
169
|
-
- field: string path to the offending field (if present)
|
|
170
|
-
- suggestion: string with remediation hint (if present)
|
|
183
|
+
Error response with:
|
|
184
|
+
- code: a recognized AdCP error code
|
|
185
|
+
- message: human-readable description
|
|
186
|
+
- recovery: correctable, transient, or fatal (optional)
|
|
187
|
+
|
|
171
188
|
sample_request:
|
|
172
|
-
idempotency_key: "error-test
|
|
173
|
-
start_time: "2026-
|
|
174
|
-
end_time: "2026-
|
|
189
|
+
idempotency_key: "error-structure-test"
|
|
190
|
+
start_time: "2026-12-31T00:00:00Z"
|
|
191
|
+
end_time: "2026-01-01T00:00:00Z"
|
|
175
192
|
packages:
|
|
176
|
-
- product_id: "
|
|
177
|
-
budget:
|
|
178
|
-
pricing_option_id: "
|
|
179
|
-
validations:
|
|
180
|
-
- check: field_present
|
|
181
|
-
path: "adcp_error.code"
|
|
182
|
-
description: "Error has a code field"
|
|
183
|
-
- check: field_present
|
|
184
|
-
path: "adcp_error.message"
|
|
185
|
-
description: "Error has a message field"
|
|
193
|
+
- product_id: "test-product"
|
|
194
|
+
budget: -1
|
|
195
|
+
pricing_option_id: "test-pricing"
|
|
186
196
|
|
|
187
197
|
- id: error_transport
|
|
188
|
-
title: "Error transport
|
|
198
|
+
title: "Error transport bindings"
|
|
189
199
|
narrative: |
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
provides the full typed error object.
|
|
194
|
-
|
|
195
|
-
Agents using the adcpError() helper from @adcp/client get all three layers automatically.
|
|
200
|
+
Validates that errors are transported correctly via MCP. The isError flag must
|
|
201
|
+
be set, and the error should be available in both JSON text content (L2) and
|
|
202
|
+
structuredContent (L3) bindings.
|
|
196
203
|
|
|
197
204
|
steps:
|
|
198
205
|
- id: validate_transport_binding
|
|
199
|
-
title: "Validate
|
|
206
|
+
title: "Validate error transport binding"
|
|
200
207
|
narrative: |
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
- JSON text content with adcp_error (L2 fallback)
|
|
204
|
-
- structuredContent.adcp_error (L3 full compliance)
|
|
205
|
-
|
|
206
|
-
L2 is the minimum passing level. L3 is expected for agents using adcpError().
|
|
208
|
+
Trigger an error and verify the MCP transport binding: isError flag must be
|
|
209
|
+
set to true, and the error content should include the adcp_error object.
|
|
207
210
|
task: create_media_buy
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
schema_ref: "media-buy/create-media-buy-request.json"
|
|
212
|
+
response_schema_ref: "media-buy/create-media-buy-response.json"
|
|
213
|
+
doc_ref: "/media-buy/task-reference/create_media_buy"
|
|
214
|
+
comply_scenario: error_transport
|
|
210
215
|
stateful: false
|
|
211
216
|
expected: |
|
|
212
217
|
MCP response with:
|
|
213
218
|
- isError: true
|
|
214
|
-
- content
|
|
215
|
-
|
|
216
|
-
- Error code in structuredContent matches error code in text content (consistency)
|
|
219
|
+
- content containing adcp_error (L2: JSON text, L3: structuredContent)
|
|
220
|
+
|
|
217
221
|
sample_request:
|
|
218
|
-
idempotency_key: "error-test
|
|
219
|
-
start_time: "2026-
|
|
220
|
-
end_time: "2026-
|
|
222
|
+
idempotency_key: "error-transport-test"
|
|
223
|
+
start_time: "2026-12-31T00:00:00Z"
|
|
224
|
+
end_time: "2026-01-01T00:00:00Z"
|
|
221
225
|
packages:
|
|
222
|
-
- product_id: "
|
|
223
|
-
budget:
|
|
224
|
-
pricing_option_id: "
|
|
225
|
-
validations:
|
|
226
|
-
- check: field_present
|
|
227
|
-
path: "adcp_error"
|
|
228
|
-
description: "structuredContent contains adcp_error object"
|
|
229
|
-
- check: error_code
|
|
230
|
-
value: "PRODUCT_NOT_FOUND"
|
|
231
|
-
description: "Error code is a valid AdCP standard code or X_-prefixed vendor code"
|
|
226
|
+
- product_id: "nonexistent"
|
|
227
|
+
budget: -1
|
|
228
|
+
pricing_option_id: "bad-pricing"
|