@adcp/sdk 5.25.1 → 6.0.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 (288) hide show
  1. package/README.md +45 -7
  2. package/dist/lib/compliance-fixtures/index.d.ts +1 -1
  3. package/dist/lib/compliance-fixtures/index.js +1 -1
  4. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  5. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  6. package/dist/lib/core/SingleAgentClient.js +15 -0
  7. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  8. package/dist/lib/core/TaskExecutor.d.ts +7 -0
  9. package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
  10. package/dist/lib/core/TaskExecutor.js +9 -2
  11. package/dist/lib/core/TaskExecutor.js.map +1 -1
  12. package/dist/lib/index.d.ts +1 -1
  13. package/dist/lib/index.d.ts.map +1 -1
  14. package/dist/lib/index.js +7 -8
  15. package/dist/lib/index.js.map +1 -1
  16. package/dist/lib/schemas/index.d.ts +1 -1
  17. package/dist/lib/schemas/index.js +1 -1
  18. package/dist/lib/server/create-adcp-server.d.ts +129 -11
  19. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  20. package/dist/lib/server/create-adcp-server.js +112 -2
  21. package/dist/lib/server/create-adcp-server.js.map +1 -1
  22. package/dist/lib/server/ctx-metadata/backends/memory.d.ts +27 -0
  23. package/dist/lib/server/ctx-metadata/backends/memory.d.ts.map +1 -0
  24. package/dist/lib/server/ctx-metadata/backends/memory.js +72 -0
  25. package/dist/lib/server/ctx-metadata/backends/memory.js.map +1 -0
  26. package/dist/lib/server/ctx-metadata/backends/pg.d.ts +62 -0
  27. package/dist/lib/server/ctx-metadata/backends/pg.d.ts.map +1 -0
  28. package/dist/lib/server/ctx-metadata/backends/pg.js +145 -0
  29. package/dist/lib/server/ctx-metadata/backends/pg.js.map +1 -0
  30. package/dist/lib/server/ctx-metadata/index.d.ts +15 -0
  31. package/dist/lib/server/ctx-metadata/index.d.ts.map +1 -0
  32. package/dist/lib/server/ctx-metadata/index.js +28 -0
  33. package/dist/lib/server/ctx-metadata/index.js.map +1 -0
  34. package/dist/lib/server/ctx-metadata/store.d.ts +177 -0
  35. package/dist/lib/server/ctx-metadata/store.d.ts.map +1 -0
  36. package/dist/lib/server/ctx-metadata/store.js +327 -0
  37. package/dist/lib/server/ctx-metadata/store.js.map +1 -0
  38. package/dist/lib/server/ctx-metadata/wire-shape.d.ts +55 -0
  39. package/dist/lib/server/ctx-metadata/wire-shape.d.ts.map +1 -0
  40. package/dist/lib/server/ctx-metadata/wire-shape.js +121 -0
  41. package/dist/lib/server/ctx-metadata/wire-shape.js.map +1 -0
  42. package/dist/lib/server/decisioning/account.d.ts +309 -0
  43. package/dist/lib/server/decisioning/account.d.ts.map +1 -0
  44. package/dist/lib/server/decisioning/account.js +102 -0
  45. package/dist/lib/server/decisioning/account.js.map +1 -0
  46. package/dist/lib/server/decisioning/admin-router.d.ts +75 -0
  47. package/dist/lib/server/decisioning/admin-router.d.ts.map +1 -0
  48. package/dist/lib/server/decisioning/admin-router.js +120 -0
  49. package/dist/lib/server/decisioning/admin-router.js.map +1 -0
  50. package/dist/lib/server/decisioning/assembly-helpers.d.ts +204 -0
  51. package/dist/lib/server/decisioning/assembly-helpers.d.ts.map +1 -0
  52. package/dist/lib/server/decisioning/assembly-helpers.js +173 -0
  53. package/dist/lib/server/decisioning/assembly-helpers.js.map +1 -0
  54. package/dist/lib/server/decisioning/async-outcome.d.ts +154 -0
  55. package/dist/lib/server/decisioning/async-outcome.d.ts.map +1 -0
  56. package/dist/lib/server/decisioning/async-outcome.js +239 -0
  57. package/dist/lib/server/decisioning/async-outcome.js.map +1 -0
  58. package/dist/lib/server/decisioning/capabilities.d.ts +251 -0
  59. package/dist/lib/server/decisioning/capabilities.d.ts.map +1 -0
  60. package/dist/lib/server/decisioning/capabilities.js +16 -0
  61. package/dist/lib/server/decisioning/capabilities.js.map +1 -0
  62. package/dist/lib/server/decisioning/context.d.ts +212 -0
  63. package/dist/lib/server/decisioning/context.d.ts.map +1 -0
  64. package/dist/lib/server/decisioning/context.js +26 -0
  65. package/dist/lib/server/decisioning/context.js.map +1 -0
  66. package/dist/lib/server/decisioning/errors-typed.d.ts +104 -0
  67. package/dist/lib/server/decisioning/errors-typed.d.ts.map +1 -0
  68. package/dist/lib/server/decisioning/errors-typed.js +304 -0
  69. package/dist/lib/server/decisioning/errors-typed.js.map +1 -0
  70. package/dist/lib/server/decisioning/helpers.d.ts +131 -0
  71. package/dist/lib/server/decisioning/helpers.d.ts.map +1 -0
  72. package/dist/lib/server/decisioning/helpers.js +134 -0
  73. package/dist/lib/server/decisioning/helpers.js.map +1 -0
  74. package/dist/lib/server/decisioning/index.d.ts +46 -0
  75. package/dist/lib/server/decisioning/index.d.ts.map +1 -0
  76. package/dist/lib/server/decisioning/index.js +120 -0
  77. package/dist/lib/server/decisioning/index.js.map +1 -0
  78. package/dist/lib/server/decisioning/list-helpers.d.ts +53 -0
  79. package/dist/lib/server/decisioning/list-helpers.d.ts.map +1 -0
  80. package/dist/lib/server/decisioning/list-helpers.js +96 -0
  81. package/dist/lib/server/decisioning/list-helpers.js.map +1 -0
  82. package/dist/lib/server/decisioning/manifest-helpers.d.ts +56 -0
  83. package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -0
  84. package/dist/lib/server/decisioning/manifest-helpers.js +78 -0
  85. package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -0
  86. package/dist/lib/server/decisioning/pagination.d.ts +21 -0
  87. package/dist/lib/server/decisioning/pagination.d.ts.map +1 -0
  88. package/dist/lib/server/decisioning/pagination.js +12 -0
  89. package/dist/lib/server/decisioning/pagination.js.map +1 -0
  90. package/dist/lib/server/decisioning/platform.d.ts +188 -0
  91. package/dist/lib/server/decisioning/platform.d.ts.map +1 -0
  92. package/dist/lib/server/decisioning/platform.js +19 -0
  93. package/dist/lib/server/decisioning/platform.js.map +1 -0
  94. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +510 -0
  95. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -0
  96. package/dist/lib/server/decisioning/runtime/from-platform.js +2196 -0
  97. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -0
  98. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +114 -0
  99. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -0
  100. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +247 -0
  101. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -0
  102. package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts +32 -0
  103. package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts.map +1 -0
  104. package/dist/lib/server/decisioning/runtime/protocol-for-tool.js +127 -0
  105. package/dist/lib/server/decisioning/runtime/protocol-for-tool.js.map +1 -0
  106. package/dist/lib/server/decisioning/runtime/task-registry.d.ts +105 -0
  107. package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -0
  108. package/dist/lib/server/decisioning/runtime/task-registry.js +96 -0
  109. package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -0
  110. package/dist/lib/server/decisioning/runtime/to-context.d.ts +54 -0
  111. package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -0
  112. package/dist/lib/server/decisioning/runtime/to-context.js +166 -0
  113. package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -0
  114. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts +20 -0
  115. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -0
  116. package/dist/lib/server/decisioning/runtime/validate-platform.js +93 -0
  117. package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -0
  118. package/dist/lib/server/decisioning/specialisms/audiences.d.ts +72 -0
  119. package/dist/lib/server/decisioning/specialisms/audiences.d.ts.map +1 -0
  120. package/dist/lib/server/decisioning/specialisms/audiences.js +15 -0
  121. package/dist/lib/server/decisioning/specialisms/audiences.js.map +1 -0
  122. package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts +92 -0
  123. package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts.map +1 -0
  124. package/dist/lib/server/decisioning/specialisms/brand-rights.js +28 -0
  125. package/dist/lib/server/decisioning/specialisms/brand-rights.js.map +1 -0
  126. package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts +67 -0
  127. package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts.map +1 -0
  128. package/dist/lib/server/decisioning/specialisms/campaign-governance.js +31 -0
  129. package/dist/lib/server/decisioning/specialisms/campaign-governance.js.map +1 -0
  130. package/dist/lib/server/decisioning/specialisms/content-standards.d.ts +78 -0
  131. package/dist/lib/server/decisioning/specialisms/content-standards.d.ts.map +1 -0
  132. package/dist/lib/server/decisioning/specialisms/content-standards.js +35 -0
  133. package/dist/lib/server/decisioning/specialisms/content-standards.js.map +1 -0
  134. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +81 -0
  135. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -0
  136. package/dist/lib/server/decisioning/specialisms/creative-ad-server.js +28 -0
  137. package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -0
  138. package/dist/lib/server/decisioning/specialisms/creative.d.ts +144 -0
  139. package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -0
  140. package/dist/lib/server/decisioning/specialisms/creative.js +19 -0
  141. package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -0
  142. package/dist/lib/server/decisioning/specialisms/lists.d.ts +61 -0
  143. package/dist/lib/server/decisioning/specialisms/lists.d.ts.map +1 -0
  144. package/dist/lib/server/decisioning/specialisms/lists.js +30 -0
  145. package/dist/lib/server/decisioning/specialisms/lists.js.map +1 -0
  146. package/dist/lib/server/decisioning/specialisms/sales.d.ts +163 -0
  147. package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -0
  148. package/dist/lib/server/decisioning/specialisms/sales.js +64 -0
  149. package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -0
  150. package/dist/lib/server/decisioning/specialisms/signals.d.ts +64 -0
  151. package/dist/lib/server/decisioning/specialisms/signals.d.ts.map +1 -0
  152. package/dist/lib/server/decisioning/specialisms/signals.js +28 -0
  153. package/dist/lib/server/decisioning/specialisms/signals.js.map +1 -0
  154. package/dist/lib/server/decisioning/start-time.d.ts +76 -0
  155. package/dist/lib/server/decisioning/start-time.d.ts.map +1 -0
  156. package/dist/lib/server/decisioning/start-time.js +81 -0
  157. package/dist/lib/server/decisioning/start-time.js.map +1 -0
  158. package/dist/lib/server/decisioning/status-changes.d.ts +165 -0
  159. package/dist/lib/server/decisioning/status-changes.d.ts.map +1 -0
  160. package/dist/lib/server/decisioning/status-changes.js +131 -0
  161. package/dist/lib/server/decisioning/status-changes.js.map +1 -0
  162. package/dist/lib/server/decisioning/status-mappers.d.ts +46 -0
  163. package/dist/lib/server/decisioning/status-mappers.d.ts.map +1 -0
  164. package/dist/lib/server/decisioning/status-mappers.js +46 -0
  165. package/dist/lib/server/decisioning/status-mappers.js.map +1 -0
  166. package/dist/lib/server/decisioning/tenant-registry.d.ts +289 -0
  167. package/dist/lib/server/decisioning/tenant-registry.d.ts.map +1 -0
  168. package/dist/lib/server/decisioning/tenant-registry.js +503 -0
  169. package/dist/lib/server/decisioning/tenant-registry.js.map +1 -0
  170. package/dist/lib/server/express-adapter.d.ts +1 -1
  171. package/dist/lib/server/express-adapter.js +1 -1
  172. package/dist/lib/server/governance.d.ts +1 -1
  173. package/dist/lib/server/governance.js +1 -1
  174. package/dist/lib/server/idempotency/store.d.ts +1 -1
  175. package/dist/lib/server/idempotency/store.js +1 -1
  176. package/dist/lib/server/index.d.ts +9 -2
  177. package/dist/lib/server/index.d.ts.map +1 -1
  178. package/dist/lib/server/index.js +79 -4
  179. package/dist/lib/server/index.js.map +1 -1
  180. package/dist/lib/server/legacy/v5/index.d.ts +38 -0
  181. package/dist/lib/server/legacy/v5/index.d.ts.map +1 -0
  182. package/dist/lib/server/legacy/v5/index.js +60 -0
  183. package/dist/lib/server/legacy/v5/index.js.map +1 -0
  184. package/dist/lib/server/normalize-errors.d.ts +88 -0
  185. package/dist/lib/server/normalize-errors.d.ts.map +1 -0
  186. package/dist/lib/server/normalize-errors.js +146 -0
  187. package/dist/lib/server/normalize-errors.js.map +1 -0
  188. package/dist/lib/server/pick-safe-details.d.ts +90 -0
  189. package/dist/lib/server/pick-safe-details.d.ts.map +1 -0
  190. package/dist/lib/server/pick-safe-details.js +148 -0
  191. package/dist/lib/server/pick-safe-details.js.map +1 -0
  192. package/dist/lib/server/postgres-state-store.d.ts +1 -1
  193. package/dist/lib/server/postgres-state-store.js +1 -1
  194. package/dist/lib/server/responses.d.ts +38 -0
  195. package/dist/lib/server/responses.d.ts.map +1 -1
  196. package/dist/lib/server/responses.js +38 -0
  197. package/dist/lib/server/responses.js.map +1 -1
  198. package/dist/lib/server/state-store.d.ts +1 -1
  199. package/dist/lib/server/state-store.js +1 -1
  200. package/dist/lib/server/test-controller.d.ts +10 -3
  201. package/dist/lib/server/test-controller.d.ts.map +1 -1
  202. package/dist/lib/server/test-controller.js +10 -3
  203. package/dist/lib/server/test-controller.js.map +1 -1
  204. package/dist/lib/testing/comply-controller.d.ts +47 -1
  205. package/dist/lib/testing/comply-controller.d.ts.map +1 -1
  206. package/dist/lib/testing/comply-controller.js +11 -4
  207. package/dist/lib/testing/comply-controller.js.map +1 -1
  208. package/dist/lib/testing/index.d.ts +1 -1
  209. package/dist/lib/testing/index.d.ts.map +1 -1
  210. package/dist/lib/testing/index.js.map +1 -1
  211. package/dist/lib/testing/personas/index.d.ts +143 -0
  212. package/dist/lib/testing/personas/index.d.ts.map +1 -0
  213. package/dist/lib/testing/personas/index.js +190 -0
  214. package/dist/lib/testing/personas/index.js.map +1 -0
  215. package/dist/lib/testing/storyboard/index.d.ts +1 -1
  216. package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
  217. package/dist/lib/testing/storyboard/index.js +3 -2
  218. package/dist/lib/testing/storyboard/index.js.map +1 -1
  219. package/dist/lib/testing/storyboard/runner.d.ts +13 -0
  220. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  221. package/dist/lib/testing/storyboard/runner.js +179 -7
  222. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  223. package/dist/lib/types/asset-instances.d.ts +1 -0
  224. package/dist/lib/types/asset-instances.d.ts.map +1 -1
  225. package/dist/lib/types/core.generated.d.ts +203 -98
  226. package/dist/lib/types/core.generated.d.ts.map +1 -1
  227. package/dist/lib/types/core.generated.js +1 -1
  228. package/dist/lib/types/index.d.ts +1 -0
  229. package/dist/lib/types/index.d.ts.map +1 -1
  230. package/dist/lib/types/index.js.map +1 -1
  231. package/dist/lib/types/schemas.generated.d.ts +599 -159
  232. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  233. package/dist/lib/types/schemas.generated.js +175 -94
  234. package/dist/lib/types/schemas.generated.js.map +1 -1
  235. package/dist/lib/types/tools.generated.d.ts +315 -46
  236. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  237. package/dist/lib/utils/capabilities.d.ts +1 -1
  238. package/dist/lib/utils/capabilities.d.ts.map +1 -1
  239. package/dist/lib/utils/capabilities.js +6 -0
  240. package/dist/lib/utils/capabilities.js.map +1 -1
  241. package/dist/lib/validation/schema-validator.d.ts +13 -0
  242. package/dist/lib/validation/schema-validator.d.ts.map +1 -1
  243. package/dist/lib/validation/schema-validator.js +240 -3
  244. package/dist/lib/validation/schema-validator.js.map +1 -1
  245. package/dist/lib/version.d.ts +3 -3
  246. package/dist/lib/version.d.ts.map +1 -1
  247. package/dist/lib/version.js +3 -3
  248. package/dist/lib/version.js.map +1 -1
  249. package/docs/guides/BUILD-AN-AGENT.md +30 -5
  250. package/docs/llms.txt +28 -17
  251. package/examples/README.md +3 -1
  252. package/examples/decisioning-platform-broadcast-tv.ts +300 -0
  253. package/examples/decisioning-platform-identity-graph.ts +214 -0
  254. package/examples/decisioning-platform-mock-seller.ts +332 -0
  255. package/examples/decisioning-platform-multi-tenant.ts +128 -0
  256. package/examples/decisioning-platform-programmatic.ts +254 -0
  257. package/examples/signals-agent.ts +1 -1
  258. package/package.json +13 -2
  259. package/skills/build-brand-rights-agent/SKILL.md +10 -3
  260. package/skills/build-creative-agent/SKILL.md +94 -64
  261. package/skills/build-decisioning-creative-template/SKILL.md +554 -0
  262. package/skills/build-decisioning-platform/SKILL.md +304 -0
  263. package/skills/build-decisioning-platform/advanced/BRAND-RIGHTS.md +25 -0
  264. package/skills/build-decisioning-platform/advanced/COMPLIANCE.md +23 -0
  265. package/skills/build-decisioning-platform/advanced/GOVERNANCE.md +24 -0
  266. package/skills/build-decisioning-platform/advanced/HITL.md +34 -0
  267. package/skills/build-decisioning-platform/advanced/IDEMPOTENCY.md +52 -0
  268. package/skills/build-decisioning-platform/advanced/MULTI-TENANT.md +47 -0
  269. package/skills/build-decisioning-platform/advanced/OAUTH.md +22 -0
  270. package/skills/build-decisioning-platform/advanced/REFERENCE.md +991 -0
  271. package/skills/build-decisioning-platform/advanced/SANDBOX.md +24 -0
  272. package/skills/build-decisioning-platform/advanced/STATE-MACHINE.md +52 -0
  273. package/skills/build-decisioning-signal-marketplace/SKILL.md +269 -0
  274. package/skills/build-generative-seller-agent/SKILL.md +89 -53
  275. package/skills/build-governance-agent/SKILL.md +76 -45
  276. package/skills/build-retail-media-agent/SKILL.md +87 -62
  277. package/skills/build-seller-agent/SKILL.md +384 -255
  278. package/skills/build-seller-agent/deployment.md +5 -3
  279. package/skills/build-seller-agent/specialisms/audience-sync.md +0 -2
  280. package/skills/build-seller-agent/specialisms/sales-broadcast-tv.md +0 -2
  281. package/skills/build-seller-agent/specialisms/sales-guaranteed.md +0 -2
  282. package/skills/build-seller-agent/specialisms/sales-non-guaranteed.md +0 -2
  283. package/skills/build-seller-agent/specialisms/sales-proposal-mode.md +0 -2
  284. package/skills/build-seller-agent/specialisms/sales-social.md +0 -2
  285. package/skills/build-seller-agent/specialisms/signed-requests.md +0 -2
  286. package/skills/build-si-agent/SKILL.md +40 -32
  287. package/skills/build-signals-agent/SKILL.md +139 -92
  288. package/skills/call-adcp-agent.previous/SKILL.md +5 -0
