@adcp/client 0.2.4 → 0.4.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 (40) hide show
  1. package/README.md +362 -166
  2. package/dist/lib/agents/index.generated.d.ts +1 -21
  3. package/dist/lib/agents/index.generated.d.ts.map +1 -1
  4. package/dist/lib/agents/index.generated.js +0 -28
  5. package/dist/lib/agents/index.generated.js.map +1 -1
  6. package/dist/lib/core/ADCPClient.d.ts +66 -0
  7. package/dist/lib/core/ADCPClient.d.ts.map +1 -1
  8. package/dist/lib/core/ADCPClient.js +160 -11
  9. package/dist/lib/core/ADCPClient.js.map +1 -1
  10. package/dist/lib/core/AgentClient.d.ts +16 -0
  11. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  12. package/dist/lib/core/AgentClient.js +20 -0
  13. package/dist/lib/core/AgentClient.js.map +1 -1
  14. package/dist/lib/core/AsyncHandler.d.ts +137 -0
  15. package/dist/lib/core/AsyncHandler.d.ts.map +1 -0
  16. package/dist/lib/core/AsyncHandler.js +133 -0
  17. package/dist/lib/core/AsyncHandler.js.map +1 -0
  18. package/dist/lib/core/ResponseValidator.d.ts +60 -0
  19. package/dist/lib/core/ResponseValidator.d.ts.map +1 -0
  20. package/dist/lib/core/ResponseValidator.js +250 -0
  21. package/dist/lib/core/ResponseValidator.js.map +1 -0
  22. package/dist/lib/core/TaskEventTypes.d.ts +220 -0
  23. package/dist/lib/core/TaskEventTypes.d.ts.map +1 -0
  24. package/dist/lib/core/TaskEventTypes.js +80 -0
  25. package/dist/lib/core/TaskEventTypes.js.map +1 -0
  26. package/dist/lib/core/TaskExecutor.d.ts +7 -1
  27. package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
  28. package/dist/lib/core/TaskExecutor.js +50 -4
  29. package/dist/lib/core/TaskExecutor.js.map +1 -1
  30. package/dist/lib/index.d.ts +5 -0
  31. package/dist/lib/index.d.ts.map +1 -1
  32. package/dist/lib/index.js +9 -1
  33. package/dist/lib/index.js.map +1 -1
  34. package/dist/lib/types/core.generated.d.ts +2 -18
  35. package/dist/lib/types/core.generated.d.ts.map +1 -1
  36. package/dist/lib/types/core.generated.js +1 -1
  37. package/dist/lib/types/tools.generated.d.ts +2 -215
  38. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  39. package/dist/lib/types/tools.generated.js.map +1 -1
  40. package/package.json +5 -3
