@adcp/client 4.22.1 → 4.24.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/README.md +23 -9
- package/bin/adcp.js +83 -18
- package/dist/lib/index.d.ts +3 -5
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +16 -12
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/server/index.d.ts +5 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +10 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/postgres-task-store.d.ts +105 -0
- package/dist/lib/server/postgres-task-store.d.ts.map +1 -0
- package/dist/lib/server/postgres-task-store.js +267 -0
- package/dist/lib/server/postgres-task-store.js.map +1 -0
- package/dist/lib/server/responses.d.ts +1 -0
- package/dist/lib/server/responses.d.ts.map +1 -1
- package/dist/lib/server/responses.js +1 -0
- package/dist/lib/server/responses.js.map +1 -1
- package/dist/lib/server/test-controller.d.ts +88 -0
- package/dist/lib/server/test-controller.d.ts.map +1 -0
- package/dist/lib/server/test-controller.js +227 -0
- package/dist/lib/server/test-controller.js.map +1 -0
- package/dist/lib/testing/agent-tester.d.ts +1 -1
- package/dist/lib/testing/agent-tester.d.ts.map +1 -1
- package/dist/lib/testing/agent-tester.js +13 -1
- package/dist/lib/testing/agent-tester.js.map +1 -1
- package/dist/lib/testing/compliance/comply.d.ts +24 -5
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
- package/dist/lib/testing/compliance/comply.js +318 -277
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/index.d.ts +2 -1
- 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 +232 -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 +15 -46
- package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -1
- package/dist/lib/testing/compliance/types.d.ts +22 -1
- package/dist/lib/testing/compliance/types.d.ts.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/testing/orchestrator.d.ts.map +1 -1
- package/dist/lib/testing/orchestrator.js +5 -1
- package/dist/lib/testing/orchestrator.js.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.d.ts +19 -1
- package/dist/lib/testing/scenarios/brand-rights.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.js +138 -1
- package/dist/lib/testing/scenarios/brand-rights.js.map +1 -1
- package/dist/lib/testing/scenarios/deterministic.js +7 -7
- package/dist/lib/testing/scenarios/deterministic.js.map +1 -1
- package/dist/lib/testing/scenarios/index.d.ts +1 -1
- package/dist/lib/testing/scenarios/index.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/index.js +4 -2
- package/dist/lib/testing/scenarios/index.js.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.js +4 -4
- package/dist/lib/testing/scenarios/media-buy.js.map +1 -1
- package/dist/lib/testing/storyboard/loader.d.ts +1 -0
- package/dist/lib/testing/storyboard/loader.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/loader.js +14 -0
- package/dist/lib/testing/storyboard/loader.js.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.js +88 -11
- package/dist/lib/testing/storyboard/request-builder.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +83 -5
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/task-map.d.ts +2 -0
- package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/task-map.js +23 -9
- package/dist/lib/testing/storyboard/task-map.js.map +1 -1
- package/dist/lib/testing/storyboard/types.d.ts +6 -2
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/validations.js +21 -4
- package/dist/lib/testing/storyboard/validations.js.map +1 -1
- package/dist/lib/testing/types.d.ts +1 -1
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/types/core.generated.d.ts +242 -3
- 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 +3697 -3468
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +226 -118
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/tools.generated.d.ts +281 -79
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.d.ts +2 -2
- package/dist/lib/utils/capabilities.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.js +9 -3
- package/dist/lib/utils/capabilities.js.map +1 -1
- package/dist/lib/utils/response-schemas.d.ts.map +1 -1
- package/dist/lib/utils/response-schemas.js +9 -0
- package/dist/lib/utils/response-schemas.js.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/docs/llms.txt +56 -32
- package/package.json +8 -2
- package/skills/adcp/SKILL.md +118 -33
- package/skills/build-creative-agent/SKILL.md +221 -0
- package/skills/build-generative-seller-agent/SKILL.md +288 -0
- package/skills/build-retail-media-agent/SKILL.md +237 -0
- package/skills/build-seller-agent/SKILL.md +313 -0
- package/skills/build-signals-agent/SKILL.md +203 -0
- 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 +136 -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_generative.yaml +317 -0
- package/storyboards/creative_lifecycle.yaml +284 -0
- package/storyboards/creative_sales_agent.yaml +2 -6
- package/storyboards/creative_template.yaml +3 -6
- package/storyboards/deterministic_testing.yaml +271 -245
- package/storyboards/error_compliance.yaml +105 -108
- package/storyboards/media_buy_catalog_creative.yaml +8 -5
- package/storyboards/media_buy_generative_seller.yaml +581 -0
- package/storyboards/media_buy_governance_escalation.yaml +10 -6
- package/storyboards/media_buy_guaranteed_approval.yaml +21 -19
- package/storyboards/media_buy_non_guaranteed.yaml +9 -8
- package/storyboards/media_buy_proposal_mode.yaml +12 -11
- package/storyboards/media_buy_seller.yaml +161 -173
- package/storyboards/media_buy_state_machine.yaml +102 -101
- package/storyboards/property_governance.yaml +239 -0
- package/storyboards/schema.yaml +3 -2
- package/storyboards/schema_validation.yaml +58 -51
- package/storyboards/si_session.yaml +99 -317
- package/storyboards/signal_marketplace.yaml +9 -5
- package/storyboards/signal_owned.yaml +6 -5
- package/storyboards/social_platform.yaml +274 -0
- package/storyboards/test-kits/acme-outdoor.yaml +118 -0
- package/storyboards/test-kits/nova-motors.yaml +134 -0
- package/storyboards/governance_content_standards.yaml +0 -213
- package/storyboards/governance_property_lists.yaml +0 -372
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
id: media_buy_generative_seller
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
title: "Generative seller agent"
|
|
4
|
+
category: media_buy_generative_seller
|
|
5
|
+
summary: "Seller agent that generates creatives from briefs at buy time — no pre-built assets required."
|
|
6
|
+
track: media_buy
|
|
7
|
+
required_tools:
|
|
8
|
+
- get_products
|
|
9
|
+
- create_media_buy
|
|
10
|
+
- list_creative_formats
|
|
11
|
+
- sync_creatives
|
|
12
|
+
- get_media_buy_delivery
|
|
13
|
+
|
|
14
|
+
narrative: |
|
|
15
|
+
You run a generative sell-side platform — an AI ad network, generative DSP, or any system that
|
|
16
|
+
both sells inventory and generates creatives from a brief. The buyer doesn't upload finished
|
|
17
|
+
assets. Instead, they describe what they want via a creative brief, point you at a brand.json,
|
|
18
|
+
and your platform produces finished creatives ready for delivery.
|
|
19
|
+
|
|
20
|
+
This is the media buy seller flow with generative creative capabilities. Your platform handles
|
|
21
|
+
the full lifecycle from brief to reporting, but the creative sync step accepts briefs instead
|
|
22
|
+
of static assets. Your formats declare what brief inputs they accept, and your platform
|
|
23
|
+
generates the creative — potentially asynchronously.
|
|
24
|
+
|
|
25
|
+
A programmatic seller with generative capabilities should also support standard IAB formats
|
|
26
|
+
(display, video, VAST, etc.) for buyers who bring their own assets. A platform that sells
|
|
27
|
+
programmatic inventory but can't accept a pre-built VAST tag or display banner is incoherent.
|
|
28
|
+
The generative capability is additive to standard programmatic creative acceptance.
|
|
29
|
+
|
|
30
|
+
This storyboard focuses on the generative creative delta. Governance agent registration and
|
|
31
|
+
proposal refinement work identically to the base media_buy_seller storyboard — see that
|
|
32
|
+
storyboard for those phases.
|
|
33
|
+
|
|
34
|
+
agent:
|
|
35
|
+
interaction_model: media_buy_seller
|
|
36
|
+
capabilities:
|
|
37
|
+
- sells_media
|
|
38
|
+
- accepts_briefs
|
|
39
|
+
- supports_generation
|
|
40
|
+
- supports_guaranteed
|
|
41
|
+
- supports_non_guaranteed
|
|
42
|
+
examples:
|
|
43
|
+
- "OpenAds"
|
|
44
|
+
- "AI ad networks"
|
|
45
|
+
- "Generative DSPs"
|
|
46
|
+
|
|
47
|
+
caller:
|
|
48
|
+
role: buyer_agent
|
|
49
|
+
example: "Scope3 (DSP)"
|
|
50
|
+
|
|
51
|
+
prerequisites:
|
|
52
|
+
description: |
|
|
53
|
+
The caller needs a brand identity hosted at the brand's domain (brand.json) or resolvable
|
|
54
|
+
via AgenticAdvertising.org. The brand.json provides visual identity — logos, colors, fonts,
|
|
55
|
+
tone — that the generative seller uses to produce on-brand creatives. The test kit provides
|
|
56
|
+
a sample brand with campaign parameters.
|
|
57
|
+
test_kit: "test-kits/acme-outdoor.yaml"
|
|
58
|
+
|
|
59
|
+
phases:
|
|
60
|
+
- id: account_setup
|
|
61
|
+
title: "Account setup"
|
|
62
|
+
narrative: |
|
|
63
|
+
Before buying anything, the buyer establishes an account relationship with your platform.
|
|
64
|
+
This is the same handshake as any media buy seller — the buyer identifies the brand and
|
|
65
|
+
operator, and you provision the account.
|
|
66
|
+
|
|
67
|
+
steps:
|
|
68
|
+
- id: sync_accounts
|
|
69
|
+
title: "Establish account relationship"
|
|
70
|
+
narrative: |
|
|
71
|
+
The buyer registers their brand and operator with your platform. Your platform should
|
|
72
|
+
resolve the brand via AgenticAdvertising.org to pull brand identity for creative
|
|
73
|
+
generation. If the brand domain doesn't resolve, return an error — don't generate
|
|
74
|
+
creatives for unknown brands.
|
|
75
|
+
task: sync_accounts
|
|
76
|
+
schema_ref: "account/sync-accounts-request.json"
|
|
77
|
+
response_schema_ref: "account/sync-accounts-response.json"
|
|
78
|
+
doc_ref: "/accounts/tasks/sync_accounts"
|
|
79
|
+
stateful: true
|
|
80
|
+
expected: |
|
|
81
|
+
Return the account with:
|
|
82
|
+
- account_id: your platform's identifier for this relationship
|
|
83
|
+
- action: created or updated
|
|
84
|
+
- status: active (instant approval) or pending_approval (requires human review)
|
|
85
|
+
- account_scope: operator, brand, operator_brand, or agent
|
|
86
|
+
- setup: URL and message if pending_approval
|
|
87
|
+
|
|
88
|
+
sample_request:
|
|
89
|
+
accounts:
|
|
90
|
+
- brand:
|
|
91
|
+
domain: "acmeoutdoor.com"
|
|
92
|
+
operator: "pinnacle-agency.com"
|
|
93
|
+
billing: "operator"
|
|
94
|
+
payment_terms: "net_30"
|
|
95
|
+
|
|
96
|
+
validations:
|
|
97
|
+
- check: response_schema
|
|
98
|
+
description: "Response matches sync-accounts-response.json schema"
|
|
99
|
+
- check: field_present
|
|
100
|
+
path: "accounts[0].account_id"
|
|
101
|
+
description: "Account has a platform-assigned ID"
|
|
102
|
+
- check: field_present
|
|
103
|
+
path: "accounts[0].status"
|
|
104
|
+
description: "Account has a status (active or pending_approval)"
|
|
105
|
+
|
|
106
|
+
- id: format_discovery
|
|
107
|
+
title: "Format discovery"
|
|
108
|
+
narrative: |
|
|
109
|
+
The buyer discovers what your platform can accept. A generative seller's format catalog
|
|
110
|
+
has two parts: generative formats that accept briefs as inputs, and standard IAB formats
|
|
111
|
+
that accept pre-built assets.
|
|
112
|
+
|
|
113
|
+
Generative formats declare brief asset slots. Standard formats declare image, video, or
|
|
114
|
+
HTML asset slots. The buyer uses this to decide whether to send a brief or upload finished
|
|
115
|
+
assets for each package.
|
|
116
|
+
|
|
117
|
+
A platform selling programmatic inventory should support both. Generative-only is fine for
|
|
118
|
+
a pure creative agent, but a seller that takes media buys needs to accept pre-built assets
|
|
119
|
+
from buyers who already have creatives.
|
|
120
|
+
|
|
121
|
+
steps:
|
|
122
|
+
- id: list_formats
|
|
123
|
+
title: "Discover creative formats"
|
|
124
|
+
narrative: |
|
|
125
|
+
The buyer asks what formats your platform supports. Your response should include both
|
|
126
|
+
generative formats (accepting brief inputs) and standard IAB formats (accepting image,
|
|
127
|
+
video, VAST, etc.).
|
|
128
|
+
|
|
129
|
+
A programmatic seller that only returns generative formats means the buyer can never
|
|
130
|
+
bring their own assets. If you sell inventory, you should accept pre-built creatives
|
|
131
|
+
too — the generative capability is additive.
|
|
132
|
+
task: list_creative_formats
|
|
133
|
+
schema_ref: "creative/list-creative-formats-request.json"
|
|
134
|
+
response_schema_ref: "creative/list-creative-formats-response.json"
|
|
135
|
+
doc_ref: "/creative/task-reference/list_creative_formats"
|
|
136
|
+
comply_scenario: creative_lifecycle
|
|
137
|
+
stateful: false
|
|
138
|
+
expected: |
|
|
139
|
+
Return your format catalog. It should include:
|
|
140
|
+
|
|
141
|
+
Generative formats:
|
|
142
|
+
- format_id with your agent_url and a unique id (e.g., "display_300x250_generative")
|
|
143
|
+
- Asset slots accepting brief asset types
|
|
144
|
+
- Render dimensions for the output
|
|
145
|
+
- Description indicating this is a generative format
|
|
146
|
+
|
|
147
|
+
Standard formats:
|
|
148
|
+
- Standard IAB display formats (300x250, 728x90, etc.)
|
|
149
|
+
- Video formats (VAST, pre-roll, etc.) if applicable
|
|
150
|
+
- Asset slots accepting image, video, html, etc.
|
|
151
|
+
|
|
152
|
+
Both types should be present for a programmatic seller. Buyers who already
|
|
153
|
+
have creatives need to be able to upload them directly.
|
|
154
|
+
|
|
155
|
+
sample_request: {}
|
|
156
|
+
|
|
157
|
+
validations:
|
|
158
|
+
- check: response_schema
|
|
159
|
+
description: "Response matches list-creative-formats-response.json schema"
|
|
160
|
+
- check: field_present
|
|
161
|
+
path: "formats"
|
|
162
|
+
description: "Response contains a formats array"
|
|
163
|
+
- check: field_present
|
|
164
|
+
path: "formats[0].format_id.agent_url"
|
|
165
|
+
description: "Each format has a format_id with agent_url"
|
|
166
|
+
|
|
167
|
+
- id: product_discovery
|
|
168
|
+
title: "Product discovery"
|
|
169
|
+
narrative: |
|
|
170
|
+
The buyer sends a natural-language brief describing what they want to buy. Your platform
|
|
171
|
+
interprets the brief against your inventory and returns products with pricing, delivery
|
|
172
|
+
forecasts, and creative format requirements.
|
|
173
|
+
|
|
174
|
+
Products from a generative seller should reference generative format IDs — telling the
|
|
175
|
+
buyer that this product accepts a brief rather than requiring pre-built assets. Products
|
|
176
|
+
may also reference standard formats for buyers who prefer to supply their own creatives.
|
|
177
|
+
|
|
178
|
+
steps:
|
|
179
|
+
- id: get_products_brief
|
|
180
|
+
title: "Send a brief"
|
|
181
|
+
narrative: |
|
|
182
|
+
The buyer describes what they want. Your platform returns products. Each product's
|
|
183
|
+
creative_format_ids should reference formats from the catalog — some generative,
|
|
184
|
+
some standard. The buyer uses this to decide the creative approach per product.
|
|
185
|
+
task: get_products
|
|
186
|
+
schema_ref: "media-buy/get-products-request.json"
|
|
187
|
+
response_schema_ref: "media-buy/get-products-response.json"
|
|
188
|
+
doc_ref: "/media-buy/task-reference/get_products"
|
|
189
|
+
comply_scenario: full_sales_flow
|
|
190
|
+
stateful: false
|
|
191
|
+
expected: |
|
|
192
|
+
Return products matching the brief. Each product should include:
|
|
193
|
+
- product_id: unique identifier
|
|
194
|
+
- name and description
|
|
195
|
+
- delivery_type: guaranteed or non_guaranteed
|
|
196
|
+
- pricing_models: available pricing options
|
|
197
|
+
- forecast: estimated impressions, reach
|
|
198
|
+
- creative_format_ids: formats this product accepts (including generative formats)
|
|
199
|
+
|
|
200
|
+
sample_request:
|
|
201
|
+
buying_mode: "brief"
|
|
202
|
+
brief: "Premium display and video inventory on outdoor lifestyle content. Q2 flight, $50K budget. Adults 25-54, US. We want your platform to generate the creatives from our brand brief."
|
|
203
|
+
brand:
|
|
204
|
+
domain: "acmeoutdoor.com"
|
|
205
|
+
account:
|
|
206
|
+
brand:
|
|
207
|
+
domain: "acmeoutdoor.com"
|
|
208
|
+
operator: "pinnacle-agency.com"
|
|
209
|
+
|
|
210
|
+
validations:
|
|
211
|
+
- check: response_schema
|
|
212
|
+
description: "Response matches get-products-response.json schema"
|
|
213
|
+
- check: field_present
|
|
214
|
+
path: "products"
|
|
215
|
+
description: "Response contains a products array"
|
|
216
|
+
- check: field_present
|
|
217
|
+
path: "products[0].product_id"
|
|
218
|
+
description: "Each product has a product_id"
|
|
219
|
+
|
|
220
|
+
- id: create_buy
|
|
221
|
+
title: "Create the media buy"
|
|
222
|
+
narrative: |
|
|
223
|
+
The buyer commits to specific products with budgets and flight dates. This is the same
|
|
224
|
+
create_media_buy flow as any seller — the generative aspect doesn't change the buy
|
|
225
|
+
creation. The buy may return pending_creatives status, indicating the buyer needs to
|
|
226
|
+
sync creatives (via brief) before the campaign can go live.
|
|
227
|
+
|
|
228
|
+
steps:
|
|
229
|
+
- id: create_media_buy
|
|
230
|
+
title: "Create a media buy"
|
|
231
|
+
narrative: |
|
|
232
|
+
The buyer commits to products. The response may include pending_creatives status
|
|
233
|
+
for packages that require creative sync before activation.
|
|
234
|
+
task: create_media_buy
|
|
235
|
+
schema_ref: "media-buy/create-media-buy-request.json"
|
|
236
|
+
response_schema_ref: "media-buy/create-media-buy-response.json"
|
|
237
|
+
doc_ref: "/media-buy/task-reference/create_media_buy"
|
|
238
|
+
comply_scenario: create_media_buy
|
|
239
|
+
stateful: true
|
|
240
|
+
expected: |
|
|
241
|
+
Process the media buy request and return one of:
|
|
242
|
+
- completed: buy confirmed, packages may be pending_creatives
|
|
243
|
+
- working: platform is processing (poll for status)
|
|
244
|
+
- submitted: long-running async (approval workflow, IO signing)
|
|
245
|
+
- input-required: need more information
|
|
246
|
+
|
|
247
|
+
sample_request:
|
|
248
|
+
account:
|
|
249
|
+
brand:
|
|
250
|
+
domain: "acmeoutdoor.com"
|
|
251
|
+
operator: "pinnacle-agency.com"
|
|
252
|
+
brand:
|
|
253
|
+
domain: "acmeoutdoor.com"
|
|
254
|
+
start_time: "2026-04-01T00:00:00Z"
|
|
255
|
+
end_time: "2026-06-30T23:59:59Z"
|
|
256
|
+
packages:
|
|
257
|
+
- product_id: "outdoor_display_q2"
|
|
258
|
+
budget: 30000
|
|
259
|
+
pricing_option_id: "cpm_guaranteed"
|
|
260
|
+
- product_id: "outdoor_video_q2"
|
|
261
|
+
budget: 20000
|
|
262
|
+
pricing_option_id: "cpm_standard"
|
|
263
|
+
push_notification_config:
|
|
264
|
+
url: "https://buyer.example/webhooks/adcp"
|
|
265
|
+
authentication:
|
|
266
|
+
scheme: "HMAC-SHA256"
|
|
267
|
+
|
|
268
|
+
validations:
|
|
269
|
+
- check: response_schema
|
|
270
|
+
description: "Response matches create-media-buy-response.json schema"
|
|
271
|
+
|
|
272
|
+
- id: creative_brief_sync
|
|
273
|
+
title: "Creative brief sync"
|
|
274
|
+
narrative: |
|
|
275
|
+
This is where a generative seller diverges from the standard flow. Instead of the buyer
|
|
276
|
+
uploading finished assets, they send a creative brief through sync_creatives. The brief
|
|
277
|
+
describes campaign messaging, tone, audience, and compliance requirements. The format_id
|
|
278
|
+
points to a generative format that accepts brief asset types.
|
|
279
|
+
|
|
280
|
+
Your platform resolves the brand via AgenticAdvertising.org (using the account's brand
|
|
281
|
+
domain), pulls brand.json for visual identity, and generates the creative. This may be
|
|
282
|
+
synchronous (accepted immediately) or asynchronous (pending_review while generation
|
|
283
|
+
completes). The buyer polls or waits for a webhook to know when the creative is ready.
|
|
284
|
+
|
|
285
|
+
steps:
|
|
286
|
+
- id: sync_creatives_brief
|
|
287
|
+
title: "Send creative brief via sync_creatives"
|
|
288
|
+
narrative: |
|
|
289
|
+
The buyer sends a creative brief through sync_creatives, using a generative format_id
|
|
290
|
+
that accepts brief asset types. The account's brand domain tells your platform where
|
|
291
|
+
to resolve brand identity for generation.
|
|
292
|
+
|
|
293
|
+
Your platform should actually read the operator and brand from the request — not
|
|
294
|
+
ignore them. If the brand domain is invalid or unresolvable, return a rejection
|
|
295
|
+
with a clear error rather than generating with defaults.
|
|
296
|
+
task: sync_creatives
|
|
297
|
+
schema_ref: "creative/sync-creatives-request.json"
|
|
298
|
+
response_schema_ref: "creative/sync-creatives-response.json"
|
|
299
|
+
doc_ref: "/creative/task-reference/sync_creatives"
|
|
300
|
+
comply_scenario: creative_sync
|
|
301
|
+
stateful: true
|
|
302
|
+
expected: |
|
|
303
|
+
Accept the creative brief and begin generation:
|
|
304
|
+
- Per-creative action: created
|
|
305
|
+
- Per-creative status: pending_review (generation in progress) or accepted (instant)
|
|
306
|
+
- The brand domain from the account should be resolved via AgenticAdvertising.org
|
|
307
|
+
- If the brand domain is invalid, reject with a clear error
|
|
308
|
+
- If the brief references a non-generative format, reject with format mismatch error
|
|
309
|
+
|
|
310
|
+
sample_request:
|
|
311
|
+
account:
|
|
312
|
+
brand:
|
|
313
|
+
domain: "acmeoutdoor.com"
|
|
314
|
+
operator: "pinnacle-agency.com"
|
|
315
|
+
creatives:
|
|
316
|
+
- creative_id: "gen_display_summer_sale"
|
|
317
|
+
name: "Summer Sale - Generated Display 300x250"
|
|
318
|
+
format_id:
|
|
319
|
+
agent_url: "https://your-platform.example.com"
|
|
320
|
+
id: "display_300x250_generative"
|
|
321
|
+
assets:
|
|
322
|
+
brief:
|
|
323
|
+
name: "Acme Outdoor Summer Sale Q2"
|
|
324
|
+
objective: "conversion"
|
|
325
|
+
tone: "Bold, adventurous, urgent"
|
|
326
|
+
audience: "Active adults 25-54, outdoor enthusiasts"
|
|
327
|
+
territory: "Summer gear clearance"
|
|
328
|
+
messaging:
|
|
329
|
+
headline: "Summer Sale — 40% Off All Gear"
|
|
330
|
+
tagline: "Gear up for less"
|
|
331
|
+
cta: "Shop Now"
|
|
332
|
+
key_messages:
|
|
333
|
+
- "40% off all trail running and hiking gear"
|
|
334
|
+
- "Free shipping on orders over $75"
|
|
335
|
+
compliance:
|
|
336
|
+
required_disclosures:
|
|
337
|
+
- text: "Sale ends June 30, 2026. Exclusions apply."
|
|
338
|
+
position: "footer"
|
|
339
|
+
jurisdictions: ["US"]
|
|
340
|
+
prohibited_claims:
|
|
341
|
+
- "Best price guaranteed"
|
|
342
|
+
- creative_id: "gen_video_summer_sale"
|
|
343
|
+
name: "Summer Sale - Generated Video 30s"
|
|
344
|
+
format_id:
|
|
345
|
+
agent_url: "https://your-platform.example.com"
|
|
346
|
+
id: "video_30s_generative"
|
|
347
|
+
assets:
|
|
348
|
+
brief:
|
|
349
|
+
name: "Acme Outdoor Summer Sale Q2 - Video"
|
|
350
|
+
objective: "awareness"
|
|
351
|
+
tone: "Cinematic, energetic"
|
|
352
|
+
audience: "Active adults 25-54"
|
|
353
|
+
territory: "Summer adventure"
|
|
354
|
+
messaging:
|
|
355
|
+
headline: "Your Next Adventure Starts Here"
|
|
356
|
+
tagline: "Acme Outdoor — Gear up for less"
|
|
357
|
+
cta: "Shop the Sale"
|
|
358
|
+
key_messages:
|
|
359
|
+
- "40% off all gear this summer"
|
|
360
|
+
compliance:
|
|
361
|
+
required_disclosures:
|
|
362
|
+
- text: "Sale ends June 30, 2026. Exclusions apply."
|
|
363
|
+
position: "audio"
|
|
364
|
+
jurisdictions: ["US"]
|
|
365
|
+
assignments:
|
|
366
|
+
- creative_id: "gen_display_summer_sale"
|
|
367
|
+
package_id: "outdoor_display_q2"
|
|
368
|
+
- creative_id: "gen_video_summer_sale"
|
|
369
|
+
package_id: "outdoor_video_q2"
|
|
370
|
+
|
|
371
|
+
validations:
|
|
372
|
+
- check: response_schema
|
|
373
|
+
description: "Response matches sync-creatives-response.json schema"
|
|
374
|
+
- check: field_present
|
|
375
|
+
path: "creatives[0].action"
|
|
376
|
+
description: "Each creative has an action (created/updated)"
|
|
377
|
+
- check: field_present
|
|
378
|
+
path: "creatives[0].status"
|
|
379
|
+
description: "Each creative has a status (pending_review or accepted)"
|
|
380
|
+
|
|
381
|
+
- id: sync_creatives_standard
|
|
382
|
+
title: "Sync standard creatives alongside generative"
|
|
383
|
+
narrative: |
|
|
384
|
+
The buyer sends a pre-built creative using a standard format — verifying that this
|
|
385
|
+
programmatic seller also accepts traditional asset uploads alongside generative briefs.
|
|
386
|
+
task: sync_creatives
|
|
387
|
+
schema_ref: "creative/sync-creatives-request.json"
|
|
388
|
+
response_schema_ref: "creative/sync-creatives-response.json"
|
|
389
|
+
doc_ref: "/creative/task-reference/sync_creatives"
|
|
390
|
+
comply_scenario: creative_sync
|
|
391
|
+
stateful: true
|
|
392
|
+
expected: |
|
|
393
|
+
Accept the standard creative:
|
|
394
|
+
- Per-creative action: created
|
|
395
|
+
- Per-creative status: accepted or pending_review
|
|
396
|
+
- Standard asset validation (dimensions, file size, mime type)
|
|
397
|
+
|
|
398
|
+
sample_request:
|
|
399
|
+
account:
|
|
400
|
+
brand:
|
|
401
|
+
domain: "acmeoutdoor.com"
|
|
402
|
+
operator: "pinnacle-agency.com"
|
|
403
|
+
creatives:
|
|
404
|
+
- creative_id: "static_display_300x250"
|
|
405
|
+
name: "Trail Pro 3000 - Pre-built Display 300x250"
|
|
406
|
+
format_id:
|
|
407
|
+
agent_url: "https://your-platform.example.com"
|
|
408
|
+
id: "display_300x250"
|
|
409
|
+
assets:
|
|
410
|
+
image:
|
|
411
|
+
url: "https://cdn.pinnacle-agency.example/trail-pro-300x250.png"
|
|
412
|
+
format: "png"
|
|
413
|
+
width: 300
|
|
414
|
+
height: 250
|
|
415
|
+
|
|
416
|
+
validations:
|
|
417
|
+
- check: response_schema
|
|
418
|
+
description: "Response matches sync-creatives-response.json schema"
|
|
419
|
+
- check: field_present
|
|
420
|
+
path: "creatives[0].action"
|
|
421
|
+
description: "Standard creative has an action"
|
|
422
|
+
|
|
423
|
+
- id: sync_creatives_invalid_brand
|
|
424
|
+
title: "Reject brief with invalid brand"
|
|
425
|
+
narrative: |
|
|
426
|
+
The buyer sends a brief referencing a brand domain that doesn't exist in
|
|
427
|
+
AgenticAdvertising.org. The seller should reject the creative rather than
|
|
428
|
+
generating with unknown brand identity.
|
|
429
|
+
task: sync_creatives
|
|
430
|
+
schema_ref: "creative/sync-creatives-request.json"
|
|
431
|
+
response_schema_ref: "creative/sync-creatives-response.json"
|
|
432
|
+
doc_ref: "/creative/task-reference/sync_creatives"
|
|
433
|
+
comply_scenario: creative_sync
|
|
434
|
+
stateful: true
|
|
435
|
+
expected: |
|
|
436
|
+
Reject the creative with a clear error:
|
|
437
|
+
- Per-creative status: rejected
|
|
438
|
+
- Validation error indicating the brand domain could not be resolved
|
|
439
|
+
- The seller should not generate creatives for unknown brands
|
|
440
|
+
|
|
441
|
+
sample_request:
|
|
442
|
+
account:
|
|
443
|
+
brand:
|
|
444
|
+
domain: "nonexistent-brand-xyz.example"
|
|
445
|
+
operator: "pinnacle-agency.com"
|
|
446
|
+
creatives:
|
|
447
|
+
- creative_id: "gen_invalid_brand"
|
|
448
|
+
name: "Invalid Brand Test"
|
|
449
|
+
format_id:
|
|
450
|
+
agent_url: "https://your-platform.example.com"
|
|
451
|
+
id: "display_300x250_generative"
|
|
452
|
+
assets:
|
|
453
|
+
brief:
|
|
454
|
+
name: "Test brief"
|
|
455
|
+
objective: "awareness"
|
|
456
|
+
tone: "Neutral"
|
|
457
|
+
messaging:
|
|
458
|
+
headline: "Test"
|
|
459
|
+
cta: "Click"
|
|
460
|
+
|
|
461
|
+
validations:
|
|
462
|
+
- check: response_schema
|
|
463
|
+
description: "Response matches sync-creatives-response.json schema"
|
|
464
|
+
- check: field_present
|
|
465
|
+
path: "creatives[0].status"
|
|
466
|
+
description: "Creative has a status (expected: rejected)"
|
|
467
|
+
|
|
468
|
+
- id: creative_generation_lifecycle
|
|
469
|
+
title: "Creative generation lifecycle"
|
|
470
|
+
narrative: |
|
|
471
|
+
If creative generation is asynchronous, the buyer monitors progress. The seller
|
|
472
|
+
transitions creatives through processing → pending_review → approved as generation
|
|
473
|
+
completes. The comply_test_controller can force these transitions for deterministic
|
|
474
|
+
testing via force_creative_status.
|
|
475
|
+
|
|
476
|
+
The buyer polls by re-calling sync_creatives with the same creatives. Because
|
|
477
|
+
sync_creatives has upsert semantics, re-sending the same brief is idempotent — the
|
|
478
|
+
seller returns the current status without restarting generation.
|
|
479
|
+
|
|
480
|
+
steps:
|
|
481
|
+
- id: check_creative_status
|
|
482
|
+
title: "Poll creative generation status"
|
|
483
|
+
narrative: |
|
|
484
|
+
The buyer re-sends the same creatives via sync_creatives. Because sync has upsert
|
|
485
|
+
semantics, this is idempotent — the seller returns updated statuses without
|
|
486
|
+
restarting generation. If the creative was pending_review after the initial sync,
|
|
487
|
+
it should transition to approved once generation completes. In testing, the
|
|
488
|
+
comply_test_controller forces this transition via force_creative_status.
|
|
489
|
+
task: sync_creatives
|
|
490
|
+
schema_ref: "creative/sync-creatives-request.json"
|
|
491
|
+
response_schema_ref: "creative/sync-creatives-response.json"
|
|
492
|
+
doc_ref: "/creative/task-reference/sync_creatives"
|
|
493
|
+
comply_scenario: creative_sync
|
|
494
|
+
stateful: true
|
|
495
|
+
expected: |
|
|
496
|
+
Return updated creative statuses:
|
|
497
|
+
- Generative creatives should transition from pending_review to approved
|
|
498
|
+
- Approved creatives should include generated assets (image URLs, VAST tags, etc.)
|
|
499
|
+
- The generated output should reflect the brand identity from the original brief
|
|
500
|
+
|
|
501
|
+
sample_request:
|
|
502
|
+
account:
|
|
503
|
+
brand:
|
|
504
|
+
domain: "acmeoutdoor.com"
|
|
505
|
+
operator: "pinnacle-agency.com"
|
|
506
|
+
creatives:
|
|
507
|
+
- creative_id: "gen_display_summer_sale"
|
|
508
|
+
name: "Summer Sale - Generated Display 300x250"
|
|
509
|
+
format_id:
|
|
510
|
+
agent_url: "https://your-platform.example.com"
|
|
511
|
+
id: "display_300x250_generative"
|
|
512
|
+
assets:
|
|
513
|
+
brief:
|
|
514
|
+
name: "Acme Outdoor Summer Sale Q2"
|
|
515
|
+
objective: "conversion"
|
|
516
|
+
tone: "Bold, adventurous, urgent"
|
|
517
|
+
messaging:
|
|
518
|
+
headline: "Summer Sale — 40% Off All Gear"
|
|
519
|
+
cta: "Shop Now"
|
|
520
|
+
- creative_id: "gen_video_summer_sale"
|
|
521
|
+
name: "Summer Sale - Generated Video 30s"
|
|
522
|
+
format_id:
|
|
523
|
+
agent_url: "https://your-platform.example.com"
|
|
524
|
+
id: "video_30s_generative"
|
|
525
|
+
assets:
|
|
526
|
+
brief:
|
|
527
|
+
name: "Acme Outdoor Summer Sale Q2 - Video"
|
|
528
|
+
objective: "awareness"
|
|
529
|
+
tone: "Cinematic, energetic"
|
|
530
|
+
messaging:
|
|
531
|
+
headline: "Your Next Adventure Starts Here"
|
|
532
|
+
cta: "Shop the Sale"
|
|
533
|
+
|
|
534
|
+
validations:
|
|
535
|
+
- check: response_schema
|
|
536
|
+
description: "Response matches sync-creatives-response.json schema"
|
|
537
|
+
- check: field_present
|
|
538
|
+
path: "creatives[0].status"
|
|
539
|
+
description: "Each creative has a current status"
|
|
540
|
+
|
|
541
|
+
- id: delivery_monitoring
|
|
542
|
+
title: "Delivery and reporting"
|
|
543
|
+
narrative: |
|
|
544
|
+
The campaign is live. Delivery monitoring is identical to any media buy seller —
|
|
545
|
+
the generative aspect doesn't change how delivery is reported. The buyer monitors
|
|
546
|
+
impressions, clicks, spend, and pacing.
|
|
547
|
+
|
|
548
|
+
steps:
|
|
549
|
+
- id: get_delivery
|
|
550
|
+
title: "Check delivery metrics"
|
|
551
|
+
narrative: |
|
|
552
|
+
The buyer requests delivery data for the active media buy. Reporting is the same
|
|
553
|
+
regardless of whether creatives were generated or uploaded.
|
|
554
|
+
task: get_media_buy_delivery
|
|
555
|
+
schema_ref: "media-buy/get-media-buy-delivery-request.json"
|
|
556
|
+
response_schema_ref: "media-buy/get-media-buy-delivery-response.json"
|
|
557
|
+
doc_ref: "/media-buy/task-reference/get_media_buy_delivery"
|
|
558
|
+
comply_scenario: reporting_flow
|
|
559
|
+
stateful: true
|
|
560
|
+
expected: |
|
|
561
|
+
Return delivery metrics for the media buy:
|
|
562
|
+
- Per-package delivery: impressions, clicks, spend, completion rates
|
|
563
|
+
- Daily breakdown if requested
|
|
564
|
+
- Pacing information
|
|
565
|
+
- Budget utilization
|
|
566
|
+
|
|
567
|
+
sample_request:
|
|
568
|
+
account:
|
|
569
|
+
brand:
|
|
570
|
+
domain: "acmeoutdoor.com"
|
|
571
|
+
operator: "pinnacle-agency.com"
|
|
572
|
+
media_buy_ids:
|
|
573
|
+
- "mb_acme_q2_2026"
|
|
574
|
+
include_package_daily_breakdown: true
|
|
575
|
+
|
|
576
|
+
validations:
|
|
577
|
+
- check: response_schema
|
|
578
|
+
description: "Response matches get-media-buy-delivery-response.json schema"
|
|
579
|
+
- check: field_present
|
|
580
|
+
path: "media_buy_deliveries"
|
|
581
|
+
description: "Response contains media buy delivery data"
|
|
@@ -3,14 +3,11 @@ version: "1.0.0"
|
|
|
3
3
|
title: "Governance denial and human escalation"
|
|
4
4
|
category: media_buy_governance_escalation
|
|
5
5
|
summary: "Buyer's governance agent denies a media buy that exceeds spending authority, escalates to a human who approves with conditions."
|
|
6
|
-
platform_types:
|
|
7
|
-
- dsp
|
|
8
|
-
- ai_ad_network
|
|
9
|
-
- generative_dsp
|
|
10
|
-
|
|
11
6
|
track: campaign_governance
|
|
12
7
|
required_tools:
|
|
13
8
|
- sync_plans
|
|
9
|
+
- check_governance
|
|
10
|
+
|
|
14
11
|
narrative: |
|
|
15
12
|
The buyer's governance agent denies a media buy because it exceeds the agent's spending
|
|
16
13
|
authority. The governance check escalates to a human reviewer who approves with conditions.
|
|
@@ -137,6 +134,7 @@ phases:
|
|
|
137
134
|
schema_ref: "governance/sync-plans-request.json"
|
|
138
135
|
response_schema_ref: "governance/sync-plans-response.json"
|
|
139
136
|
doc_ref: "/governance/campaign/tasks/sync_plans"
|
|
137
|
+
comply_scenario: campaign_governance
|
|
140
138
|
stateful: true
|
|
141
139
|
expected: |
|
|
142
140
|
Acknowledge the governance plan:
|
|
@@ -179,6 +177,7 @@ phases:
|
|
|
179
177
|
schema_ref: "media-buy/get-products-request.json"
|
|
180
178
|
response_schema_ref: "media-buy/get-products-response.json"
|
|
181
179
|
doc_ref: "/media-buy/task-reference/get_products"
|
|
180
|
+
comply_scenario: full_sales_flow
|
|
182
181
|
stateful: false
|
|
183
182
|
expected: |
|
|
184
183
|
Return products matching the brief with pricing that totals above $20K:
|
|
@@ -224,6 +223,7 @@ phases:
|
|
|
224
223
|
schema_ref: "governance/check-governance-request.json"
|
|
225
224
|
response_schema_ref: "governance/check-governance-response.json"
|
|
226
225
|
doc_ref: "/governance/campaign/tasks/check_governance"
|
|
226
|
+
comply_scenario: campaign_governance_denied
|
|
227
227
|
stateful: true
|
|
228
228
|
expected: |
|
|
229
229
|
Return a denied governance decision:
|
|
@@ -282,6 +282,7 @@ phases:
|
|
|
282
282
|
schema_ref: "governance/check-governance-request.json"
|
|
283
283
|
response_schema_ref: "governance/check-governance-response.json"
|
|
284
284
|
doc_ref: "/governance/campaign/tasks/check_governance"
|
|
285
|
+
comply_scenario: campaign_governance_conditions
|
|
285
286
|
stateful: true
|
|
286
287
|
expected: |
|
|
287
288
|
Return an approved governance decision with conditions:
|
|
@@ -344,11 +345,12 @@ phases:
|
|
|
344
345
|
schema_ref: "media-buy/create-media-buy-request.json"
|
|
345
346
|
response_schema_ref: "media-buy/create-media-buy-response.json"
|
|
346
347
|
doc_ref: "/media-buy/task-reference/create_media_buy"
|
|
348
|
+
comply_scenario: create_media_buy
|
|
347
349
|
stateful: true
|
|
348
350
|
expected: |
|
|
349
351
|
Confirm the media buy with governance approval:
|
|
350
352
|
- media_buy_id: your platform's identifier
|
|
351
|
-
- status:
|
|
353
|
+
- status: active
|
|
352
354
|
- confirmed_at: timestamp
|
|
353
355
|
- governance_context: echoed back confirming governance was validated
|
|
354
356
|
- packages: confirmed line items
|
|
@@ -398,6 +400,7 @@ phases:
|
|
|
398
400
|
schema_ref: "governance/report-plan-outcome-request.json"
|
|
399
401
|
response_schema_ref: "governance/report-plan-outcome-response.json"
|
|
400
402
|
doc_ref: "/governance/campaign/tasks/report_plan_outcome"
|
|
403
|
+
comply_scenario: campaign_governance
|
|
401
404
|
stateful: true
|
|
402
405
|
expected: |
|
|
403
406
|
Acknowledge the outcome report:
|
|
@@ -443,6 +446,7 @@ phases:
|
|
|
443
446
|
schema_ref: "governance/get-plan-audit-logs-request.json"
|
|
444
447
|
response_schema_ref: "governance/get-plan-audit-logs-response.json"
|
|
445
448
|
doc_ref: "/governance/campaign/tasks/get_plan_audit_logs"
|
|
449
|
+
comply_scenario: campaign_governance
|
|
446
450
|
stateful: false
|
|
447
451
|
expected: |
|
|
448
452
|
Return the complete audit trail for the governance plan:
|