package/docs/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  # Ad Context Protocol (AdCP)
2
2
 
3
- > Generated at: 2026-04-28
4
- > Library: @adcp/sdk v5.21.1
3
+ > Generated at: 2026-04-30
4
+ > Library: @adcp/sdk v5.25.1
5
5
  > AdCP major version: 3
6
6
  > Canonical URL: https://adcontextprotocol.github.io/adcp-client/llms.txt
7
7
 
@@ -12,25 +12,36 @@ AdCP is an open protocol for AI agents to buy, manage, and optimize advertising
12
12
  ## Are you building a client or a server?
13
13
 
14
14
  - **Client** (calling existing agents): Continue reading — the Quick Start below is for you.
15
- - **Server** (implementing an agent that others call): Read `docs/guides/BUILD-AN-AGENT.md` instead. Minimal example:
15
+ - **Server** (implementing an agent that others call): Read `docs/guides/BUILD-AN-AGENT.md` and `docs/migration-5.x-to-6.x.md`. v6 recommended path:
16
16
 
17
17
  ```typescript
18
- import { createTaskCapableServer, taskToolResponse, serve, GetSignalsRequestSchema } from '@adcp/sdk';
19
-
20
- function createAgent({ taskStore }) {
21
- const server = createTaskCapableServer('My Agent', '1.0.0', { taskStore });
22
- server.registerTool(
23
- 'get_signals',
24
- { description: 'Discover segments.', inputSchema: GetSignalsRequestSchema.shape },
25
- async (args) => taskToolResponse({ signals: [...], sandbox: true }, 'Found segments')
26
- );
27
- return server;
28
- }
29
-
30
- serve(createAgent); // http://localhost:3001/mcp
18
+ import { serve } from '@adcp/sdk';
19
+ import { createAdcpServerFromPlatform } from '@adcp/sdk/server';
20
+
21
+ const platform = {
22
+ capabilities: {
23
+ specialisms: ['signal-marketplace'] as const,
24
+ creative_agents: [], channels: [], pricingModels: ['cpm'] as const, config: {},
25
+ },
26
+ statusMappers: {},
27
+ accounts: {
28
+ resolve: async () => ({ id: 'acc_1', ctx_metadata: {}, authInfo: { kind: 'api_key' } }),
29
+ },
30
+ signals: {
31
+ getSignals: async (req, ctx) => ({ signals: [/* ... */], sandbox: true }),
32
+ activateSignal: async (req, ctx) => ({ /* ... */ }),
33
+ },
34
+ };
35
+
36
+ serve(() => createAdcpServerFromPlatform(platform, {
37
+ name: 'My Signals Agent',
38
+ version: '1.0.0',
39
+ })); // http://localhost:3001/mcp
31
40
  ```