package/README.md CHANGED
@@ -3,9 +3,18 @@
3
3
  [![npm version](https://badge.fury.io/js/@adcp%2Fclient.svg)](https://badge.fury.io/js/@adcp%2Fclient)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
6
- [![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://your-org.github.io/adcp-client/)
7
6
 
8
- Official TypeScript/JavaScript client for the **Ad Context Protocol (AdCP)**. Seamlessly communicate with advertising agents using MCP and A2A protocols.
7
+ Official TypeScript/JavaScript client for the **Ad Context Protocol (AdCP)**. Build distributed advertising operations that work synchronously OR asynchronously with the same code.
8
+
9
+ ## The Core Concept
10
+
11
+ AdCP operations are **distributed and asynchronous by default**. An agent might:
12
+ - Complete your request **immediately** (synchronous)
13
+ - Need time to process and **send results via webhook** (asynchronous)
14
+ - Ask for **clarifications** before proceeding
15
+ - Send periodic **status updates** as work progresses
16
+
17
+ **Your code stays the same.** You write handlers once, and they work for both sync completions and webhook deliveries.
9
18
 
10
19
  ## Installation
11
20
 
@@ -13,239 +22,426 @@ Official TypeScript/JavaScript client for the **Ad Context Protocol (AdCP)**. Se
13
22
  npm install @adcp/client
14
23
  ```
15
24
 
16
- ### Requirements
17
-
18
- - **Node.js**: Version 18.0.0 or higher (specified in `.nvmrc`)
19
- - **TypeScript**: 5.3.0+ for full type safety
20
- - **Peer Dependencies**: `@a2a-js/sdk` and `@modelcontextprotocol/sdk`
21
-
22
- ## Quick Start
25
+ ## Quick Start: Distributed Operations
23
26
 
24
27
  ```typescript
25
28
  import { ADCPMultiAgentClient } from '@adcp/client';
26
29
 
27
- // Multi-agent setup with type safety
28
- const client = new ADCPMultiAgentClient([{
29
- id: 'premium-agent',
30
- name: 'Premium Ad Agent',
31
- agent_uri: 'https://agent.example.com/mcp/',
32
- protocol: 'mcp',
33
- auth_token_env: 'PREMIUM_AGENT_TOKEN' // Secure: references environment variable
34
- }]);
35
-
36
- const agent = client.agent('premium-agent');
37
-
38
- // ✅ TYPE-SAFE: Full IntelliSense and compile-time checking
39
- const result = await agent.getProducts({
40
- brief: 'Looking for premium coffee advertising',
41
- promoted_offering: 'Artisan coffee blends'
30
+ // Configure agents and handlers
31
+ const client = new ADCPMultiAgentClient([
32
+ {
33
+ id: 'agent_x',
34
+ agent_uri: 'https://agent-x.com',
35
+ protocol: 'a2a'
36
+ },
37
+ {
38
+ id: 'agent_y',
39
+ agent_uri: 'https://agent-y.com/mcp/',
40
+ protocol: 'mcp'
41
+ }
42
+ ], {
43
+ // Webhook URL template (macros: {agent_id}, {task_type}, {operation_id})
44
+ webhookUrlTemplate: 'https://myapp.com/webhook/{task_type}/{agent_id}/{operation_id}',
45
+
46
+ // Activity callback - fires for ALL events (requests, responses, status changes, webhooks)
47
+ onActivity: (activity) => {
48
+ console.log(`[${activity.type}] ${activity.task_type} - ${activity.operation_id}`);
49
+ // Log to monitoring, update UI, etc.
50
+ },
51
+
52
+ // Status change handlers - called for ALL status changes (completed, failed, needs_input, working, etc)
53
+ handlers: {
54
+ onGetProductsStatusChange: (response, metadata) => {
55
+ // Called for sync completion, async webhook, AND status changes
56
+ console.log(`[${metadata.status}] Got products for ${metadata.operation_id}`);
57
+
58
+ if (metadata.status === 'completed') {
59
+ db.saveProducts(metadata.operation_id, response.products);
60
+ } else if (metadata.status === 'failed') {
61
+ db.markFailed(metadata.operation_id, metadata.error);
62
+ } else if (metadata.status === 'needs_input') {
63
+ // Handle clarification needed
64
+ console.log('Needs input:', response.message);
65
+ }
66
+ }
67
+ }
42
68
  });
43
- // result is TaskResult<GetProductsResponse> with known properties
44
69
 
45
- if (result.success) {
46
- console.log('Products:', result.data.products); // Fully typed!
47
- } else {
48
- console.error('Error:', result.error);
70
+ // Execute operation - library handles operation IDs, webhook URLs, context management
71
+ const agent = client.agent('agent_x');
72
+ const result = await agent.getProducts({ brief: 'Coffee brands' });
73
+
74
+ // onActivity fired: protocol_request
75
+ // onActivity fired: protocol_response
76
+
77
+ // Check result
78
+ if (result.status === 'completed') {
79
+ // Agent completed synchronously!
80
+ console.log('✅ Sync completion:', result.data.products.length, 'products');
81
+ // onGetProductsStatusChange handler ALREADY fired with status='completed' ✓
82
+ }
83
+
84
+ if (result.status === 'submitted') {
85
+ // Agent will send webhook when complete
86
+ console.log('⏳ Async - webhook registered at:', result.submitted?.webhookUrl);
87
+ // onGetProductsStatusChange handler will fire when webhook arrives ✓
49
88
  }
50
89
  ```
51
90
 
52
- ## 🔧 Easy Configuration
91
+ ### Handling Clarifications (needs_input)
53
92
 
54
- ### Environment-based Setup (Recommended)
55
- Set your agent configuration once and auto-discover everywhere:
93
+ When an agent needs more information, you can continue the conversation:
56
94
 
57
- ```bash
58
- # .env file - NEVER commit real tokens to version control
59
- ADCP_AGENTS='[{"id":"agent1","name":"My Agent","agent_uri":"https://agent.example.com","protocol":"mcp","auth_token_env":"MY_AGENT_TOKEN"}]'
60
- MY_AGENT_TOKEN=your_actual_token_here
95
+ ```typescript
96
+ const result = await agent.getProducts({ brief: 'Coffee brands' });
97
+
98
+ if (result.status === 'needs_input') {
99
+ console.log('❓ Agent needs clarification:', result.needs_input?.message);
100
+ // onActivity fired: status_change (needs_input)
101
+
102
+ // Continue the conversation with the same agent
103
+ const refined = await agent.continueConversation('Only premium brands above $50');
104
+ // onActivity fired: protocol_request
105
+ // onActivity fired: protocol_response
106
+
107
+ if (refined.status === 'completed') {
108
+ console.log('✅ Got refined results:', refined.data.products.length);
109
+ // onGetProductsStatusChange handler fired ✓
110
+ }
111
+ }
61
112
  ```
62
113
 
63
- **Security Best Practices:**
64
- - Use `auth_token_env` to reference environment variables instead of hardcoding tokens
65
- - Add `.env` files to `.gitignore`
66
- - Rotate tokens regularly
67
- - Use different tokens for different environments
114
+ ## Webhook Pattern
115
+
116
+ All webhooks (task completions AND notifications) use one endpoint with flexible URL templates.
117
+
118
+ ### Configure Your Webhook URL Structure
68
119
 
69
120
  ```typescript
70
- // Auto-discover agents from environment
71
- const client = ADCPMultiAgentClient.fromEnv();
72
- console.log(`Found ${client.agentCount} agents`); // Auto-discovered!
121
+ const client = new ADCPMultiAgentClient(agents, {
122
+ // Path-based (default pattern)
123
+ webhookUrlTemplate: 'https://myapp.com/webhook/{task_type}/{agent_id}/{operation_id}',
73
124
 
74
- // Or manually configure
75
- const client = new ADCPMultiAgentClient([
76
- { id: 'agent1', agent_uri: 'https://...', protocol: 'mcp' }
77
- ]);
125
+ // OR query string
126
+ webhookUrlTemplate: 'https://myapp.com/webhook?agent={agent_id}&op={operation_id}&type={task_type}',
127
+
128
+ // OR custom path
129
+ webhookUrlTemplate: 'https://myapp.com/api/v1/adcp/{agent_id}?operation={operation_id}',
130
+
131
+ // OR namespace to avoid conflicts
132
+ webhookUrlTemplate: 'https://myapp.com/adcp-webhooks/{agent_id}/{task_type}/{operation_id}'
133
+ });
78
134
  ```
79
135
 
80
- ### Multiple Agents Made Simple
136
+ ### Single Webhook Endpoint
137
+
81
138
  ```typescript
82
- const client = new ADCPMultiAgentClient([
83
- { id: 'premium', agent_uri: 'https://premium.example.com', protocol: 'mcp' },
84
- { id: 'budget', agent_uri: 'https://budget.example.com', protocol: 'a2a' }
85
- ]);
139
+ // Handles ALL webhooks (task completions and notifications)
140
+ app.post('/webhook/:task_type/:agent_id/:operation_id', async (req, res) => {
141
+ const { task_type, agent_id, operation_id } = req.params;
142
+
143
+ // Inject URL parameters into payload
144
+ const payload = {
145
+ ...req.body,
146
+ task_type,
147
+ operation_id
148
+ };
149
+
150
+ // Route to agent client - handlers fire automatically
151
+ const agent = client.agent(agent_id);
152
+ await agent.handleWebhook(payload, req.headers['x-adcp-signature']);
153
+
154
+ res.json({ received: true });
155
+ });
156
+ ```
86
157
 
87
- // Work with specific agents
88
- const premium = client.agent('premium');
89
- const budget = client.agent('budget');
158
+ ### URL Generation is Automatic
90
159
 
91
- // Or run across all agents in parallel
92
- const allResults = await client.getProducts(params); // TaskResult<GetProductsResponse>[]
160
+ ```typescript
161
+ const operationId = createOperationId();
162
+ const webhookUrl = agent.getWebhookUrl('sync_creatives', operationId);
163
+ // Returns: https://myapp.com/webhook/sync_creatives/agent_x/op_123
164
+ // (or whatever your template generates)
93
165
  ```
94
166
 
95
- ## 🛡️ Type Safety
167
+ ## Activity Events
96
168
 
97
- Get **full TypeScript support** with compile-time checking and IntelliSense:
169
+ Get observability into everything happening:
98
170
 
99
171
  ```typescript
100
- const agent = client.agent('agent-id');
101
-
102
- // ✅ TYPE-SAFE METHODS: Full IntelliSense, compile-time checking
103
- await agent.getProducts(params); // TaskResult<GetProductsResponse>
104
- await agent.createMediaBuy(params); // TaskResult<CreateMediaBuyResponse>
105
- await agent.listCreativeFormats(params); // TaskResult<ListCreativeFormatsResponse>
172
+ const client = new ADCPMultiAgentClient(agents, {
173
+ onActivity: (activity) => {
174
+ console.log({
175
+ type: activity.type, // 'protocol_request', 'webhook_received', etc.
176
+ operation_id: activity.operation_id,
177
+ agent_id: activity.agent_id,
178
+ status: activity.status
179
+ });
180
+
181
+ // Stream to UI, save to database, send to monitoring
182
+ eventStream.send(activity);
183
+ }
184
+ });
185
+ ```
106
186
 
107
- // ✅ GENERIC METHOD WITH AUTO TYPE INFERENCE: No casting needed!
108
- const result = await agent.executeTask('get_products', params);
109
- // result is TaskResult<GetProductsResponse> - TypeScript knows the return type!
187
+ Activity types:
188
+ - `protocol_request` - Request sent to agent
189
+ - `protocol_response` - Response received from agent
190
+ - `webhook_received` - Webhook received from agent
191
+ - `handler_called` - Completion handler fired
110
192
 
111
- // CUSTOM TYPES: For non-standard tasks
112
- const customResult = await agent.executeTask<MyCustomResponse>('custom_task', params);
193
+ ## Notifications (Agent-Initiated)
113
194
 
114
- // BOTH support async patterns & input handlers!
115
- const withHandler = await agent.getProducts(
116
- { brief: "Premium inventory" },
117
- async (inputRequest) => ({ approve: true })
118
- );
119
- ```
195
+ **Mental Model**: Notifications are operations that get set up when you create a media buy. The agent sends periodic updates (like delivery reports) to the webhook URL you configured during media buy creation.
120
196
 
121
- ## Key Features
197
+ ```typescript
198
+ // When creating a media buy, agent registers for delivery notifications
199
+ const result = await agent.createMediaBuy({
200
+ campaign_id: 'camp_123',
201
+ budget: { amount: 10000, currency: 'USD' }
202
+ // Agent internally sets up recurring delivery_report notifications
203
+ });
122
204
 
123
- - **🔗 Unified Interface** - Single API for MCP and A2A protocols
124
- - **⚡ Async Support** - Handle long-running tasks with webhooks and deferrals
125
- - **🔐 Built-in Auth** - Bearer tokens and API key support with environment variable security
126
- - **🛡️ Type Safe** - Full TypeScript with comprehensive types
127
- - **📊 Production Ready** - Circuit breakers, retries, and validation
128
- - **🔒 Security-First** - No hardcoded tokens, SSRF protection, secure defaults
129
- - **🧪 Protocol Compliance** - 100% A2A and MCP specification compliance
130
- - **🌐 Cross-Platform** - Works with Node.js 18+ and modern JavaScript environments
205
+ // Later, agent sends notifications to your webhook
206
+ const client = new ADCPMultiAgentClient(agents, {
207
+ handlers: {
208
+ onMediaBuyDeliveryNotification: (notification, metadata) => {
209
+ console.log(`Report #${metadata.sequence_number}: ${metadata.notification_type}`);
131
210
 
132
- ## Async Execution Model
211
+ // notification_type indicates progress:
212
+ // 'scheduled' → Progress update (like status: 'working')
213
+ // 'final' → Operation complete (like status: 'completed')
214
+ // 'delayed' → Still waiting (extended timeline)
133
215
 
134
- Handle complex async patterns with ease:
216
+ db.saveDeliveryUpdate(metadata.operation_id, notification);
135
217
 
136
- ```typescript
137
- // Configure input handler for interactive tasks
138
- const client = ADCPClient.simple('https://agent.example.com', {
139
- authToken: 'token',
140
- inputHandler: async (request) => {
141
- // Handle 'input-required' status
142
- if (request.type === 'user_approval') {
143
- const approved = await getUserApproval(request.data);
144
- return { approved };
218
+ if (metadata.notification_type === 'final') {
219
+ db.markOperationComplete(metadata.operation_id);
220
+ }
145
221
  }
146
- // Defer for human review
147
- return { defer: true };
148
222
  }
149
223
  });
224
+ ```
150
225
 
151
- // Long-running server task (returns immediately)
152
- const result = await client.executeTask('analyze_campaign', {
153
- campaign_id: '12345'
154
- });
226
+ Notifications use the **same webhook URL pattern** as regular operations:
227
+ ```
228
+ POST https://myapp.com/webhook/media_buy_delivery/agent_x/delivery_report_agent_x_2025-10
229
+ ```
155
230
 
156
- if (result.status === 'submitted') {
157
- // Task running on server, will notify via webhook
158
- console.log('Task ID:', result.submitted.taskId);
159
- console.log('Webhook:', result.submitted.webhookUrl);
231
+ The `operation_id` is lazily generated from agent + month: `delivery_report_{agent_id}_{YYYY-MM}`
232
+
233
+ All intermediate reports for the same agent + month → same `operation_id`
234
+
235
+ ## Type Safety
236
+
237
+ Full TypeScript support with IntelliSense:
238
+
239
+ ```typescript
240
+ // All responses are fully typed
241
+ const result = await agent.getProducts(params);
242
+ // result: TaskResult<GetProductsResponse>
243
+
244
+ if (result.success) {
245
+ result.data.products.forEach(p => {
246
+ console.log(p.name, p.price); // Full autocomplete!
247
+ });
160
248
  }
161
249
 
162
- // Client-deferred task (needs human input)
163
- if (result.status === 'deferred') {
164
- // Save continuation for later
165
- const continuation = result.deferred;
166
-
167
- // ... later, after human provides input ...
168
- const finalResult = await client.resumeDeferredTask(
169
- continuation,
170
- { approved: true, budget: 50000 }
171
- );
250
+ // Handlers receive typed responses
251
+ handlers: {
252
+ onCreateMediaBuyComplete: (response, metadata) => {
253
+ // response: CreateMediaBuyResponse
254
+ // metadata: WebhookMetadata
255
+ const buyId = response.media_buy_id; // Typed!
256
+ }
172
257
  }
173
258
  ```
174
259
 
175
- ## Multi-Agent Support
260
+ ## Multi-Agent Operations
261
+
262
+ Execute across multiple agents simultaneously:
176
263
 
177
264
  ```typescript
178
- import { ADCPMultiAgentClient } from '@adcp/client';
265
+ const client = new ADCPMultiAgentClient([agentX, agentY, agentZ]);
179
266
 
180
- const client = new ADCPMultiAgentClient([
181
- {
182
- id: 'agent1',
183
- name: 'MCP Agent',
184
- agent_uri: 'https://agent1.example.com/mcp/',
185
- protocol: 'mcp',
186
- requiresAuth: true,
187
- auth_token_env: 'AGENT1_TOKEN'
188
- },
189
- {
190
- id: 'agent2',
191
- name: 'A2A Agent',
192
- agent_uri: 'https://agent2.example.com',
193
- protocol: 'a2a'
267
+ // Parallel execution across all agents
268
+ const results = await client.getProducts({ brief: 'Coffee brands' });
269
+ // results: TaskResult<GetProductsResponse>[]
270
+
271
+ results.forEach((result, i) => {
272
+ const agentId = client.agentIds[i];
273
+ console.log(`${agentId}: ${result.status}`);
274
+
275
+ if (result.status === 'completed') {
276
+ console.log(` Sync: ${result.data.products?.length} products`);
277
+ } else if (result.status === 'submitted') {
278
+ console.log(` Async: webhook to ${result.submitted?.webhookUrl}`);
194
279
  }
195
- ]);
280
+ });
281
+ ```
282
+
283
+ ## Security
196
284
 
197
- // Execute on specific agent
198
- const result = await client.executeTask('agent1', 'get_products', params);
285
+ ### Webhook Signature Verification
286
+
287
+ ```typescript
288
+ const client = new ADCPMultiAgentClient(agents, {
289
+ webhookSecret: process.env.WEBHOOK_SECRET
290
+ });
199
291
 
200
- // Execute on all agents in parallel
201
- const results = await client.executeTaskOnAll('get_products', params);
292
+ // Signatures verified automatically on handleWebhook()
293
+ // Returns 401 if signature invalid
202
294
  ```
203
295
 
204
- ## Documentation
296
+ ### Authentication
205
297
 
206
- - 📚 **[Full Documentation](https://your-org.github.io/adcp-client/)** - Complete guides and API reference
207
- - 🚀 **[Getting Started Guide](https://your-org.github.io/adcp-client/getting-started)** - Step-by-step tutorial
208
- - 🔄 **[Async Patterns](https://your-org.github.io/adcp-client/async-patterns)** - Handle complex async flows
209
- - 📖 **[API Reference](https://your-org.github.io/adcp-client/api)** - Generated from TypeDoc
210
- - 💡 **[Examples](./examples/)** - Real-world usage examples
298
+ ```typescript
299
+ const agents = [{
300
+ id: 'agent_x',
301
+ agent_uri: 'https://agent-x.com',
302
+ protocol: 'a2a',
303
+ auth_token_env: process.env.AGENT_X_TOKEN, // ✅ Secure
304
+ requiresAuth: true
305
+ }];
306
+ ```
211
307
 
212
- ## Examples
308
+ ## Environment Configuration
213
309
 
214
310
  ```bash
215
- # Clone for full examples
216
- git clone https://github.com/your-org/adcp-client
217
- cd adcp-client/examples
311
+ # .env
312
+ WEBHOOK_URL_TEMPLATE="https://myapp.com/webhook/{task_type}/{agent_id}/{operation_id}"
313
+ WEBHOOK_SECRET="your-webhook-secret"
218
314
 
219
- # Run examples
220
- npx tsx basic-usage.ts
221
- npx tsx async-patterns.ts
222
- npx tsx multi-agent.ts
315
+ ADCP_AGENTS='[
316
+ {
317
+ "id": "agent_x",
318
+ "agent_uri": "https://agent-x.com",
319
+ "protocol": "a2a",
320
+ "auth_token_env": "AGENT_X_TOKEN"
321
+ }
322
+ ]'
323
+ AGENT_X_TOKEN="actual-token-here"
223
324
  ```
224
325
 
225
- ## Testing UI
326
+ ```typescript
327
+ // Auto-discover from environment
328
+ const client = ADCPMultiAgentClient.fromEnv();
329
+ ```
330
+
331
+ ## Available Tools
332
+
333
+ All AdCP tools with full type safety:
334
+
335
+ **Media Buy Lifecycle:**
336
+ - `getProducts()` - Discover advertising products
337
+ - `listCreativeFormats()` - Get supported creative formats
338
+ - `createMediaBuy()` - Create new media buy
339
+ - `updateMediaBuy()` - Update existing media buy
340
+ - `syncCreatives()` - Upload/sync creative assets
341
+ - `listCreatives()` - List creative assets
342
+ - `getMediaBuyDelivery()` - Get delivery performance
343
+
344
+ **Audience & Targeting:**
345
+ - `listAuthorizedProperties()` - Get authorized properties
346
+ - `getSignals()` - Get audience signals
347
+ - `activateSignal()` - Activate audience signals
348
+ - `providePerformanceFeedback()` - Send performance feedback
349
+
350
+ ## Database Schema
351
+
352
+ Simple unified event log for all operations:
353
+
354
+ ```sql
355
+ CREATE TABLE webhook_events (
356
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
357
+ operation_id TEXT NOT NULL, -- Groups related events
358
+ agent_id TEXT NOT NULL,
359
+ task_type TEXT NOT NULL, -- 'sync_creatives', 'media_buy_delivery', etc.
360
+ status TEXT, -- For tasks: 'submitted', 'working', 'completed'
361
+ notification_type TEXT, -- For notifications: 'scheduled', 'final', 'delayed'
362
+ sequence_number INTEGER, -- For notifications: report sequence
363
+ payload JSONB NOT NULL,
364
+ timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
365
+ );
366
+
367
+ CREATE INDEX idx_events_operation ON webhook_events(operation_id);
368
+ CREATE INDEX idx_events_agent ON webhook_events(agent_id);
369
+ CREATE INDEX idx_events_timestamp ON webhook_events(timestamp DESC);
370
+
371
+ -- Query all events for an operation
372
+ SELECT * FROM webhook_events
373
+ WHERE operation_id = 'op_123'
374
+ ORDER BY timestamp;
375
+
376
+ -- Get all delivery reports for agent + month
377
+ SELECT * FROM webhook_events
378
+ WHERE operation_id = 'delivery_report_agent_x_2025-10'
379
+ ORDER BY sequence_number;
380
+ ```
226
381
 
227
- The package includes an interactive testing framework:
382
+ ## Testing
383
+
384
+ Try the live testing UI at `http://localhost:8080` when running the server:
228
385
 
229
386
  ```bash
230
- # Install and run locally
231
- git clone https://github.com/your-org/adcp-client
232
- cd adcp-client
233
- npm install
234
- npm run dev
387
+ npm start
388
+ ```
389
+
390
+ Features:
391
+ - Configure multiple agents (test agents + your own)
392
+ - Execute ONE operation across all agents
393
+ - See live activity stream (protocol requests, webhooks, handlers)
394
+ - View sync vs async completions side-by-side
395
+ - Test different scenarios (clarifications, errors, timeouts)
396
+
397
+ ## Examples
398
+
399
+ ### Basic Operation
400
+ ```typescript
401
+ const result = await agent.getProducts({ brief: 'Coffee brands' });
402
+ ```
403
+
404
+ ### With Clarification Handler
405
+ ```typescript
406
+ const result = await agent.createMediaBuy(
407
+ { brief: 'Coffee campaign' },
408
+ (context) => {
409
+ // Agent needs more info
410
+ if (context.inputRequest.field === 'budget') {
411
+ return 50000; // Provide programmatically
412
+ }
413
+ return context.deferToHuman(); // Or defer to human
414
+ }
415
+ );
416
+ ```
417
+
418
+ ### With Webhook for Long-Running Operations
419
+ ```typescript
420
+ const operationId = createOperationId();
421
+
422
+ const result = await agent.syncCreatives(
423
+ { creatives: largeCreativeList },
424
+ null, // No clarification handler = webhook mode
425
+ {
426
+ contextId: operationId,
427
+ webhookUrl: agent.getWebhookUrl('sync_creatives', operationId)
428
+ }
429
+ );
235
430
 
236
- # Open http://localhost:8080
431
+ // Result will be 'submitted', webhook arrives later
432
+ // Handler fires when webhook received
237
433
  ```
238
434
 
239
435
  ## Contributing
240
436
 
241
- We welcome contributions! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
437
+ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
242
438
 
243
439
  ## License
244
440
 
245
- MIT - see [LICENSE](./LICENSE) for details.
441
+ MIT License - see [LICENSE](LICENSE) file for details.
246
442
 
247
- ## Links
443
+ ## Support
248
444
 
249
- - [AdCP Specification](https://adcontextprotocol.org)
250
- - [Issue Tracker](https://github.com/your-org/adcp-client/issues)
251
- - [npm Package](https://www.npmjs.com/package/@adcp/client)
445
+ - **Documentation**: [GitHub Pages](https://your-org.github.io/adcp-client/)
446
+ - **Issues**: [GitHub Issues](https://github.com/your-org/adcp-client/issues)
447
+ - **Protocol Spec**: [AdCP Specification](https://github.com/adcontextprotocol/adcp)
@@ -1,5 +1,5 @@
1
1
  import type { AgentConfig } from '../types';
2
- import type { GetProductsRequest, GetProductsResponse, ListCreativeFormatsRequest, ListCreativeFormatsResponse, CreateMediaBuyRequest, CreateMediaBuyResponse, SyncCreativesRequest, SyncCreativesResponse, ListCreativesRequest, ListCreativesResponse, UpdateMediaBuyRequest, UpdateMediaBuyResponse, GetMediaBuyDeliveryRequest, GetMediaBuyDeliveryResponse, ListAuthorizedPropertiesRequest, ListAuthorizedPropertiesResponse, ProvidePerformanceFeedbackRequest, ProvidePerformanceFeedbackResponse, BuildCreativeRequest, BuildCreativeResponse, ManageCreativeLibraryRequest, ManageCreativeLibraryResponse, GetSignalsRequest, GetSignalsResponse, ActivateSignalRequest, ActivateSignalResponse } from '../types/tools.generated';
2
+ import type { GetProductsRequest, GetProductsResponse, ListCreativeFormatsRequest, ListCreativeFormatsResponse, CreateMediaBuyRequest, CreateMediaBuyResponse, SyncCreativesRequest, SyncCreativesResponse, ListCreativesRequest, ListCreativesResponse, UpdateMediaBuyRequest, UpdateMediaBuyResponse, GetMediaBuyDeliveryRequest, GetMediaBuyDeliveryResponse, ListAuthorizedPropertiesRequest, ListAuthorizedPropertiesResponse, ProvidePerformanceFeedbackRequest, ProvidePerformanceFeedbackResponse, GetSignalsRequest, GetSignalsResponse, ActivateSignalRequest, ActivateSignalResponse } from '../types/tools.generated';
3
3
  interface ToolResponse<T> {
4
4
  success: true;
5
5
  data: T;
@@ -78,16 +78,6 @@ export declare class Agent {
78
78
  * Official AdCP provide_performance_feedback tool schema
79
79
  */
80
80
  providePerformanceFeedback(params: ProvidePerformanceFeedbackRequest): Promise<ToolResult<ProvidePerformanceFeedbackResponse>>;
81
- /**
82
- * Official AdCP build_creative tool schema
83
- * Official AdCP build_creative tool schema
84
- */
85
- buildCreative(params: BuildCreativeRequest): Promise<ToolResult<BuildCreativeResponse>>;
86
- /**
87
- * Official AdCP manage_creative_library tool schema
88
- * Official AdCP manage_creative_library tool schema
89
- */
90
- manageCreativeLibrary(params: ManageCreativeLibraryRequest): Promise<ToolResult<ManageCreativeLibraryResponse>>;
91
81
  /**
92
82
  * Official AdCP get_signals tool schema
93
83
  * Official AdCP get_signals tool schema
@@ -142,16 +132,6 @@ export declare class AgentCollection {
142
132
  * Official AdCP provide_performance_feedback tool schema
143
133
  */
144
134
  providePerformanceFeedback(params: ProvidePerformanceFeedbackRequest): Promise<ToolResult<ProvidePerformanceFeedbackResponse>[]>;
145
- /**
146
- * Official AdCP build_creative tool schema (across multiple agents)
147
- * Official AdCP build_creative tool schema
148
- */
149
- buildCreative(params: BuildCreativeRequest): Promise<ToolResult<BuildCreativeResponse>[]>;
150
- /**
151
- * Official AdCP manage_creative_library tool schema (across multiple agents)
152
- * Official AdCP manage_creative_library tool schema
153
- */
154
- manageCreativeLibrary(params: ManageCreativeLibraryRequest): Promise<ToolResult<ManageCreativeLibraryResponse>[]>;
155
135
  /**
156
136
  * Official AdCP get_signals tool schema (across multiple agents)
157
137
  * Official AdCP get_signals tool schema