@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,396 @@
1
+ id: media_buy_guaranteed_approval
2
+ version: "1.0.0"
3
+ title: "Guaranteed media buy with human IO approval"
4
+ category: media_buy_guaranteed_approval
5
+ summary: "Seller agent that requires human-in-the-loop IO signing before guaranteed media buys go live."
6
+ platform_types:
7
+ - display_ad_server
8
+ - video_ad_server
9
+ - audio_platform
10
+ - linear_tv_platform
11
+
12
+ track: media_buy
13
+ required_tools:
14
+ - create_media_buy
15
+ narrative: |
16
+ You run a sell-side platform that requires human approval before guaranteed media buys go
17
+ live. When a buyer creates a guaranteed buy, your platform returns a submitted status with
18
+ an estimated completion time. A human reviewer on your side reviews the deal terms and
19
+ signs the IO through a URL your platform provides.
20
+
21
+ The buyer either polls get_media_buys or configures a push_notification_config webhook to
22
+ receive a callback when the IO is signed. Once approved, the media buy transitions from
23
+ pending_approval to confirmed/active and the buyer can sync creatives and monitor delivery.
24
+
25
+ This storyboard isolates the guaranteed approval path — the async handshake between agent
26
+ automation and human decision-making that makes guaranteed buys work in practice.
27
+
28
+ agent:
29
+ interaction_model: media_buy_seller
30
+ capabilities:
31
+ - sells_media
32
+ - supports_guaranteed
33
+ - requires_io_approval
34
+ examples:
35
+ - "Premium publisher with IO requirements"
36
+ - "Retail media network with sales approval"
37
+ - "CTV platform with guaranteed deals"
38
+
39
+ caller:
40
+ role: buyer_agent
41
+ example: "Scope3 (DSP)"
42
+
43
+ prerequisites:
44
+ description: |
45
+ The caller needs a brand identity and operator credentials for account setup.
46
+ The test kit provides a sample brand (Acme Outdoor) with campaign parameters
47
+ suitable for testing the guaranteed approval flow.
48
+ test_kit: "test-kits/acme-outdoor.yaml"
49
+
50
+ phases:
51
+ - id: account_setup
52
+ title: "Account setup"
53
+ narrative: |
54
+ Before buying anything, the buyer establishes an account relationship with
55
+ your platform. This is the handshake: the buyer tells you which brand and
56
+ agency (operator) they represent, and you return an account ID, status, and
57
+ any setup requirements.
58
+
59
+ steps:
60
+ - id: sync_accounts
61
+ title: "Establish account relationship"
62
+ narrative: |
63
+ The buyer registers their brand and operator with your platform. This is
64
+ the first call in any new relationship. Your platform validates the request,
65
+ provisions the account, and returns its status.
66
+ task: sync_accounts
67
+ schema_ref: "account/sync-accounts-request.json"
68
+ response_schema_ref: "account/sync-accounts-response.json"
69
+ doc_ref: "/accounts/tasks/sync_accounts"
70
+ stateful: true
71
+ expected: |
72
+ Return the account with:
73
+ - account_id: your platform's identifier for this relationship
74
+ - action: created or updated
75
+ - status: active or pending_approval
76
+ - account_scope: operator, brand, operator_brand, or agent
77
+ - setup: URL and message if pending_approval
78
+ - payment_terms: net_30, prepay, etc.
79
+
80
+ sample_request:
81
+ accounts:
82
+ - brand:
83
+ domain: "acmeoutdoor.com"
84
+ operator: "pinnacle-agency.com"
85
+ billing: "operator"
86
+ payment_terms: "net_30"
87
+
88
+ validations:
89
+ - check: response_schema
90
+ description: "Response matches sync-accounts-response.json schema"
91
+ - check: field_present
92
+ path: "accounts[0].account_id"
93
+ description: "Account has a platform-assigned ID"
94
+ - check: field_present
95
+ path: "accounts[0].status"
96
+ description: "Account has a status (active or pending_approval)"
97
+
98
+ - id: product_discovery
99
+ title: "Discover guaranteed products"
100
+ narrative: |
101
+ The buyer sends a brief to discover your guaranteed inventory. The emphasis
102
+ here is on products with delivery_type: guaranteed — fixed-price, reserved
103
+ inventory that requires an IO commitment. Your platform returns products with
104
+ pricing, delivery forecasts, and SLA commitments.
105
+
106
+ steps:
107
+ - id: get_products_brief
108
+ title: "Send a brief targeting guaranteed inventory"
109
+ narrative: |
110
+ The buyer describes what they want, emphasizing guaranteed delivery. Your
111
+ platform returns products with delivery_type: guaranteed, including SLA
112
+ commitments, minimum spend requirements, and IO terms.
113
+ task: get_products
114
+ schema_ref: "media-buy/get-products-request.json"
115
+ response_schema_ref: "media-buy/get-products-response.json"
116
+ doc_ref: "/media-buy/task-reference/get_products"
117
+ stateful: false
118
+ expected: |
119
+ Return guaranteed products matching the brief. Each product should include:
120
+ - product_id: unique identifier
121
+ - name and description
122
+ - delivery_type: guaranteed
123
+ - pricing_models: fixed CPM or flat-rate pricing
124
+ - forecast: committed impressions with SLA guarantees
125
+ - creative_format_ids: required creative formats
126
+ - minimum_spend or commitment terms if applicable
127
+
128
+ sample_request:
129
+ buying_mode: "brief"
130
+ brief: "Guaranteed premium video on sports and outdoor lifestyle publishers. Q2 flight, $50K budget. Adults 25-54, US only. Need completion rate SLA."
131
+ brand:
132
+ domain: "acmeoutdoor.com"
133
+ account:
134
+ brand:
135
+ domain: "acmeoutdoor.com"
136
+ operator: "pinnacle-agency.com"
137
+
138
+ validations:
139
+ - check: response_schema
140
+ description: "Response matches get-products-response.json schema"
141
+ - check: field_present
142
+ path: "products"
143
+ description: "Response contains a products array"
144
+ - check: field_present
145
+ path: "products[0].product_id"
146
+ description: "Each product has a product_id"
147
+ - check: field_present
148
+ path: "products[0].delivery_type"
149
+ description: "Each product declares delivery_type: guaranteed"
150
+
151
+ - id: create_buy_submitted
152
+ title: "Create guaranteed buy (submitted for approval)"
153
+ narrative: |
154
+ The buyer creates a guaranteed media buy. Because your platform requires human
155
+ IO signing for guaranteed deals, the response comes back as submitted — not
156
+ completed. The buyer gets an estimated_completion timestamp indicating when the
157
+ IO review should finish. The buyer configures a webhook to be notified when the
158
+ status changes.
159
+
160
+ steps:
161
+ - id: create_media_buy
162
+ title: "Create a guaranteed media buy"
163
+ narrative: |
164
+ The buyer commits to guaranteed products with budgets and flight dates. Your
165
+ platform accepts the request but does not confirm it immediately. Instead,
166
+ it enters an IO approval workflow and returns submitted status with an
167
+ estimated_completion timestamp.
168
+
169
+ The buyer includes push_notification_config so your platform can call back
170
+ when the IO is signed (or rejected).
171
+ task: create_media_buy
172
+ schema_ref: "media-buy/create-media-buy-request.json"
173
+ response_schema_ref: "media-buy/create-media-buy-response.json"
174
+ doc_ref: "/media-buy/task-reference/create_media_buy"
175
+ stateful: true
176
+ expected: |
177
+ Return the media buy in submitted status:
178
+ - media_buy_id: your platform's identifier
179
+ - status: submitted (NOT completed — this requires human approval)
180
+ - estimated_completion: timestamp when the IO review should finish
181
+ - packages: the proposed line items echoed back
182
+ - The buyer's push_notification_config is acknowledged
183
+
184
+ Do NOT return completed status for guaranteed buys that require IO signing.
185
+
186
+ sample_request:
187
+ account:
188
+ brand:
189
+ domain: "acmeoutdoor.com"
190
+ operator: "pinnacle-agency.com"
191
+ brand:
192
+ domain: "acmeoutdoor.com"
193
+ start_time: "2026-04-01T00:00:00Z"
194
+ end_time: "2026-06-30T23:59:59Z"
195
+ packages:
196
+ - product_id: "sports_preroll_q2_guaranteed"
197
+ budget: 30000
198
+ pricing_option_id: "cpm_guaranteed_fixed"
199
+ creative_assignments:
200
+ - creative_id: "video_30s_trail_pro"
201
+ - product_id: "outdoor_ctv_q2_guaranteed"
202
+ budget: 20000
203
+ pricing_option_id: "cpm_guaranteed_fixed"
204
+ push_notification_config:
205
+ url: "https://buyer.example/webhooks/adcp"
206
+ authentication:
207
+ scheme: "HMAC-SHA256"
208
+
209
+ validations:
210
+ - check: response_schema
211
+ description: "Response matches create-media-buy-response.json schema"
212
+
213
+ - id: poll_approval
214
+ title: "Poll for IO approval"
215
+ narrative: |
216
+ The media buy is sitting in an approval queue. A human on the seller side needs
217
+ to review the deal terms and sign the IO. The buyer polls get_media_buys to check
218
+ the current status. Your platform returns pending_approval with a setup URL where
219
+ the human reviewer signs the IO and a message explaining what is needed.
220
+
221
+ steps:
222
+ - id: get_media_buys_pending
223
+ title: "Check media buy status (pending approval)"
224
+ narrative: |
225
+ The buyer polls for the media buy status. Your platform returns
226
+ pending_approval with a setup object containing the URL where the human
227
+ reviewer signs the IO and a message describing what action is needed.
228
+ task: get_media_buys
229
+ schema_ref: "media-buy/get-media-buys-request.json"
230
+ response_schema_ref: "media-buy/get-media-buys-response.json"
231
+ doc_ref: "/media-buy/task-reference/get_media_buys"
232
+ stateful: true
233
+ expected: |
234
+ Return the media buy in pending_approval status:
235
+ - media_buy_id: matches the buy created earlier
236
+ - status: pending_approval
237
+ - setup.url: where the human goes to review and sign the IO
238
+ - setup.message: explains what the human needs to do (e.g., "Review and sign the IO for Acme Outdoor Q2 campaign")
239
+ - packages: line items with their current state
240
+ - valid_actions: what the buyer can do in this state
241
+
242
+ sample_request:
243
+ account:
244
+ brand:
245
+ domain: "acmeoutdoor.com"
246
+ operator: "pinnacle-agency.com"
247
+ media_buy_ids:
248
+ - "mb_acme_q2_2026_guaranteed"
249
+
250
+ validations:
251
+ - check: response_schema
252
+ description: "Response matches get-media-buys-response.json schema"
253
+ - check: field_present
254
+ path: "media_buys[0].status"
255
+ description: "Media buy has a status"
256
+ - check: field_present
257
+ path: "media_buys[0].setup.url"
258
+ description: "Pending approval buy includes a setup URL for IO signing"
259
+ - check: field_present
260
+ path: "media_buys[0].setup.message"
261
+ description: "Pending approval buy includes a message explaining what's needed"
262
+
263
+ - id: confirm_active
264
+ title: "Confirm active after IO signing"
265
+ narrative: |
266
+ The human has reviewed the IO and signed it through the setup URL. The buyer
267
+ polls get_media_buys again (or received a webhook notification) and sees that the
268
+ media buy has transitioned from pending_approval to confirmed or active. The buy
269
+ is now live.
270
+
271
+ steps:
272
+ - id: get_media_buys_confirmed
273
+ title: "Check media buy status (confirmed/active)"
274
+ narrative: |
275
+ After the human signs the IO, the buyer checks the media buy status again.
276
+ Your platform returns confirmed or active, indicating the buy is approved
277
+ and inventory is reserved.
278
+ task: get_media_buys
279
+ schema_ref: "media-buy/get-media-buys-request.json"
280
+ response_schema_ref: "media-buy/get-media-buys-response.json"
281
+ doc_ref: "/media-buy/task-reference/get_media_buys"
282
+ stateful: true
283
+ expected: |
284
+ Return the media buy in confirmed or active status:
285
+ - media_buy_id: matches the buy created earlier
286
+ - status: confirmed or active (IO has been signed)
287
+ - confirmed_at: timestamp when the IO was signed
288
+ - packages: line items now confirmed with reserved inventory
289
+ - valid_actions: updated for confirmed state (creative sync, pause, etc.)
290
+
291
+ sample_request:
292
+ account:
293
+ brand:
294
+ domain: "acmeoutdoor.com"
295
+ operator: "pinnacle-agency.com"
296
+ media_buy_ids:
297
+ - "mb_acme_q2_2026_guaranteed"
298
+
299
+ validations:
300
+ - check: response_schema
301
+ description: "Response matches get-media-buys-response.json schema"
302
+ - check: field_present
303
+ path: "media_buys[0].status"
304
+ description: "Media buy status is confirmed or active"
305
+ - check: field_present
306
+ path: "media_buys[0].confirmed_at"
307
+ description: "Confirmed buy includes a confirmed_at timestamp"
308
+
309
+ - id: creative_sync
310
+ title: "Creative sync"
311
+ narrative: |
312
+ With the IO signed and the media buy confirmed, the buyer syncs creative assets
313
+ to your platform. Each package has creative format requirements that the buyer
314
+ discovered during product discovery.
315
+
316
+ steps:
317
+ - id: sync_creatives
318
+ title: "Push creative assets"
319
+ narrative: |
320
+ The buyer uploads creative assets for the confirmed packages. Your platform
321
+ validates each creative against the format specs and returns per-creative status.
322
+ task: sync_creatives
323
+ schema_ref: "creative/sync-creatives-request.json"
324
+ response_schema_ref: "creative/sync-creatives-response.json"
325
+ doc_ref: "/creative/task-reference/sync_creatives"
326
+ stateful: true
327
+ expected: |
328
+ Accept and validate creatives:
329
+ - Per-creative action: created or updated
330
+ - Per-creative status: accepted, pending_review, or rejected
331
+ - Validation errors for rejected creatives
332
+
333
+ sample_request:
334
+ account:
335
+ brand:
336
+ domain: "acmeoutdoor.com"
337
+ operator: "pinnacle-agency.com"
338
+ creatives:
339
+ - creative_id: "video_30s_trail_pro"
340
+ name: "Trail Pro 3000 - 30s CTV Spot"
341
+ format_id:
342
+ agent_url: "https://your-platform.example.com"
343
+ id: "ssai_30s"
344
+ assets:
345
+ - asset_id: "video"
346
+ asset_type: "video"
347
+ url: "https://cdn.pinnacle-agency.example/trail-pro-30s.mp4"
348
+ mime_type: "video/mp4"
349
+
350
+ validations:
351
+ - check: response_schema
352
+ description: "Response matches sync-creatives-response.json schema"
353
+ - check: field_present
354
+ path: "creatives[0].action"
355
+ description: "Each creative has an action (created/updated)"
356
+
357
+ - id: delivery_monitoring
358
+ title: "Delivery and reporting"
359
+ narrative: |
360
+ The campaign is live with guaranteed delivery commitments. The buyer monitors
361
+ delivery to ensure the seller is meeting the SLA guarantees from the IO.
362
+
363
+ steps:
364
+ - id: get_delivery
365
+ title: "Check delivery metrics"
366
+ narrative: |
367
+ The buyer requests delivery data for the active guaranteed media buy. Your
368
+ platform returns performance metrics with pacing against the guaranteed
369
+ commitment.
370
+ task: get_media_buy_delivery
371
+ schema_ref: "media-buy/get-media-buy-delivery-request.json"
372
+ response_schema_ref: "media-buy/get-media-buy-delivery-response.json"
373
+ doc_ref: "/media-buy/task-reference/get_media_buy_delivery"
374
+ stateful: true
375
+ expected: |
376
+ Return delivery metrics for the guaranteed media buy:
377
+ - Per-package delivery: impressions, clicks, spend, completion rates
378
+ - Pacing against guaranteed commitment: on track, ahead, behind
379
+ - Budget utilization: spent vs. committed
380
+ - SLA compliance: completion rate vs. guaranteed threshold
381
+
382
+ sample_request:
383
+ account:
384
+ brand:
385
+ domain: "acmeoutdoor.com"
386
+ operator: "pinnacle-agency.com"
387
+ media_buy_ids:
388
+ - "mb_acme_q2_2026_guaranteed"
389
+ include_package_daily_breakdown: true
390
+
391
+ validations:
392
+ - check: response_schema
393
+ description: "Response matches get-media-buy-delivery-response.json schema"
394
+ - check: field_present
395
+ path: "media_buys"
396
+ description: "Response contains media buy delivery data"
@@ -0,0 +1,288 @@
1
+ id: media_buy_non_guaranteed
2
+ version: "1.0.0"
3
+ title: "Non-guaranteed auction-based media buy"
4
+ category: media_buy_non_guaranteed
5
+ summary: "Seller agent for auction-based, non-guaranteed buying where the buyer sets bid prices and budgets."
6
+ platform_types:
7
+ - social_platform
8
+ - dsp
9
+ - pmax_platform
10
+ - generative_dsp
11
+
12
+ track: media_buy
13
+ required_tools:
14
+ - create_media_buy
15
+ narrative: |
16
+ You run a sell-side platform with auction-based inventory. Non-guaranteed buys don't
17
+ require IOs or human approval — the buyer sets a bid price and budget, and your platform
18
+ runs the auction. Delivery is best-effort based on bid competitiveness.
19
+
20
+ The buyer discovers products with floor prices and bid guidance, creates a buy with bid
21
+ prices per package, monitors win rates and pacing, and adjusts bids or budgets in-flight
22
+ to optimize performance.
23
+
24
+ This storyboard covers the non-guaranteed buying path — fast setup, no human approval,
25
+ real-time optimization through bid and budget adjustments.
26
+
27
+ agent:
28
+ interaction_model: media_buy_seller
29
+ capabilities:
30
+ - sells_media
31
+ - supports_non_guaranteed
32
+ - auction_based
33
+ examples:
34
+ - "SSP with programmatic auction inventory"
35
+ - "Exchange-based publisher platform"
36
+ - "Open marketplace seller"
37
+
38
+ caller:
39
+ role: buyer_agent
40
+ example: "Scope3 (DSP)"
41
+
42
+ prerequisites:
43
+ description: |
44
+ The caller needs a brand identity and operator credentials. Non-guaranteed buys
45
+ typically have lower barriers to entry — no IO signing required. The test kit
46
+ provides a sample brand (Acme Outdoor) with bid parameters suitable for testing
47
+ the auction-based flow.
48
+ test_kit: "test-kits/acme-outdoor.yaml"
49
+
50
+ phases:
51
+ - id: product_discovery
52
+ title: "Discover auction-based products"
53
+ narrative: |
54
+ The buyer sends a brief to discover your non-guaranteed inventory. Products
55
+ come back with delivery_type: non_guaranteed, floor prices, and bid guidance
56
+ that helps the buyer set competitive bids.
57
+
58
+ steps:
59
+ - id: get_products_brief
60
+ title: "Send a brief for non-guaranteed inventory"
61
+ narrative: |
62
+ The buyer describes what they want. Your platform returns non-guaranteed
63
+ products with auction mechanics: floor prices, recommended bid ranges,
64
+ estimated win rates at different bid levels, and available audience segments.
65
+ task: get_products
66
+ schema_ref: "media-buy/get-products-request.json"
67
+ response_schema_ref: "media-buy/get-products-response.json"
68
+ doc_ref: "/media-buy/task-reference/get_products"
69
+ stateful: false
70
+ expected: |
71
+ Return non-guaranteed products matching the brief. Each product should include:
72
+ - product_id: unique identifier
73
+ - name and description
74
+ - delivery_type: non_guaranteed
75
+ - pricing_models: auction-based pricing with floor_price and recommended bid range
76
+ - forecast: estimated impressions at different bid levels (best-effort)
77
+ - creative_format_ids: required creative formats
78
+ - targeting: available audiences and contexts
79
+
80
+ sample_request:
81
+ buying_mode: "brief"
82
+ brief: "Display and video inventory across sports and outdoor lifestyle sites. Q2 flight, $25K budget. Adults 25-54, US. Auction-based, looking for competitive CPMs."
83
+ brand:
84
+ domain: "acmeoutdoor.com"
85
+ account:
86
+ brand:
87
+ domain: "acmeoutdoor.com"
88
+ operator: "pinnacle-agency.com"
89
+
90
+ validations:
91
+ - check: response_schema
92
+ description: "Response matches get-products-response.json schema"
93
+ - check: field_present
94
+ path: "products"
95
+ description: "Response contains a products array"
96
+ - check: field_present
97
+ path: "products[0].product_id"
98
+ description: "Each product has a product_id"
99
+ - check: field_present
100
+ path: "products[0].delivery_type"
101
+ description: "Each product declares delivery_type: non_guaranteed"
102
+
103
+ - id: create_buy
104
+ title: "Create non-guaranteed buy"
105
+ narrative: |
106
+ The buyer creates a media buy with bid prices per package. Since this is
107
+ non-guaranteed, no IO is required and no human approval is needed. The response
108
+ comes back as completed — the buy is immediately active and your platform starts
109
+ bidding in auctions on the buyer's behalf.
110
+
111
+ steps:
112
+ - id: create_media_buy
113
+ title: "Create a media buy with bid prices"
114
+ narrative: |
115
+ The buyer commits to non-guaranteed products with bid prices and budgets.
116
+ Your platform validates the bids against floor prices, confirms the buy
117
+ immediately (completed status), and begins auction participation.
118
+
119
+ Each package includes a bid_price that the buyer is willing to pay per unit
120
+ (CPM, CPC, etc.). The platform uses this to compete in auctions.
121
+ task: create_media_buy
122
+ schema_ref: "media-buy/create-media-buy-request.json"
123
+ response_schema_ref: "media-buy/create-media-buy-response.json"
124
+ doc_ref: "/media-buy/task-reference/create_media_buy"
125
+ stateful: true
126
+ expected: |
127
+ Return the media buy in completed status:
128
+ - media_buy_id: your platform's identifier
129
+ - status: confirmed or active (no async approval needed)
130
+ - confirmed_at: timestamp
131
+ - packages: confirmed line items with bid prices acknowledged
132
+ - valid_actions: pause, update_bid, get_delivery
133
+
134
+ Bids below floor_price should be rejected with a clear error.
135
+
136
+ sample_request:
137
+ account:
138
+ brand:
139
+ domain: "acmeoutdoor.com"
140
+ operator: "pinnacle-agency.com"
141
+ brand:
142
+ domain: "acmeoutdoor.com"
143
+ start_time: "2026-04-01T00:00:00Z"
144
+ end_time: "2026-06-30T23:59:59Z"
145
+ packages:
146
+ - product_id: "sports_display_auction"
147
+ budget: 10000
148
+ bid_price: 8.50
149
+ pricing_option_id: "cpm_auction"
150
+ creative_assignments:
151
+ - creative_id: "display_trail_pro_300x250"
152
+ - product_id: "outdoor_video_auction"
153
+ budget: 15000
154
+ bid_price: 22.00
155
+ pricing_option_id: "cpm_auction"
156
+ creative_assignments:
157
+ - creative_id: "video_30s_trail_pro"
158
+
159
+ validations:
160
+ - check: response_schema
161
+ description: "Response matches create-media-buy-response.json schema"
162
+
163
+ - id: monitor_pacing
164
+ title: "Monitor win rates and pacing"
165
+ narrative: |
166
+ The non-guaranteed buy is live and bidding in auctions. The buyer checks
167
+ pacing to understand how competitive their bids are and whether the budget
168
+ is spending at the desired rate.
169
+
170
+ steps:
171
+ - id: get_media_buys_pacing
172
+ title: "Check buy status and pacing"
173
+ narrative: |
174
+ The buyer polls for the media buy status. Your platform returns the active
175
+ buy with pacing data — how much budget has been spent, win rates, and whether
176
+ the buy is on pace to exhaust the budget by the end of the flight.
177
+ task: get_media_buys
178
+ schema_ref: "media-buy/get-media-buys-request.json"
179
+ response_schema_ref: "media-buy/get-media-buys-response.json"
180
+ doc_ref: "/media-buy/task-reference/get_media_buys"
181
+ stateful: true
182
+ expected: |
183
+ Return the media buy with pacing data:
184
+ - media_buy_id: matches the buy created earlier
185
+ - status: active
186
+ - packages: line items with current spend, win rate, and pacing status
187
+ - valid_actions: update, pause, get_delivery
188
+
189
+ sample_request:
190
+ account:
191
+ brand:
192
+ domain: "acmeoutdoor.com"
193
+ operator: "pinnacle-agency.com"
194
+ media_buy_ids:
195
+ - "mb_acme_q2_2026_auction"
196
+
197
+ validations:
198
+ - check: response_schema
199
+ description: "Response matches get-media-buys-response.json schema"
200
+ - check: field_present
201
+ path: "media_buys[0].status"
202
+ description: "Media buy has a status"
203
+
204
+ - id: adjust_bids
205
+ title: "Adjust bids and budget"
206
+ narrative: |
207
+ Based on pacing data, the buyer adjusts bids or budgets in-flight. If a package
208
+ is underspending (low win rate), the buyer increases the bid. If a package is
209
+ overspending, the buyer decreases the bid or caps the daily budget.
210
+
211
+ steps:
212
+ - id: update_media_buy
213
+ title: "Update bid prices and budget"
214
+ narrative: |
215
+ The buyer modifies the active media buy — adjusting bid prices, reallocating
216
+ budget between packages, or changing daily spend caps. Your platform applies
217
+ the updates immediately to the live auction participation.
218
+ task: update_media_buy
219
+ schema_ref: "media-buy/update-media-buy-request.json"
220
+ response_schema_ref: "media-buy/update-media-buy-response.json"
221
+ doc_ref: "/media-buy/task-reference/update_media_buy"
222
+ stateful: true
223
+ expected: |
224
+ Apply the updates and return the modified media buy:
225
+ - media_buy_id: matches the existing buy
226
+ - status: active (still running)
227
+ - packages: updated line items reflecting new bids and budgets
228
+ - Changes take effect immediately for subsequent auctions
229
+
230
+ sample_request:
231
+ account:
232
+ brand:
233
+ domain: "acmeoutdoor.com"
234
+ operator: "pinnacle-agency.com"
235
+ media_buy_id: "mb_acme_q2_2026_auction"
236
+ packages:
237
+ - product_id: "sports_display_auction"
238
+ bid_price: 10.00
239
+ budget: 12000
240
+ - product_id: "outdoor_video_auction"
241
+ bid_price: 20.00
242
+ budget: 13000
243
+
244
+ validations:
245
+ - check: response_schema
246
+ description: "Response matches update-media-buy-response.json schema"
247
+
248
+ - id: delivery
249
+ title: "Delivery and auction metrics"
250
+ narrative: |
251
+ The buyer reviews delivery data including auction-specific metrics: win rates,
252
+ average clearing prices, and bid competitiveness across packages.
253
+
254
+ steps:
255
+ - id: get_delivery
256
+ title: "Check delivery with auction metrics"
257
+ narrative: |
258
+ The buyer requests delivery data for the active non-guaranteed media buy.
259
+ Your platform returns standard delivery metrics plus auction-specific data:
260
+ win rates, average clearing prices, bid-to-win ratios, and budget pacing.
261
+ task: get_media_buy_delivery
262
+ schema_ref: "media-buy/get-media-buy-delivery-request.json"
263
+ response_schema_ref: "media-buy/get-media-buy-delivery-response.json"
264
+ doc_ref: "/media-buy/task-reference/get_media_buy_delivery"
265
+ stateful: true
266
+ expected: |
267
+ Return delivery metrics for the non-guaranteed media buy:
268
+ - Per-package delivery: impressions, clicks, spend
269
+ - Win rate: percentage of auctions won per package
270
+ - Average clearing price: what the buyer actually paid vs. bid price
271
+ - Pacing: on track, ahead, behind relative to budget and flight dates
272
+ - Budget utilization: spent vs. committed
273
+
274
+ sample_request:
275
+ account:
276
+ brand:
277
+ domain: "acmeoutdoor.com"
278
+ operator: "pinnacle-agency.com"
279
+ media_buy_ids:
280
+ - "mb_acme_q2_2026_auction"
281
+ include_package_daily_breakdown: true
282
+
283
+ validations:
284
+ - check: response_schema
285
+ description: "Response matches get-media-buy-delivery-response.json schema"
286
+ - check: field_present
287
+ path: "media_buys"
288
+ description: "Response contains media buy delivery data"