32
41
 
33
- Low-level server (bypassing `createAdcpServer`)? Use `wrapEnvelope(inner, { replayed, context, operationId })` from `@adcp/sdk/server` to attach protocol envelope fields with the per-error-code allowlist applied (IDEMPOTENCY_CONFLICT drops `replayed`).
42
+ Compile-time enforcement: `RequiredPlatformsFor<S>` catches missing specialism methods. Capability projection auto-derives `get_adcp_capabilities` blocks (`audience_targeting`, `conversion_tracking`, `compliance_testing.scenarios`, etc.). Idempotency, RFC 9421 signing, async tasks, status normalization, and sync-completion webhook auto-emit are framework-owned.
43
+
44
+ Lower-level option: `createAdcpServer({ signals: { getSignals: ... } })` from `@adcp/sdk/server/legacy/v5` — handler-bag API. Still fully supported, the substrate the platform path calls into. Use when you need fine control over individual handlers, mid-migration from a v5 codebase, or custom-shaped tools the platform interface doesn't yet model. `wrapEnvelope(inner, { replayed, context, operationId })` from `@adcp/sdk/server` attaches protocol envelope fields with the per-error-code allowlist (IDEMPOTENCY_CONFLICT drops `replayed`).
34
45
 
35
46
  ## Quick Start (Client)
36
47
 
@@ -54,7 +54,9 @@ ADCP_AGENTS_CONFIG='[{"id":"test-agent","name":"Test Agent","agent_uri":"https:/
54
54
  ```typescript
55
55
  import { ADCPMultiAgentClient, type AgentConfig } from '@adcp/sdk';
56
56
 
57
- const agents: AgentConfig[] = [/* your agents */];
57
+ const agents: AgentConfig[] = [
58
+ /* your agents */
59
+ ];
58
60
  const client = new ADCPMultiAgentClient(agents);
59
61
 
60
62
  // Single agent operation
@@ -0,0 +1,300 @@
1
+ /**
2
+ * BroadcastTvSeller — worked example for `sales-broadcast-tv`.
3
+ *
4
+ * Broadcast linear TV is the canonical HITL case: a media buy isn't real
5
+ * until the trafficker confirms inventory holds and the plan clears
6
+ * standards & practices. Buyers don't get a `media_buy_id` until the
7
+ * trafficker accepts; the unified hybrid shape projects this directly:
8
+ *
9
+ * - `getProducts` — sync catalog read of the affiliate's standing
10
+ * inventory packages (no trafficker review for catalog reads). Brief-
11
+ * based proposal generation is a separate verb (`request_proposal`,
12
+ * adcp#3407) and rides on a status-change channel, not on
13
+ * `get_products`.
14
+ * - `createMediaBuy(req, ctx)` — returns `ctx.handoffToTask(fn)` for
15
+ * trafficker review + IO sign-off (hours to days). The handoff fn
16
+ * does the actual work and returns the wire `Success` arm when the
17
+ * trafficker accepts; `throw AdcpError` becomes the terminal error.
18
+ * - `syncCreatives(creatives, ctx)` — returns `ctx.handoffToTask(fn)`
19
+ * for the standards-and-practices review (24-48 hour SLA in
20
+ * production; demo uses `standardsReviewMs`).
21
+ *
22
+ * Lifecycle changes after acceptance (plan goes from `pending_start` →
23
+ * `active` → `completed` over the campaign window) flow via
24
+ * `publishStatusChange`.
25
+ *
26
+ * @see `skills/build-decisioning-platform/SKILL.md`
27
+ */
28
+
29
+ import {
30
+ AdcpError,
31
+ publishStatusChange,
32
+ type DecisioningPlatform,
33
+ type SalesPlatform,
34
+ type AccountStore,
35
+ type SyncCreativesRow,
36
+ } from '@adcp/sdk/server';
37
+ import type {
38
+ GetProductsRequest,
39
+ GetProductsResponse,
40
+ CreateMediaBuyRequest,
41
+ CreateMediaBuySuccess,
42
+ UpdateMediaBuyRequest,
43
+ UpdateMediaBuySuccess,
44
+ GetMediaBuyDeliveryRequest,
45
+ GetMediaBuyDeliveryResponse,
46
+ CreativeAsset,
47
+ AccountReference,
48
+ } from '@adcp/sdk/types';
49
+
50
+ // ---------------------------------------------------------------------------
51
+ // BroadcastTvSeller config + state
52
+ // ---------------------------------------------------------------------------
53
+
54
+ export interface BroadcastTvConfig {
55
+ /** Affiliate the trafficker IO desk maps to (e.g., 'WCBS'). */
56
+ affiliateId: string;
57
+ /** Simulated trafficker review duration (ms). */
58
+ trafficReviewMs: number;
59
+ /** Simulated S&P review duration (ms). */
60
+ standardsReviewMs: number;
61
+ /** Day-of-week and hour the schedule "activates" relative to start_time. */
62
+ activationOffsetMs: number;
63
+ }
64
+
65
+ interface BroadcastTvMeta {
66
+ agency_buyer_id: string;
67
+ affiliate_advertiser_id: string;
68
+ [key: string]: unknown;
69
+ }
70
+
71
+ type BroadcastBuy = CreateMediaBuySuccess & { daypart?: string };
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Implementation
75
+ // ---------------------------------------------------------------------------
76
+
77
+ export class BroadcastTvSeller implements DecisioningPlatform<BroadcastTvConfig, BroadcastTvMeta> {
78
+ private mediaBuys = new Map<string, BroadcastBuy>();
79
+
80
+ capabilities = {
81
+ specialisms: ['sales-broadcast-tv'] as const,
82
+ creative_agents: [{ agent_url: 'https://example.com/broadcast-creative-agent/mcp' }],
83
+ channels: ['linear_tv'] as const,
84
+ pricingModels: ['cpm'] as const,
85
+ config: {
86
+ affiliateId: 'WCBS',
87
+ trafficReviewMs: 100,
88
+ standardsReviewMs: 80,
89
+ activationOffsetMs: 50,
90
+ } satisfies BroadcastTvConfig,
91
+ };
92
+
93
+ statusMappers = {};
94
+
95
+ accounts: AccountStore<BroadcastTvMeta> = {
96
+ resolve: async (ref: AccountReference) => {
97
+ const id = 'account_id' in ref ? ref.account_id : 'broadcast_acc_1';
98
+ return {
99
+ id,
100
+ name: `Broadcast TV — ${id}`,
101
+ status: 'active',
102
+ operator: 'broadcast.example.com',
103
+ ctx_metadata: { agency_buyer_id: 'agc_42', affiliate_advertiser_id: 'aff_99' },
104
+ authInfo: { kind: 'api_key' },
105
+ };
106
+ },
107
+ };
108
+
109
+ sales: SalesPlatform<BroadcastTvMeta> = {
110
+ /**
111
+ * Sync catalog read. Returns the affiliate's standing packages —
112
+ * primetime daypart, sports tentpoles, etc. Brief-based proposal
113
+ * generation is a separate verb the spec is consolidating
114
+ * (adcp#3407 `request_proposal`); proposal-mode adopters surface
115
+ * the eventual products via `publishStatusChange` on
116
+ * `resource_type: 'proposal'`.
117
+ */
118
+ getProducts: async (req: GetProductsRequest): Promise<GetProductsResponse> => {
119
+ const promotedOffering = (req as { promoted_offering?: string }).promoted_offering ?? '';
120
+ if (/political|cannabis|gambling/i.test(promotedOffering)) {
121
+ throw new AdcpError('POLICY_VIOLATION', {
122
+ recovery: 'terminal',
123
+ message: 'Affiliate does not carry this category under FCC + station policy',
124
+ field: 'promoted_offering',
125
+ details: { affiliate: this.capabilities.config.affiliateId },
126
+ });
127
+ }
128
+
129
+ return {
130
+ products: [
131
+ {
132
+ product_id: 'prod_primetime_30s',
133
+ name: 'Primetime 30s — M-F 8-11pm',
134
+ description: 'Local broadcast primetime, :30 spots',
135
+ format_ids: [{ id: 'video_30s', agent_url: 'https://example.com/broadcast-creative-agent/mcp' }],
136
+ delivery_type: 'guaranteed',
137
+ publisher_properties: [{ publisher_domain: 'broadcast.example.com', selection_type: 'all' }],
138
+ reporting_capabilities: {
139
+ available_reporting_frequencies: ['daily'],
140
+ expected_delay_minutes: 240,
141
+ timezone: 'UTC',
142
+ supports_webhooks: false,
143
+ available_metrics: [],
144
+ date_range_support: 'date_range',
145
+ },
146
+ pricing_options: [
147
+ {
148
+ pricing_option_id: 'cpm_42_00',
149
+ pricing_model: 'cpm',
150
+ fixed_price: 42.0,
151
+ currency: 'USD',
152
+ min_spend_per_package: 5_000,
153
+ },
154
+ ],
155
+ },
156
+ ],
157
+ };
158
+ },
159
+
160
+ /**
161
+ * Hybrid HITL: trafficker review + IO sign-off. Buyer sees `submitted`
162
+ * envelope with `task_id` immediately; the framework runs the handoff
163
+ * fn in background. Trafficker accepts → handoff returns the wire
164
+ * `Success` arm with `media_buy_id`; trafficker rejects → handoff
165
+ * throws `AdcpError`, framework surfaces terminal error.
166
+ *
167
+ * Pre-flight runs sync (rejects bad budgets before allocating a task
168
+ * id). Lifecycle after acceptance flows via `publishStatusChange`.
169
+ */
170
+ createMediaBuy: (req, ctx) => {
171
+ // Pre-flight runs sync regardless of path
172
+ const errors = this.preflight(req);
173
+ if (errors.length > 0) {
174
+ throw new AdcpError('INVALID_REQUEST', {
175
+ recovery: 'correctable',
176
+ message: errors[0]!.message,
177
+ field: errors[0]!.field,
178
+ details: { errors },
179
+ });
180
+ }
181
+
182
+ return Promise.resolve(
183
+ ctx.handoffToTask(async taskCtx => {
184
+ void taskCtx; // taskCtx.id available if you need to log it
185
+ // Trafficker review window
186
+ await new Promise(r => setTimeout(r, this.capabilities.config.trafficReviewMs));
187
+
188
+ const buyId = `mb_${this.capabilities.config.affiliateId}_${Date.now()}`;
189
+ const buy: BroadcastBuy = {
190
+ media_buy_id: buyId,
191
+ status: 'pending_start',
192
+ confirmed_at: new Date().toISOString(),
193
+ revision: 1,
194
+ daypart: 'primetime',
195
+ packages: [],
196
+ };
197
+ this.mediaBuys.set(buyId, buy);
198
+
199
+ // After acceptance, the broadcast traffic system controls the
200
+ // campaign window. Schedule the post-acceptance status-change.
201
+ const account = (req as { account?: { account_id?: string } }).account;
202
+ const accountId = account?.account_id ?? 'broadcast_acc_1';
203
+ setTimeout(() => {
204
+ buy.status = 'active';
205
+ publishStatusChange({
206
+ account_id: accountId,
207
+ resource_type: 'media_buy',
208
+ resource_id: buyId,
209
+ payload: { status: 'active', activated_at: new Date().toISOString() },
210
+ });
211
+ }, this.capabilities.config.activationOffsetMs).unref?.();
212
+
213
+ return buy;
214
+ })
215
+ );
216
+ },
217
+
218
+ updateMediaBuy: async (buyId: string, patch: UpdateMediaBuyRequest): Promise<UpdateMediaBuySuccess> => {
219
+ const existing = this.mediaBuys.get(buyId);
220
+ if (!existing) {
221
+ throw new AdcpError('MEDIA_BUY_NOT_FOUND', {
222
+ recovery: 'terminal',
223
+ message: `media buy ${buyId} not found`,
224
+ field: 'media_buy_id',
225
+ });
226
+ }
227
+ // Broadcast: pause = preempt the schedule; canceled is irreversible
228
+ // (cannot reactivate without a fresh IO).
229
+ if (patch.paused === true) existing.status = 'paused';
230
+ if (patch.paused === false && existing.status === 'paused') existing.status = 'active';
231
+ return { media_buy_id: existing.media_buy_id, status: existing.status, revision: existing.revision };
232
+ },
233
+
234
+ /**
235
+ * Hybrid HITL S&P review: every spot goes through standards-and-
236
+ * practices before it can air. 24-48 hour SLA in production. Returns
237
+ * `ctx.handoffToTask(fn)` so the buyer sees the submitted envelope
238
+ * immediately and the review runs in background.
239
+ */
240
+ syncCreatives: (creatives, ctx) =>
241
+ Promise.resolve(
242
+ ctx.handoffToTask(async taskCtx => {
243
+ void taskCtx;
244
+ await new Promise(r => setTimeout(r, this.capabilities.config.standardsReviewMs));
245
+ // Mock policy: anything tagged "political" rejects; rest approve.
246
+ return creatives.map(c => {
247
+ const id = (c as { creative_id?: string }).creative_id ?? `cr_${Math.random()}`;
248
+ const tags = ((c as { tags?: string[] }).tags ?? []).map(t => t.toLowerCase());
249
+ if (tags.includes('political')) {
250
+ return {
251
+ creative_id: id,
252
+ action: 'failed',
253
+ status: 'rejected',
254
+ errors: [
255
+ {
256
+ code: 'CREATIVE_REJECTED',
257
+ message: 'Political ads require FCC disclosure file + station GM sign-off',
258
+ },
259
+ ],
260
+ } satisfies SyncCreativesRow;
261
+ }
262
+ return { creative_id: id, action: 'created', status: 'approved' } satisfies SyncCreativesRow;
263
+ });
264
+ })
265
+ ),
266
+
267
+ getMediaBuyDelivery: async (filter: GetMediaBuyDeliveryRequest): Promise<GetMediaBuyDeliveryResponse> => {
268
+ return {
269
+ currency: 'USD',
270
+ reporting_period: {
271
+ start: filter.start_date ?? '2026-04-01',
272
+ end: filter.end_date ?? '2026-04-30',
273
+ },
274
+ media_buy_deliveries: [],
275
+ };
276
+ },
277
+
278
+ // Required on SalesPlatform — write-only adopters return an empty array.
279
+ // This affiliate doesn't enumerate buys via this surface (push-channel
280
+ // delivery via webhooks); the empty array is truthful.
281
+ getMediaBuys: async () => ({ media_buys: [] }),
282
+ };
283
+
284
+ private preflight(req: CreateMediaBuyRequest): { code: string; recovery: string; message: string; field: string }[] {
285
+ const errors = [];
286
+ const totalBudget =
287
+ typeof req.total_budget === 'number'
288
+ ? req.total_budget
289
+ : ((req.total_budget as { amount?: number })?.amount ?? 0);
290
+ if (totalBudget < 5_000) {
291
+ errors.push({
292
+ code: 'BUDGET_TOO_LOW',
293
+ recovery: 'correctable',
294
+ message: 'Broadcast minimum is $5,000 per IO',
295
+ field: 'total_budget',
296
+ });
297
+ }
298
+ return errors;
299
+ }
300
+ }
@@ -0,0 +1,214 @@
1
+ /**
2
+ * IdentityGraphProvider — worked example for `audience-sync`.
3
+ *
4
+ * Identity-graph providers (the category covers vendors like LiveRamp,
5
+ * Oracle Data Cloud, Salesforce CDP, Neustar) have a long-tail
6
+ * activation pipeline: ingest → match → activate to destinations. Match
7
+ * takes 5-30 minutes; activation per destination takes hours. Buyers
8
+ * can't usefully wait synchronously, but they DO want immediate
9
+ * confirmation that the audience was accepted and to know when it's
10
+ * ready.
11
+ *
12
+ * This sample is generic — no real provider's API or branding is
13
+ * implied; the latencies and stages are illustrative. The shape adapters
14
+ * use is:
15
+ *
16
+ * - Sync `syncAudiences` returns per-audience rows with the *current*
17
+ * wire status (`processing` is fine — the buyer's audience_id is
18
+ * now known and they can subscribe for updates).
19
+ * - `publishStatusChange({ resource_type: 'audience', ... })` fires from
20
+ * the match-pipeline + activation-pipeline as each audience reaches
21
+ * internal stages `matched` → `activating` → `active`.
22
+ *
23
+ * `AdcpError` for buyer-fixable rejection (`REFERENCE_NOT_FOUND`,
24
+ * insufficient identifiers, etc.).
25
+ *
26
+ * @see `skills/build-decisioning-platform/SKILL.md`
27
+ */
28
+
29
+ import { publishStatusChange, type DecisioningPlatform, type AccountStore } from '@adcp/sdk/server';
30
+ import type { AudiencePlatform, Audience, AudienceStatus, SyncAudiencesRow } from '@adcp/sdk/server';
31
+ import type { AccountReference } from '@adcp/sdk/types';
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Config + state
35
+ // ---------------------------------------------------------------------------
36
+
37
+ export interface IdentityGraphConfig {
38
+ /** Minimum identifier count before activation; audiences below this reject. */
39
+ minIdentifiers: number;
40
+ /** Identity-graph match latency (ms). */
41
+ matchLatencyMs: number;
42
+ /** Per-destination activation latency (ms). */
43
+ activationLatencyMs: number;
44
+ /** Default match rate the demo simulates. */
45
+ defaultMatchRate: number;
46
+ }
47
+
48
+ interface IdentityGraphMeta {
49
+ graph_id: string;
50
+ [key: string]: unknown;
51
+ }
52
+
53
+ /**
54
+ * Internal lifecycle stages — richer than the wire `AudienceStatus` enum
55
+ * (`'processing' | 'ready' | 'too_small'`). The internal stages flow
56
+ * through `publishStatusChange.payload` (freeform JSON) so buyers
57
+ * subscribed to the bus see `matched_count`, `match_rate`, and the
58
+ * stage transitions. The wire-shaped `pollAudienceStatuses` collapses
59
+ * back to the spec enum.
60
+ */
61
+ type IdentityGraphStage = 'matching' | 'matched' | 'activating' | 'active' | 'failed';
62
+
63
+ function toWireStatus(stage: IdentityGraphStage): AudienceStatus {
64
+ switch (stage) {
65
+ case 'active':
66
+ return 'ready';
67
+ case 'failed':
68
+ return 'too_small';
69
+ default:
70
+ return 'processing';
71
+ }
72
+ }
73
+
74
+ type AudienceState = {
75
+ audience_id: string;
76
+ stage: IdentityGraphStage;
77
+ matched_count?: number;
78
+ match_rate?: number;
79
+ };
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // Implementation
83
+ // ---------------------------------------------------------------------------
84
+
85
+ export class IdentityGraphProvider implements DecisioningPlatform<IdentityGraphConfig, IdentityGraphMeta> {
86
+ private audienceState = new Map<string, AudienceState>();
87
+
88
+ capabilities = {
89
+ specialisms: ['audience-sync'] as const,
90
+ creative_agents: [],
91
+ channels: [] as const,
92
+ pricingModels: ['cpm'] as const,
93
+ config: {
94
+ minIdentifiers: 100,
95
+ matchLatencyMs: 60,
96
+ activationLatencyMs: 80,
97
+ defaultMatchRate: 0.42,
98
+ } satisfies IdentityGraphConfig,
99
+ };
100
+
101
+ statusMappers = {};
102
+
103
+ accounts: AccountStore<IdentityGraphMeta> = {
104
+ resolve: async (ref: AccountReference) => {
105
+ const id = 'account_id' in ref ? ref.account_id : 'idg_acc_1';
106
+ return {
107
+ id,
108
+ name: `IdentityGraph — ${id}`,
109
+ status: 'active',
110
+ operator: 'identity-graph.example.com',
111
+ ctx_metadata: { graph_id: 'IG-12345' },
112
+ authInfo: { kind: 'api_key' },
113
+ };
114
+ },
115
+ };
116
+
117
+ audiences: AudiencePlatform<IdentityGraphMeta> = {
118
+ /**
119
+ * Sync acknowledgment: return current state for each audience. Match
120
+ * pipeline + activation pipeline run in background and emit
121
+ * publishStatusChange events as each audience progresses through the
122
+ * richer internal stages (`matching` → `matched` → `activating` →
123
+ * `active`). Buyers subscribed to the status-change bus see the full
124
+ * lifecycle; buyers polling `pollAudienceStatuses` see the wire-flat
125
+ * `processing | ready | too_small`.
126
+ */
127
+ syncAudiences: async (audiences: Audience[]): Promise<SyncAudiencesRow[]> => {
128
+ const results: SyncAudiencesRow[] = [];
129
+ const accountId = 'idg_acc_1';
130
+
131
+ for (const aud of audiences) {
132
+ const audienceId = (aud as { audience_id?: string }).audience_id ?? `aud_${Math.random()}`;
133
+ const identifiers = ((aud as { identifiers?: unknown[] }).identifiers ?? []) as unknown[];
134
+
135
+ if (identifiers.length < this.capabilities.config.minIdentifiers) {
136
+ this.audienceState.set(audienceId, { audience_id: audienceId, stage: 'failed' });
137
+ results.push({
138
+ audience_id: audienceId,
139
+ action: 'failed',
140
+ status: 'too_small',
141
+ });
142
+ continue;
143
+ }
144
+
145
+ const isUpdate = this.audienceState.has(audienceId);
146
+ const initial: AudienceState = { audience_id: audienceId, stage: 'matching' };
147
+ this.audienceState.set(audienceId, initial);
148
+
149
+ // Schedule match → matched
150
+ setTimeout(() => {
151
+ const matched = Math.floor(identifiers.length * this.capabilities.config.defaultMatchRate);
152
+ const next: AudienceState = {
153
+ audience_id: audienceId,
154
+ stage: 'matched',
155
+ matched_count: matched,
156
+ match_rate: this.capabilities.config.defaultMatchRate,
157
+ };
158
+ this.audienceState.set(audienceId, next);
159
+ publishStatusChange({
160
+ account_id: accountId,
161
+ resource_type: 'audience',
162
+ resource_id: audienceId,
163
+ payload: {
164
+ stage: 'matched',
165
+ status: 'processing',
166
+ matched_count: matched,
167
+ match_rate: this.capabilities.config.defaultMatchRate,
168
+ },
169
+ });
170
+
171
+ // Schedule matched → activating → active
172
+ setTimeout(() => {
173
+ this.audienceState.set(audienceId, { ...next, stage: 'activating' });
174
+ publishStatusChange({
175
+ account_id: accountId,
176
+ resource_type: 'audience',
177
+ resource_id: audienceId,
178
+ payload: { stage: 'activating', status: 'processing' },
179
+ });
180
+
181
+ setTimeout(() => {
182
+ this.audienceState.set(audienceId, { ...next, stage: 'active' });
183
+ publishStatusChange({
184
+ account_id: accountId,
185
+ resource_type: 'audience',
186
+ resource_id: audienceId,
187
+ payload: { stage: 'active', status: 'ready' },
188
+ });
189
+ }, this.capabilities.config.activationLatencyMs).unref?.();
190
+ }, 10).unref?.();
191
+ }, this.capabilities.config.matchLatencyMs).unref?.();
192
+
193
+ results.push({
194
+ audience_id: audienceId,
195
+ action: isUpdate ? 'updated' : 'created',
196
+ status: 'processing',
197
+ matched_count: 0,
198
+ effective_match_rate: 0,
199
+ });
200
+ }
201
+
202
+ return results;
203
+ },
204
+
205
+ pollAudienceStatuses: async (audienceIds): Promise<Map<string, AudienceStatus>> => {
206
+ const out = new Map<string, AudienceStatus>();
207
+ for (const audienceId of audienceIds) {
208
+ const state = this.audienceState.get(audienceId);
209
+ if (state) out.set(audienceId, toWireStatus(state.stage));
210
+ }
211
+ return out;
212
+ },
213
+ };
214
+ }