@elevasis/sdk 0.5.13 → 0.5.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +745 -409
- package/dist/index.d.ts +32 -0
- package/dist/index.js +68 -0
- package/dist/templates.js +254 -37
- package/dist/worker/index.js +3 -7
- package/package.json +1 -1
- package/reference/cli.mdx +568 -505
- package/reference/concepts.mdx +4 -43
- package/reference/deployment/api.mdx +297 -297
- package/reference/deployment/command-center.mdx +9 -12
- package/reference/deployment/index.mdx +7 -7
- package/reference/framework/agent.mdx +6 -18
- package/reference/framework/interaction-guidance.mdx +182 -182
- package/reference/framework/memory.mdx +3 -24
- package/reference/framework/project-structure.mdx +277 -298
- package/reference/framework/tutorial-system.mdx +13 -44
- package/reference/getting-started.mdx +152 -148
- package/reference/index.mdx +28 -14
- package/reference/platform-tools/adapters.mdx +868 -1072
- package/reference/platform-tools/index.mdx +3 -3
- package/reference/resources/index.mdx +339 -341
- package/reference/resources/patterns.mdx +355 -354
- package/reference/resources/types.mdx +207 -207
- package/reference/roadmap.mdx +163 -147
- package/reference/runtime.mdx +2 -25
- package/reference/troubleshooting.mdx +223 -210
|
@@ -1,1072 +1,868 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Typed Adapters
|
|
3
|
-
description: Type-safe wrappers over platform.call() for all integrations and platform tools -- Attio, Stripe, Notion, Google Sheets, and more -- with full autocomplete, compile-time checking, and zero boilerplate
|
|
4
|
-
loadWhen: "Using typed adapters instead of raw platform.call(), or needs to know what adapter methods are available"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Typed adapters are ergonomic wrappers over `platform.call()` that provide full TypeScript autocomplete and compile-time type checking. They eliminate stringly-typed method names, manual `as Promise<T>` casts, and repeated credential passing.
|
|
8
|
-
|
|
9
|
-
Both patterns work simultaneously -- adapters compile down to `platform.call()` with zero runtime overhead.
|
|
10
|
-
|
|
11
|
-
**Coverage:** 11 integration adapters (55 methods) + 9 platform tool adapters (57 methods) = 112 total typed methods.
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
// Before: raw platform.call()
|
|
15
|
-
const records = await platform.call({
|
|
16
|
-
tool: 'attio',
|
|
17
|
-
method: 'listRecords',
|
|
18
|
-
credential: 'my-attio',
|
|
19
|
-
params: { object: 'deals' }
|
|
20
|
-
}) as unknown as QueryRecordsResult
|
|
21
|
-
|
|
22
|
-
// After: typed adapter
|
|
23
|
-
const attio = createAttioAdapter('my-attio')
|
|
24
|
-
const records = await attio.listRecords({ object: 'deals' })
|
|
25
|
-
// ^-- QueryRecordsResult (fully typed, autocomplete on params)
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
All adapters are imported from `@elevasis/sdk/worker` -- the same subpath as `platform`.
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Quick Reference
|
|
33
|
-
|
|
34
|
-
### Integration Adapters (factory pattern, credential required)
|
|
35
|
-
|
|
36
|
-
| Import
|
|
37
|
-
|
|
38
|
-
| `createAttioAdapter(cred)`
|
|
39
|
-
| `createStripeAdapter(cred)`
|
|
40
|
-
| `createNotionAdapter(cred)`
|
|
41
|
-
| `createGoogleSheetsAdapter(cred)` | 13
|
|
42
|
-
| `createInstantlyAdapter(cred)`
|
|
43
|
-
| `createSignatureApiAdapter(cred)` | 4
|
|
44
|
-
| `createResendAdapter(cred)`
|
|
45
|
-
| `createDropboxAdapter(cred)`
|
|
46
|
-
| `createApifyAdapter(cred)`
|
|
47
|
-
| `createGmailAdapter(cred)`
|
|
48
|
-
| `createMailsoAdapter(cred)`
|
|
49
|
-
|
|
50
|
-
### Platform Adapters (singletons, no credential)
|
|
51
|
-
|
|
52
|
-
| Import
|
|
53
|
-
|
|
54
|
-
| `lead`
|
|
55
|
-
| `scheduler`
|
|
56
|
-
| `storage`
|
|
57
|
-
| `pdf`
|
|
58
|
-
| `approval`
|
|
59
|
-
| `notifications` | 1
|
|
60
|
-
| `llm`
|
|
61
|
-
| `execution`
|
|
62
|
-
| `email`
|
|
63
|
-
|
|
64
|
-
### Generic Factory
|
|
65
|
-
|
|
66
|
-
| Import
|
|
67
|
-
|
|
68
|
-
| `createAdapter<TMap>(tool, methods, cred?)` | Build custom adapters for any tool |
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
import {
|
|
72
|
-
// Integration adapters
|
|
73
|
-
createAttioAdapter, createStripeAdapter, createNotionAdapter,
|
|
74
|
-
createGoogleSheetsAdapter, createInstantlyAdapter,
|
|
75
|
-
createSignatureApiAdapter, createResendAdapter, createDropboxAdapter,
|
|
76
|
-
createApifyAdapter, createGmailAdapter, createMailsoAdapter,
|
|
77
|
-
// Platform adapters
|
|
78
|
-
lead, scheduler, storage, pdf, approval, notifications, llm, execution, email,
|
|
79
|
-
// Generic factory
|
|
80
|
-
createAdapter,
|
|
81
|
-
} from '@elevasis/sdk/worker'
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Attio CRM Adapter
|
|
87
|
-
|
|
88
|
-
Factory pattern -- bind a credential once, use 12 typed methods.
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
const attio = createAttioAdapter('my-attio-credential')
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Methods
|
|
95
|
-
|
|
96
|
-
| Method
|
|
97
|
-
|
|
98
|
-
| `createRecord`
|
|
99
|
-
| `updateRecord`
|
|
100
|
-
| `listRecords`
|
|
101
|
-
| `getRecord`
|
|
102
|
-
| `deleteRecord`
|
|
103
|
-
| `listObjects`
|
|
104
|
-
| `listAttributes`
|
|
105
|
-
| `createAttribute` | `CreateAttributeParams` | `CreateAttributeResult` |
|
|
106
|
-
| `updateAttribute` | `UpdateAttributeParams` | `UpdateAttributeResult` |
|
|
107
|
-
| `createNote`
|
|
108
|
-
| `listNotes`
|
|
109
|
-
| `deleteNote`
|
|
110
|
-
|
|
111
|
-
### Examples
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
// Create a company record
|
|
115
|
-
const company = await attio.createRecord({
|
|
116
|
-
object: 'companies',
|
|
117
|
-
values: {
|
|
118
|
-
name: [{ value: 'Acme Corp' }],
|
|
119
|
-
domains: [{ domain: 'acme.com' }],
|
|
120
|
-
},
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
// Query deals with filters
|
|
124
|
-
const deals = await attio.listRecords({
|
|
125
|
-
object: 'deals',
|
|
126
|
-
filter: {
|
|
127
|
-
operator: 'and',
|
|
128
|
-
filters: [
|
|
129
|
-
{ field: 'stage', operator: 'equals', value: 'proposal' },
|
|
130
|
-
],
|
|
131
|
-
},
|
|
132
|
-
sorts: [{ field: 'created_at', direction: 'desc' }],
|
|
133
|
-
limit: 20,
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
// Get a specific record
|
|
137
|
-
const record = await attio.getRecord({
|
|
138
|
-
object: 'people',
|
|
139
|
-
recordId: 'rec_abc123',
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
// List all objects (no params)
|
|
143
|
-
const objects = await attio.listObjects()
|
|
144
|
-
|
|
145
|
-
// Create a note on a record
|
|
146
|
-
await attio.createNote({
|
|
147
|
-
parentObject: 'deals',
|
|
148
|
-
parentRecordId: 'rec_abc123',
|
|
149
|
-
title: 'Discovery call notes',
|
|
150
|
-
content: 'Key takeaways from the call...',
|
|
151
|
-
})
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
Multiple adapters with different credentials work simultaneously:
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
const prodAttio = createAttioAdapter('prod-attio')
|
|
158
|
-
const testAttio = createAttioAdapter('test-attio')
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## Stripe Adapter
|
|
164
|
-
|
|
165
|
-
Factory pattern -- 6 methods for payment links and checkout sessions.
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
const stripe = createStripeAdapter('my-stripe-credential')
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### Methods
|
|
172
|
-
|
|
173
|
-
| Method
|
|
174
|
-
|
|
175
|
-
| `createPaymentLink`
|
|
176
|
-
| `getPaymentLink`
|
|
177
|
-
| `updatePaymentLink`
|
|
178
|
-
| `listPaymentLinks`
|
|
179
|
-
| `createAutoPaymentLink` | `CreateAutoPaymentLinkParams` | `CreateAutoPaymentLinkResult` |
|
|
180
|
-
| `createCheckoutSession` | `CreateCheckoutSessionParams` | `CreateCheckoutSessionResult` |
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
## Notion Adapter
|
|
185
|
-
|
|
186
|
-
Factory pattern -- 8 methods for page and block operations.
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
const notion = createNotionAdapter('my-notion-credential')
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### Methods
|
|
193
|
-
|
|
194
|
-
| Method
|
|
195
|
-
|
|
196
|
-
| `listAllPages`
|
|
197
|
-
| `readPage`
|
|
198
|
-
| `createPage`
|
|
199
|
-
| `updatePageTitle` | `UpdatePageTitleParams` | `UpdatePageTitleResult` |
|
|
200
|
-
| `appendBlocks`
|
|
201
|
-
| `updateBlocks`
|
|
202
|
-
| `deletePage`
|
|
203
|
-
| `deleteBlocks`
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Google Sheets Adapter
|
|
208
|
-
|
|
209
|
-
Factory pattern -- 13 methods including workflow-friendly helpers (getRowByValue, upsertRow, filterRows).
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
const sheets = createGoogleSheetsAdapter('my-google-credential')
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Methods
|
|
216
|
-
|
|
217
|
-
| Method
|
|
218
|
-
|
|
219
|
-
| `readSheet`
|
|
220
|
-
| `writeSheet`
|
|
221
|
-
| `appendRows`
|
|
222
|
-
| `clearRange`
|
|
223
|
-
| `getSpreadsheetMetadata` | `GetSpreadsheetMetadataParams` | `GetSpreadsheetMetadataResult` |
|
|
224
|
-
| `batchUpdate`
|
|
225
|
-
| `getHeaders`
|
|
226
|
-
| `getLastRow`
|
|
227
|
-
| `getRowByValue`
|
|
228
|
-
| `updateRowByValue`
|
|
229
|
-
| `upsertRow`
|
|
230
|
-
| `filterRows`
|
|
231
|
-
| `deleteRowByValue`
|
|
232
|
-
|
|
233
|
-
---
|
|
234
|
-
|
|
235
|
-
## Instantly Adapter
|
|
236
|
-
|
|
237
|
-
Factory pattern -- 5 methods for email campaign management.
|
|
238
|
-
|
|
239
|
-
```typescript
|
|
240
|
-
const instantly = createInstantlyAdapter('my-instantly-credential')
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
### Methods
|
|
244
|
-
|
|
245
|
-
| Method
|
|
246
|
-
|
|
247
|
-
| `sendReply`
|
|
248
|
-
| `removeFromSubsequence` | `RemoveFromSubsequenceParams` | `RemoveFromSubsequenceResult` |
|
|
249
|
-
| `getEmails`
|
|
250
|
-
| `updateInterestStatus`
|
|
251
|
-
| `addToCampaign`
|
|
252
|
-
|
|
253
|
-
---
|
|
254
|
-
|
|
255
|
-
## SignatureAPI Adapter
|
|
256
|
-
|
|
257
|
-
Factory pattern -- 4 methods for eSignature envelope operations.
|
|
258
|
-
|
|
259
|
-
```typescript
|
|
260
|
-
const signatureApi = createSignatureApiAdapter('my-signatureapi-credential')
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### Methods
|
|
264
|
-
|
|
265
|
-
| Method
|
|
266
|
-
|
|
267
|
-
| `createEnvelope`
|
|
268
|
-
| `voidEnvelope`
|
|
269
|
-
| `downloadDocument` | `DownloadDocumentParams` | `DownloadDocumentResult` |
|
|
270
|
-
| `getEnvelope`
|
|
271
|
-
|
|
272
|
-
---
|
|
273
|
-
|
|
274
|
-
## Resend Adapter
|
|
275
|
-
|
|
276
|
-
Factory pattern -- 2 methods for transactional email.
|
|
277
|
-
|
|
278
|
-
```typescript
|
|
279
|
-
const resend = createResendAdapter('my-resend-credential')
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Methods
|
|
283
|
-
|
|
284
|
-
| Method
|
|
285
|
-
|
|
286
|
-
| `sendEmail` | `ResendSendEmailParams` | `ResendSendEmailResult` |
|
|
287
|
-
| `getEmail`
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
## Dropbox Adapter
|
|
292
|
-
|
|
293
|
-
Factory pattern -- 2 methods for file operations.
|
|
294
|
-
|
|
295
|
-
```typescript
|
|
296
|
-
const dropbox = createDropboxAdapter('my-dropbox-credential')
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### Methods
|
|
300
|
-
|
|
301
|
-
| Method
|
|
302
|
-
|
|
303
|
-
| `uploadFile`
|
|
304
|
-
| `createFolder` | `CreateFolderParams` | `CreateFolderResult` |
|
|
305
|
-
|
|
306
|
-
---
|
|
307
|
-
|
|
308
|
-
## Apify Adapter
|
|
309
|
-
|
|
310
|
-
Factory pattern -- 1 method for running web scraping actors.
|
|
311
|
-
|
|
312
|
-
```typescript
|
|
313
|
-
const apify = createApifyAdapter('my-apify-credential')
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
### Methods
|
|
317
|
-
|
|
318
|
-
| Method
|
|
319
|
-
|
|
320
|
-
| `runActor` | `RunActorParams` | `RunActorResult` |
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
|
-
## Gmail Adapter
|
|
325
|
-
|
|
326
|
-
Factory pattern -- 1 method for sending email via Gmail API.
|
|
327
|
-
|
|
328
|
-
```typescript
|
|
329
|
-
const gmail = createGmailAdapter('my-gmail-credential')
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
### Methods
|
|
333
|
-
|
|
334
|
-
| Method
|
|
335
|
-
|
|
336
|
-
| `sendEmail` | `GmailSendEmailParams` | `GmailSendEmailResult` |
|
|
337
|
-
|
|
338
|
-
---
|
|
339
|
-
|
|
340
|
-
## Mailso Adapter
|
|
341
|
-
|
|
342
|
-
Factory pattern -- 1 method for email verification.
|
|
343
|
-
|
|
344
|
-
```typescript
|
|
345
|
-
const mailso = createMailsoAdapter('my-mailso-credential')
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
### Methods
|
|
349
|
-
|
|
350
|
-
| Method
|
|
351
|
-
|
|
352
|
-
| `verifyEmail` | `MailsoVerifyEmailParams` | `MailsoVerifyEmailResult` |
|
|
353
|
-
|
|
354
|
-
---
|
|
355
|
-
|
|
356
|
-
## Scheduler Adapter
|
|
357
|
-
|
|
358
|
-
Singleton -- 9 methods for task schedule management.
|
|
359
|
-
|
|
360
|
-
```typescript
|
|
361
|
-
import { scheduler } from '@elevasis/sdk/worker'
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
### Methods
|
|
365
|
-
|
|
366
|
-
| Method
|
|
367
|
-
|
|
368
|
-
| `createSchedule`
|
|
369
|
-
| `updateAnchor`
|
|
370
|
-
| `deleteSchedule`
|
|
371
|
-
| `findByIdempotencyKey`
|
|
372
|
-
| `deleteScheduleByIdempotencyKey` | `{ idempotencyKey }`
|
|
373
|
-
| `listSchedules`
|
|
374
|
-
| `getSchedule`
|
|
375
|
-
| `cancelSchedule`
|
|
376
|
-
| `cancelSchedulesByMetadata`
|
|
377
|
-
|
|
378
|
-
### Examples
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
// Create a relative schedule (follow-up sequence)
|
|
382
|
-
const schedule = await scheduler.createSchedule({
|
|
383
|
-
organizationId: context.organizationId,
|
|
384
|
-
name: 'Proposal follow-up',
|
|
385
|
-
target: { resourceType: 'workflow', resourceId: 'send-followup' },
|
|
386
|
-
scheduleConfig: {
|
|
387
|
-
type: 'relative',
|
|
388
|
-
anchorAt: '2026-03-15T10:00:00Z',
|
|
389
|
-
anchorLabel: 'proposal_sent_date',
|
|
390
|
-
items: [
|
|
391
|
-
{ offset: '+3d', payload: { step: 'first-followup' }, label: 'First follow-up' },
|
|
392
|
-
{ offset: '+7d', payload: { step: 'second-followup' }, label: 'Second follow-up' },
|
|
393
|
-
],
|
|
394
|
-
},
|
|
395
|
-
metadata: { dealId: 'deal-123', contactEmail: 'jane@acme.com' },
|
|
396
|
-
idempotencyKey: 'proposal-followup-deal-123',
|
|
397
|
-
})
|
|
398
|
-
|
|
399
|
-
// Reschedule (update anchor)
|
|
400
|
-
await scheduler.updateAnchor({
|
|
401
|
-
scheduleId: schedule.id,
|
|
402
|
-
anchorAt: '2026-03-20T10:00:00Z',
|
|
403
|
-
})
|
|
404
|
-
|
|
405
|
-
// Find by idempotency key (check if already created)
|
|
406
|
-
const existing = await scheduler.findByIdempotencyKey({
|
|
407
|
-
idempotencyKey: 'proposal-followup-deal-123',
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
// Cancel all schedules matching metadata
|
|
411
|
-
await scheduler.cancelSchedulesByMetadata({
|
|
412
|
-
metadata: { dealId: 'deal-123' },
|
|
413
|
-
})
|
|
414
|
-
|
|
415
|
-
// List active schedules
|
|
416
|
-
const schedules = await scheduler.listSchedules({
|
|
417
|
-
status: 'active',
|
|
418
|
-
limit: 50,
|
|
419
|
-
})
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
---
|
|
423
|
-
|
|
424
|
-
## Storage Adapter
|
|
425
|
-
|
|
426
|
-
Singleton -- 5 methods for file storage operations.
|
|
427
|
-
|
|
428
|
-
```typescript
|
|
429
|
-
import { storage } from '@elevasis/sdk/worker'
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
All paths are relative to the organization's storage prefix. The platform injects the organization prefix server-side.
|
|
433
|
-
|
|
434
|
-
### Methods
|
|
435
|
-
|
|
436
|
-
| Method
|
|
437
|
-
|
|
438
|
-
| `upload`
|
|
439
|
-
| `download`
|
|
440
|
-
| `createSignedUrl` | `StorageSignedUrlInput` | `StorageSignedUrlOutput` |
|
|
441
|
-
| `delete`
|
|
442
|
-
| `list`
|
|
443
|
-
|
|
444
|
-
### Examples
|
|
445
|
-
|
|
446
|
-
```typescript
|
|
447
|
-
// Upload a PDF
|
|
448
|
-
await storage.upload({
|
|
449
|
-
bucket: 'acquisition',
|
|
450
|
-
path: 'proposals/deal-123/proposal.pdf',
|
|
451
|
-
content: base64PdfContent,
|
|
452
|
-
contentType: 'application/pdf',
|
|
453
|
-
})
|
|
454
|
-
|
|
455
|
-
// Generate a signed URL (temporary access)
|
|
456
|
-
const { signedUrl } = await storage.createSignedUrl({
|
|
457
|
-
bucket: 'acquisition',
|
|
458
|
-
path: 'proposals/deal-123/proposal.pdf',
|
|
459
|
-
})
|
|
460
|
-
|
|
461
|
-
// Download a file
|
|
462
|
-
const file = await storage.download({
|
|
463
|
-
bucket: 'acquisition',
|
|
464
|
-
path: 'proposals/deal-123/proposal.pdf',
|
|
465
|
-
})
|
|
466
|
-
|
|
467
|
-
// List files under a prefix
|
|
468
|
-
const files = await storage.list({
|
|
469
|
-
bucket: 'acquisition',
|
|
470
|
-
path: 'proposals/deal-123/',
|
|
471
|
-
})
|
|
472
|
-
|
|
473
|
-
// Delete a file
|
|
474
|
-
await storage.delete({
|
|
475
|
-
bucket: 'acquisition',
|
|
476
|
-
path: 'proposals/deal-123/old-proposal.pdf',
|
|
477
|
-
})
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
---
|
|
481
|
-
|
|
482
|
-
## Notification Adapter
|
|
483
|
-
|
|
484
|
-
Singleton -- 1 method for sending in-app team notifications.
|
|
485
|
-
|
|
486
|
-
```typescript
|
|
487
|
-
import { notifications } from '@elevasis/sdk/worker'
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
`userId` and `organizationId` are injected server-side from the execution context -- you never pass them.
|
|
491
|
-
|
|
492
|
-
### Method
|
|
493
|
-
|
|
494
|
-
| Method
|
|
495
|
-
|
|
496
|
-
| `create` | `NotificationSDKInput` | `void`
|
|
497
|
-
|
|
498
|
-
`NotificationSDKInput` fields: `category`, `title`, `message`, `actionUrl?`, `metadata?`
|
|
499
|
-
|
|
500
|
-
### Example
|
|
501
|
-
|
|
502
|
-
```typescript
|
|
503
|
-
await notifications.create({
|
|
504
|
-
category: 'acquisition',
|
|
505
|
-
title: 'New lead qualified',
|
|
506
|
-
message: 'Acme Corp has been qualified and moved to proposal stage.',
|
|
507
|
-
actionUrl: '/deals/deal-123',
|
|
508
|
-
})
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
---
|
|
512
|
-
|
|
513
|
-
## LLM Adapter
|
|
514
|
-
|
|
515
|
-
Singleton -- 1 method with a generic `<T>` for typed structured output.
|
|
516
|
-
|
|
517
|
-
```typescript
|
|
518
|
-
import { llm } from '@elevasis/sdk/worker'
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
No API keys needed -- keys are resolved server-side from environment variables.
|
|
522
|
-
|
|
523
|
-
### Method
|
|
524
|
-
|
|
525
|
-
| Method
|
|
526
|
-
|
|
527
|
-
| `generate<T>` | `Omit<LLMGenerateRequest, 'signal'>` | `LLMGenerateResponse<T>` |
|
|
528
|
-
|
|
529
|
-
The `signal` property (AbortSignal) is not serializable over the postMessage boundary. Abort is handled at the worker level via the parent process sending an abort message.
|
|
530
|
-
|
|
531
|
-
### Example
|
|
532
|
-
|
|
533
|
-
```typescript
|
|
534
|
-
interface Classification {
|
|
535
|
-
category: 'interested' | 'not-interested' | 'bounced'
|
|
536
|
-
confidence: number
|
|
537
|
-
summary: string
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
const response = await llm.generate<Classification>({
|
|
541
|
-
provider: 'anthropic',
|
|
542
|
-
model: 'claude-sonnet-4-5',
|
|
543
|
-
messages: [
|
|
544
|
-
{ role: 'system', content: 'Classify this email reply.' },
|
|
545
|
-
{ role: 'user', content: emailText },
|
|
546
|
-
],
|
|
547
|
-
responseSchema: {
|
|
548
|
-
type: 'object',
|
|
549
|
-
properties: {
|
|
550
|
-
category: { type: 'string', enum: ['interested', 'not-interested', 'bounced'] },
|
|
551
|
-
confidence: { type: 'number', minimum: 0, maximum: 1 },
|
|
552
|
-
summary: { type: 'string' },
|
|
553
|
-
},
|
|
554
|
-
required: ['category', 'confidence', 'summary'],
|
|
555
|
-
},
|
|
556
|
-
temperature: 0.1,
|
|
557
|
-
})
|
|
558
|
-
|
|
559
|
-
// response.output is typed as Classification
|
|
560
|
-
const { category, confidence, summary } = response.output
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
---
|
|
564
|
-
|
|
565
|
-
## Lead Adapter
|
|
566
|
-
|
|
567
|
-
Singleton -- 35 methods for acquisition lead management (lists, companies, contacts, deals, deal-sync). `organizationId` is injected server-side -- never pass it.
|
|
568
|
-
|
|
569
|
-
```typescript
|
|
570
|
-
import { lead } from '@elevasis/sdk/worker'
|
|
571
|
-
```
|
|
572
|
-
|
|
573
|
-
### Methods
|
|
574
|
-
|
|
575
|
-
**List operations:**
|
|
576
|
-
|
|
577
|
-
| Method
|
|
578
|
-
|
|
579
|
-
| `listLists`
|
|
580
|
-
| `createList` | `Omit<CreateListParams, 'organizationId'>` | `AcqList`
|
|
581
|
-
| `updateList` | `{ id } & UpdateListParams`
|
|
582
|
-
| `deleteList` | `{ id }`
|
|
583
|
-
|
|
584
|
-
**Company operations:**
|
|
585
|
-
|
|
586
|
-
| Method
|
|
587
|
-
|
|
588
|
-
| `createCompany` | `Omit<CreateCompanyParams, 'organizationId'>` | `AcqCompany`
|
|
589
|
-
| `upsertCompany` | `Omit<UpsertCompanyParams, 'organizationId'>` | `AcqCompany`
|
|
590
|
-
| `updateCompany` | `{ id } & UpdateCompanyParams`
|
|
591
|
-
| `getCompany`
|
|
592
|
-
| `listCompanies` | `{ filters? }`
|
|
593
|
-
| `deleteCompany` | `{ id }`
|
|
594
|
-
|
|
595
|
-
**Contact operations:**
|
|
596
|
-
|
|
597
|
-
| Method
|
|
598
|
-
|
|
599
|
-
| `createContact`
|
|
600
|
-
| `upsertContact`
|
|
601
|
-
| `updateContact`
|
|
602
|
-
| `getContact`
|
|
603
|
-
| `getContactByEmail`
|
|
604
|
-
| `listContacts`
|
|
605
|
-
| `deleteContact`
|
|
606
|
-
| `bulkImportContacts` | `Omit<BulkImportParams, 'organizationId'>`
|
|
607
|
-
|
|
608
|
-
**Deal operations:**
|
|
609
|
-
|
|
610
|
-
| Method
|
|
611
|
-
|
|
612
|
-
| `upsertDeal`
|
|
613
|
-
| `getDealByEmail`
|
|
614
|
-
| `getDealByEnvelopeId`
|
|
615
|
-
| `updateDealEnvelopeId` | `{ attioDealId, envelopeId }`
|
|
616
|
-
| `getDealByAttioId`
|
|
617
|
-
|
|
618
|
-
**Deal-sync operations:**
|
|
619
|
-
|
|
620
|
-
| Method
|
|
621
|
-
|
|
622
|
-
| `updateDiscoveryData`
|
|
623
|
-
| `updateProposalData`
|
|
624
|
-
| `markProposalSent`
|
|
625
|
-
| `markProposalReviewed`
|
|
626
|
-
| `updateCloseLostReason`
|
|
627
|
-
| `updateFees`
|
|
628
|
-
| `syncDealStage`
|
|
629
|
-
| `setContactNurture`
|
|
630
|
-
| `cancelSchedulesAndHitlByEmail` | `Omit<..., 'organizationId'>`
|
|
631
|
-
| `cancelHitlByDealId`
|
|
632
|
-
| `clearDealFields`
|
|
633
|
-
| `deleteDeal`
|
|
634
|
-
|
|
635
|
-
### Example
|
|
636
|
-
|
|
637
|
-
```typescript
|
|
638
|
-
const deal = await lead.getDealByEmail({ email: 'jane@acme.com' })
|
|
639
|
-
if (!deal) {
|
|
640
|
-
await lead.upsertDeal({
|
|
641
|
-
attioDealId: 'deal-123',
|
|
642
|
-
contactEmail: 'jane@acme.com',
|
|
643
|
-
})
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
// Bulk import contacts
|
|
647
|
-
await lead.bulkImportContacts({
|
|
648
|
-
listId: 'list-abc',
|
|
649
|
-
contacts: [
|
|
650
|
-
{ email: 'a@example.com', firstName: 'Alice' },
|
|
651
|
-
{ email: 'b@example.com', firstName: 'Bob' },
|
|
652
|
-
],
|
|
653
|
-
})
|
|
654
|
-
```
|
|
655
|
-
|
|
656
|
-
---
|
|
657
|
-
|
|
658
|
-
## PDF Adapter
|
|
659
|
-
|
|
660
|
-
Singleton -- 2 methods for rendering PDFDocument structures to files or buffers. No credential required.
|
|
661
|
-
|
|
662
|
-
```typescript
|
|
663
|
-
import { pdf } from '@elevasis/sdk/worker'
|
|
664
|
-
```
|
|
665
|
-
|
|
666
|
-
### Methods
|
|
667
|
-
|
|
668
|
-
| Method
|
|
669
|
-
|
|
670
|
-
| `render`
|
|
671
|
-
| `renderToBuffer` | `{ document, theme? }`
|
|
672
|
-
|
|
673
|
-
### Example
|
|
674
|
-
|
|
675
|
-
```typescript
|
|
676
|
-
// Render to storage (returns a URL)
|
|
677
|
-
const result = await pdf.render({
|
|
678
|
-
document: proposalDocument,
|
|
679
|
-
storage: { bucket: 'acquisition', path: 'proposals/deal-123/proposal.pdf' },
|
|
680
|
-
})
|
|
681
|
-
console.log(result.pdfUrl)
|
|
682
|
-
|
|
683
|
-
// Render to buffer (for inline processing)
|
|
684
|
-
const { buffer } = await pdf.renderToBuffer({
|
|
685
|
-
document: proposalDocument,
|
|
686
|
-
})
|
|
687
|
-
```
|
|
688
|
-
|
|
689
|
-
---
|
|
690
|
-
|
|
691
|
-
## Approval Adapter
|
|
692
|
-
|
|
693
|
-
Singleton -- 2 methods for creating and managing human-in-the-loop (HITL) approval tasks. No credential required.
|
|
694
|
-
|
|
695
|
-
```typescript
|
|
696
|
-
import { approval } from '@elevasis/sdk/worker'
|
|
697
|
-
```
|
|
698
|
-
|
|
699
|
-
### Methods
|
|
700
|
-
|
|
701
|
-
| Method
|
|
702
|
-
|
|
703
|
-
| `create`
|
|
704
|
-
| `deleteByMetadata` | `{ metadata, status? }`
|
|
705
|
-
|
|
706
|
-
### Example
|
|
707
|
-
|
|
708
|
-
```typescript
|
|
709
|
-
// Create an approval gate
|
|
710
|
-
const task = await approval.create({
|
|
711
|
-
actions: [
|
|
712
|
-
{ id: 'approve', label: 'Approve', type: 'primary' },
|
|
713
|
-
{ id: 'reject', label: 'Reject', type: 'danger' },
|
|
714
|
-
],
|
|
715
|
-
context: { dealId: 'deal-123', proposalUrl: 'https://...' },
|
|
716
|
-
description: 'Review proposal for Acme Corp',
|
|
717
|
-
humanCheckpoint: 'proposal-review',
|
|
718
|
-
metadata: { dealId: 'deal-123' },
|
|
719
|
-
})
|
|
720
|
-
|
|
721
|
-
// Clean up stale tasks
|
|
722
|
-
await approval.deleteByMetadata({
|
|
723
|
-
metadata: { dealId: 'deal-123' },
|
|
724
|
-
status: 'pending',
|
|
725
|
-
})
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
---
|
|
729
|
-
|
|
730
|
-
## Execution Adapter
|
|
731
|
-
|
|
732
|
-
Singleton -- 1 method for triggering another resource (workflow or agent) as a nested child execution. No credential required.
|
|
733
|
-
|
|
734
|
-
```typescript
|
|
735
|
-
import { execution } from '@elevasis/sdk/worker'
|
|
736
|
-
```
|
|
737
|
-
|
|
738
|
-
### Method
|
|
739
|
-
|
|
740
|
-
| Method
|
|
741
|
-
|
|
742
|
-
| `trigger` | `{ resourceId, input? }` | `{ success, executionId, output, error? }` |
|
|
743
|
-
|
|
744
|
-
### Example
|
|
745
|
-
|
|
746
|
-
```typescript
|
|
747
|
-
const result = await execution.trigger({
|
|
748
|
-
resourceId: 'send-welcome-sequence',
|
|
749
|
-
input: { userId: newUser.id, email: newUser.email },
|
|
750
|
-
})
|
|
751
|
-
|
|
752
|
-
if (!result.success) {
|
|
753
|
-
throw new Error(`Child workflow failed: ${result.error}`)
|
|
754
|
-
}
|
|
755
|
-
```
|
|
756
|
-
|
|
757
|
-
Nested executions are tracked with depth up to a maximum of 5 levels.
|
|
758
|
-
|
|
759
|
-
---
|
|
760
|
-
|
|
761
|
-
## Email Adapter
|
|
762
|
-
|
|
763
|
-
Singleton -- 1 method for sending platform emails to organization members (from `notifications@elevasis.io`). For client-facing emails, use the Resend or Instantly integration adapters instead.
|
|
764
|
-
|
|
765
|
-
```typescript
|
|
766
|
-
import { email } from '@elevasis/sdk/worker'
|
|
767
|
-
```
|
|
768
|
-
|
|
769
|
-
### Method
|
|
770
|
-
|
|
771
|
-
| Method | Params
|
|
772
|
-
|
|
773
|
-
| `send` | `{ subject, html?, text?, userIds?, targetRole?, targetAll?, replyTo?, tags? }` | `{ sent, failed, errors? }` |
|
|
774
|
-
|
|
775
|
-
### Example
|
|
776
|
-
|
|
777
|
-
```typescript
|
|
778
|
-
// Notify all org members
|
|
779
|
-
await email.send({
|
|
780
|
-
subject: 'New deal closed',
|
|
781
|
-
text: 'Acme Corp has signed the contract.',
|
|
782
|
-
targetAll: true,
|
|
783
|
-
})
|
|
784
|
-
|
|
785
|
-
// Notify specific users
|
|
786
|
-
await email.send({
|
|
787
|
-
subject: 'Action required',
|
|
788
|
-
html: '\<p\>Please review the proposal.\</p\>',
|
|
789
|
-
userIds: ['user-abc', 'user-def'],
|
|
790
|
-
})
|
|
791
|
-
```
|
|
792
|
-
|
|
793
|
-
---
|
|
794
|
-
|
|
795
|
-
## Custom Adapters with `createAdapter`
|
|
796
|
-
|
|
797
|
-
The generic `createAdapter` factory is exported for building adapters for any tool. Define a type map and call the factory.
|
|
798
|
-
|
|
799
|
-
```typescript
|
|
800
|
-
import { createAdapter } from '@elevasis/sdk/worker'
|
|
801
|
-
|
|
802
|
-
// 1. Define a type map
|
|
803
|
-
type MyToolMap = {
|
|
804
|
-
doSomething: { params: { input: string }; result: { output: string } }
|
|
805
|
-
listItems: { params: { limit?: number }; result: { items: string[] } }
|
|
806
|
-
getStatus: { params: Record<string, never>; result: { healthy: boolean } }
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
// 2. Create the adapter
|
|
810
|
-
const myTool = createAdapter<MyToolMap>('my-tool', [
|
|
811
|
-
'doSomething', 'listItems', 'getStatus',
|
|
812
|
-
], 'my-credential') // credential is optional
|
|
813
|
-
|
|
814
|
-
// 3. Use it (fully typed)
|
|
815
|
-
const result = await myTool.doSomething({ input: 'hello' })
|
|
816
|
-
// ^-- { output: string }
|
|
817
|
-
const status = await myTool.getStatus()
|
|
818
|
-
// ^-- { healthy: boolean } (zero-arg because params is Record<string, never>)
|
|
819
|
-
```
|
|
820
|
-
|
|
821
|
-
Method names are compile-time checked against the type map keys -- misspelling a method name is a compile error.
|
|
822
|
-
|
|
823
|
-
---
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
Per-tool method maps are defined once in `@repo/core` as pure types (zero runtime code, browser-safe). A generic `createAdapter` factory generates the full typed adapter from these maps.
|
|
871
|
-
|
|
872
|
-
**Before (hand-written, per-method boilerplate):**
|
|
873
|
-
|
|
874
|
-
```typescript
|
|
875
|
-
export function createAttioAdapter(credential: string) {
|
|
876
|
-
return {
|
|
877
|
-
createRecord: (params: CreateRecordParams) =>
|
|
878
|
-
platform.call({ tool: 'attio', method: 'createRecord', params, credential }) as Promise<CreateRecordResult>,
|
|
879
|
-
// ... 12 methods, each with manual type import + literal strings + as cast
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
```
|
|
883
|
-
|
|
884
|
-
**After (ToolMap + factory):**
|
|
885
|
-
|
|
886
|
-
```typescript
|
|
887
|
-
import { createAdapter } from './create-adapter.js'
|
|
888
|
-
import type { AttioToolMap } from '../../types/index.js'
|
|
889
|
-
|
|
890
|
-
export function createAttioAdapter(credential: string) {
|
|
891
|
-
return createAdapter<AttioToolMap>('attio', METHODS, credential)
|
|
892
|
-
}
|
|
893
|
-
```
|
|
894
|
-
|
|
895
|
-
The `methods` array is constrained to `(keyof TMap & string)[]` -- misspelling a method name is a compile error.
|
|
896
|
-
|
|
897
|
-
### Type Sharing Strategy
|
|
898
|
-
|
|
899
|
-
Types are defined once in `@repo/core` and shared across SDK and server:
|
|
900
|
-
|
|
901
|
-
```
|
|
902
|
-
packages/core/src/execution/engine/tools/
|
|
903
|
-
tool-maps.ts <-- 16 ToolMap type definitions (browser-safe)
|
|
904
|
-
integration/types/
|
|
905
|
-
attio.ts, stripe.ts, notion.ts, google-sheets.ts
|
|
906
|
-
instantly.ts, signature-api.ts, resend.ts, dropbox.ts
|
|
907
|
-
apify.ts, gmail.ts, mailso.ts
|
|
908
|
-
index.ts <-- barrel export (all 12 integrations)
|
|
909
|
-
platform/storage/types.ts <-- Storage Zod schemas and inferred types
|
|
910
|
-
```
|
|
911
|
-
|
|
912
|
-
**Export chain:**
|
|
913
|
-
|
|
914
|
-
1. Types defined in `@repo/core` (browser-safe locations)
|
|
915
|
-
2. ToolMaps reference these types in `tools/tool-maps.ts`
|
|
916
|
-
3. Exported via `packages/core/src/execution/engine/index.ts`
|
|
917
|
-
4. Available at `@repo/core/execution` subpath
|
|
918
|
-
5. `packages/sdk/src/types/index.ts` re-exports named types
|
|
919
|
-
6. SDK adapters import from `../../types/index.js`
|
|
920
|
-
|
|
921
|
-
---
|
|
922
|
-
|
|
923
|
-
## Design Decisions
|
|
924
|
-
|
|
925
|
-
### ToolMap + Generic Factory
|
|
926
|
-
|
|
927
|
-
All adapters (except LLM) use `createAdapter<TMap>()` instead of hand-written method objects:
|
|
928
|
-
|
|
929
|
-
- Method names are compile-time checked against ToolMap keys (misspelling = compile error)
|
|
930
|
-
- No manual `as Promise<T>` casts -- `TypedAdapter` mapped type handles it
|
|
931
|
-
- Adding a method = one entry in the ToolMap type + one string in the methods array
|
|
932
|
-
|
|
933
|
-
### Factory with Credential Binding
|
|
934
|
-
|
|
935
|
-
Integration adapters use `createXxxAdapter(credential)` pattern:
|
|
936
|
-
|
|
937
|
-
- Credential is bound once, not repeated on every call
|
|
938
|
-
- Mirrors how `createIntegrationTool(credentialName)` works server-side
|
|
939
|
-
- Multiple adapters for same integration with different credentials work simultaneously
|
|
940
|
-
|
|
941
|
-
### LLM Adapter is Hand-Written
|
|
942
|
-
|
|
943
|
-
The LLM adapter stays hand-written because its `generate()` method uses a generic `<T>` for typed output that cannot be expressed in a static ToolMap:
|
|
944
|
-
|
|
945
|
-
```typescript
|
|
946
|
-
generate: <T = unknown>(params: Omit<LLMGenerateRequest, 'signal'>) =>
|
|
947
|
-
platform.call({ tool: 'llm', method: 'generate', params }) as Promise<LLMGenerateResponse<T>>
|
|
948
|
-
```
|
|
949
|
-
|
|
950
|
-
### Name Collision and Browser Safety
|
|
951
|
-
|
|
952
|
-
- **Gmail/Resend prefix**: Both integrations have `SendEmailParams`/`SendEmailResult`. Gmail types use `Gmail*` prefix, Resend types use `Resend*` prefix.
|
|
953
|
-
- **Mailso prefix**: `Mailso*` prefix for namespace clarity.
|
|
954
|
-
- **Browser safety**: `UploadFileParams.contents` and `DownloadDocumentResult.content` use `Uint8Array` instead of Node.js `Buffer`. Server adapters still use `Buffer` internally.
|
|
955
|
-
- **Snake\_case preservation**: Instantly types preserve snake\_case field names (`lead_email`, `campaign_id`) because the server adapter sends them as-is to the Instantly API.
|
|
956
|
-
- **No server-side changes**: All 11 server adapters keep their local type definitions. Shared types are additive.
|
|
957
|
-
|
|
958
|
-
### `NotificationSDKInput` Derived from Core
|
|
959
|
-
|
|
960
|
-
`NotificationSDKInput` is `Omit<CreateNotificationParams, 'userId' | 'organizationId'>` -- derived from the canonical core type, not a local duplicate. Re-exported as `NotificationInput` for backward compatibility.
|
|
961
|
-
|
|
962
|
-
---
|
|
963
|
-
|
|
964
|
-
## Known Issues
|
|
965
|
-
|
|
966
|
-
### Attio `listRecords` Type Mismatch (Server-Side Only)
|
|
967
|
-
|
|
968
|
-
The server-side `attio-adapter.ts` defines a local `ListRecordsParams` with `filter?: Record<string, unknown>`, which is weaker than the shared `QueryRecordsParams` with `filter?: FilterExpression`. The SDK adapter correctly uses `QueryRecordsParams`. Updating `attio-adapter.ts` to use shared types is separate refactoring work.
|
|
969
|
-
|
|
970
|
-
### Dispatcher Still Untyped
|
|
971
|
-
|
|
972
|
-
`tool-dispatcher.ts` still uses `eslint-disable @typescript-eslint/no-explicit-any`. The same ToolMap types could be used server-side to type the dispatcher's switch cases. Future improvement.
|
|
973
|
-
|
|
974
|
-
### Intentionally Not Migrated
|
|
975
|
-
|
|
976
|
-
- `full-diagnostic.ts` and `integration-test.ts` -- use generic `platform.call()` loops for connectivity testing
|
|
977
|
-
- All `supabase`, `session-memory`, `hitl`, `status`, `http` calls -- no typed adapters exist (platform-internal tools)
|
|
978
|
-
|
|
979
|
-
---
|
|
980
|
-
|
|
981
|
-
## Official SDK Comparison
|
|
982
|
-
|
|
983
|
-
| Adapter | Official SDK | Strategy Used | Mirror Accuracy |
|
|
984
|
-
|---------|-------------|---------------|-----------------|
|
|
985
|
-
| Attio | None exists | Raw HTTP fetch | Exact -- endpoints and body shapes match Attio v2 REST API |
|
|
986
|
-
| Stripe | `stripe` (official) | Official SDK | Exact -- uses `stripe.paymentLinks.*`, `stripe.checkout.sessions.*` |
|
|
987
|
-
| Notion | `@notionhq/client` (official) | Official SDK | High -- uses `notion.pages.*`, `notion.blocks.*`; custom method names |
|
|
988
|
-
| Google Sheets | `@googleapis/sheets` (official) | Official SDK + helpers | High -- adds 7 workflow-friendly helpers on top of raw SDK |
|
|
989
|
-
| Apify | `apify-client` exists, not used | Raw HTTP fetch | N/A -- custom polling loop |
|
|
990
|
-
| Resend | `resend` exists, not used | Raw HTTP fetch | High -- matches REST API surface |
|
|
991
|
-
| Gmail | `@googleapis/gmail` (official) | Official SDK | High -- parallel to Sheets pattern |
|
|
992
|
-
|
|
993
|
-
---
|
|
994
|
-
|
|
995
|
-
## When to Use Adapters vs `platform.call()`
|
|
996
|
-
|
|
997
|
-
| Scenario | Use |
|
|
998
|
-
|----------|-----|
|
|
999
|
-
| Tool has a typed adapter (all integrations + platform tools) | Adapter |
|
|
1000
|
-
| Need autocomplete and type safety | Adapter |
|
|
1001
|
-
| New dispatcher method added server-side, no SDK update yet | `platform.call()` |
|
|
1002
|
-
| Tool without a typed adapter (supabase, session-memory, status, http) | `platform.call()` |
|
|
1003
|
-
|
|
1004
|
-
`platform.call()` remains the universal escape hatch. Every adapter call compiles down to it. Both approaches work simultaneously with no conflicts.
|
|
1005
|
-
|
|
1006
|
-
---
|
|
1007
|
-
|
|
1008
|
-
## Available Platform Tools (Full Inventory)
|
|
1009
|
-
|
|
1010
|
-
Not all platform tools have typed adapters. Here is the complete list of tools accessible via `platform.call()`:
|
|
1011
|
-
|
|
1012
|
-
### Integration Adapters (credential required)
|
|
1013
|
-
|
|
1014
|
-
| Tool | Typed Adapter | Methods | Credential Shape |
|
|
1015
|
-
|------|--------------|---------|-----------------|
|
|
1016
|
-
| `attio` | `createAttioAdapter` | 12 (CRUD + schema + notes) | `{ apiKey }` |
|
|
1017
|
-
| `google-sheets` | `createGoogleSheetsAdapter` | 13 (read/write/filter/upsert) | OAuth2 / service account |
|
|
1018
|
-
| `notion` | `createNotionAdapter` | 8 (pages + blocks) | `{ token }` |
|
|
1019
|
-
| `stripe` | `createStripeAdapter` | 6 (payment links + checkout) | `{ secretKey }` |
|
|
1020
|
-
| `instantly` | `createInstantlyAdapter` | 5 (email campaigns) | `{ apiKey }` |
|
|
1021
|
-
| `signature-api` | `createSignatureApiAdapter` | 4 (envelopes) | `{ apiKey }` |
|
|
1022
|
-
| `resend` | `createResendAdapter` | 2 (send/get email) | `{ apiKey }` |
|
|
1023
|
-
| `dropbox` | `createDropboxAdapter` | 2 (upload/folder) | `{ accessToken }` |
|
|
1024
|
-
| `apify` | `createApifyAdapter` | 1 (run actor) | `{ token }` |
|
|
1025
|
-
| `gmail` | `createGmailAdapter` | 1 (send email) | OAuth2 / service account |
|
|
1026
|
-
| `mailso` | `createMailsoAdapter` | 1 (verify email) | `{ apiKey }` |
|
|
1027
|
-
| `supabase` | -- | 7 (insert/select/update/delete/upsert/rpc/count) | `{ url, serviceRoleKey }` |
|
|
1028
|
-
|
|
1029
|
-
### Platform Services (no credential)
|
|
1030
|
-
|
|
1031
|
-
| Tool | Typed Adapter | Methods |
|
|
1032
|
-
|------|--------------|---------|
|
|
1033
|
-
| `scheduler` | `scheduler` | `createSchedule`, `updateAnchor`, `deleteSchedule`, `findByIdempotencyKey`, `deleteScheduleByIdempotencyKey`, `listSchedules`, `getSchedule`, `cancelSchedule`, `cancelSchedulesByMetadata` |
|
|
1034
|
-
| `storage` | `storage` | `upload`, `download`, `createSignedUrl`, `delete`, `list` |
|
|
1035
|
-
| `notification` | `notifications` | `create` |
|
|
1036
|
-
| `llm` | `llm` | `generate` |
|
|
1037
|
-
| `lead` | `lead` | 35 methods (lists, companies, contacts, deals, deal-sync) |
|
|
1038
|
-
| `email` | `email` | `send` |
|
|
1039
|
-
| `pdf` | `pdf` | `render`, `renderToBuffer` |
|
|
1040
|
-
| `approval` | `approval` | `create`, `deleteByMetadata` |
|
|
1041
|
-
| `execution` | `execution` | `trigger` |
|
|
1042
|
-
| `http` | -- | Raw HTTP with server-side credential injection |
|
|
1043
|
-
| `status` | -- | `overview` |
|
|
1044
|
-
| `session-memory` | -- | `load`, `save` |
|
|
1045
|
-
|
|
1046
|
-
---
|
|
1047
|
-
|
|
1048
|
-
## Error Handling
|
|
1049
|
-
|
|
1050
|
-
All adapter calls throw `PlatformToolError` on failure, with a `code` field and `retryable` flag:
|
|
1051
|
-
|
|
1052
|
-
```typescript
|
|
1053
|
-
import { PlatformToolError } from '@elevasis/sdk/worker'
|
|
1054
|
-
|
|
1055
|
-
try {
|
|
1056
|
-
await attio.listRecords({ object: 'deals' })
|
|
1057
|
-
} catch (err) {
|
|
1058
|
-
if (err instanceof PlatformToolError) {
|
|
1059
|
-
console.log(err.message) // Human-readable error
|
|
1060
|
-
console.log(err.code) // e.g., 'rate_limit_exceeded', 'credentials_missing'
|
|
1061
|
-
console.log(err.retryable) // true for transient errors
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
```
|
|
1065
|
-
|
|
1066
|
-
Retryable error codes: `rate_limit_exceeded`, `network_error`, `timeout_error`, `api_error`, `service_unavailable`, `server_unavailable`.
|
|
1067
|
-
|
|
1068
|
-
Timeouts: LLM calls have a 120s timeout. All other tool calls have a 60s timeout.
|
|
1069
|
-
|
|
1070
|
-
---
|
|
1071
|
-
|
|
1072
|
-
**Last Updated:** 2026-03-05
|
|
1
|
+
---
|
|
2
|
+
title: Typed Adapters
|
|
3
|
+
description: Type-safe wrappers over platform.call() for all integrations and platform tools -- Attio, Stripe, Notion, Google Sheets, and more -- with full autocomplete, compile-time checking, and zero boilerplate
|
|
4
|
+
loadWhen: "Using typed adapters instead of raw platform.call(), or needs to know what adapter methods are available"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Typed adapters are ergonomic wrappers over `platform.call()` that provide full TypeScript autocomplete and compile-time type checking. They eliminate stringly-typed method names, manual `as Promise<T>` casts, and repeated credential passing.
|
|
8
|
+
|
|
9
|
+
Both patterns work simultaneously -- adapters compile down to `platform.call()` with zero runtime overhead.
|
|
10
|
+
|
|
11
|
+
**Coverage:** 11 integration adapters (55 methods) + 9 platform tool adapters (57 methods) = 112 total typed methods.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// Before: raw platform.call()
|
|
15
|
+
const records = await platform.call({
|
|
16
|
+
tool: 'attio',
|
|
17
|
+
method: 'listRecords',
|
|
18
|
+
credential: 'my-attio',
|
|
19
|
+
params: { object: 'deals' }
|
|
20
|
+
}) as unknown as QueryRecordsResult
|
|
21
|
+
|
|
22
|
+
// After: typed adapter
|
|
23
|
+
const attio = createAttioAdapter('my-attio')
|
|
24
|
+
const records = await attio.listRecords({ object: 'deals' })
|
|
25
|
+
// ^-- QueryRecordsResult (fully typed, autocomplete on params)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
All adapters are imported from `@elevasis/sdk/worker` -- the same subpath as `platform`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Quick Reference
|
|
33
|
+
|
|
34
|
+
### Integration Adapters (factory pattern, credential required)
|
|
35
|
+
|
|
36
|
+
| Import | Methods |
|
|
37
|
+
| --------------------------------- | ------- |
|
|
38
|
+
| `createAttioAdapter(cred)` | 12 |
|
|
39
|
+
| `createStripeAdapter(cred)` | 6 |
|
|
40
|
+
| `createNotionAdapter(cred)` | 8 |
|
|
41
|
+
| `createGoogleSheetsAdapter(cred)` | 13 |
|
|
42
|
+
| `createInstantlyAdapter(cred)` | 5 |
|
|
43
|
+
| `createSignatureApiAdapter(cred)` | 4 |
|
|
44
|
+
| `createResendAdapter(cred)` | 2 |
|
|
45
|
+
| `createDropboxAdapter(cred)` | 2 |
|
|
46
|
+
| `createApifyAdapter(cred)` | 1 |
|
|
47
|
+
| `createGmailAdapter(cred)` | 1 |
|
|
48
|
+
| `createMailsoAdapter(cred)` | 1 |
|
|
49
|
+
|
|
50
|
+
### Platform Adapters (singletons, no credential)
|
|
51
|
+
|
|
52
|
+
| Import | Methods |
|
|
53
|
+
| --------------- | ------- |
|
|
54
|
+
| `lead` | 35 |
|
|
55
|
+
| `scheduler` | 9 |
|
|
56
|
+
| `storage` | 5 |
|
|
57
|
+
| `pdf` | 2 |
|
|
58
|
+
| `approval` | 2 |
|
|
59
|
+
| `notifications` | 1 |
|
|
60
|
+
| `llm` | 1 |
|
|
61
|
+
| `execution` | 1 |
|
|
62
|
+
| `email` | 1 |
|
|
63
|
+
|
|
64
|
+
### Generic Factory
|
|
65
|
+
|
|
66
|
+
| Import | Description |
|
|
67
|
+
| --------------------------------------------- | ---------------------------------- |
|
|
68
|
+
| `createAdapter<TMap>(tool, methods, cred?)` | Build custom adapters for any tool |
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import {
|
|
72
|
+
// Integration adapters
|
|
73
|
+
createAttioAdapter, createStripeAdapter, createNotionAdapter,
|
|
74
|
+
createGoogleSheetsAdapter, createInstantlyAdapter,
|
|
75
|
+
createSignatureApiAdapter, createResendAdapter, createDropboxAdapter,
|
|
76
|
+
createApifyAdapter, createGmailAdapter, createMailsoAdapter,
|
|
77
|
+
// Platform adapters
|
|
78
|
+
lead, scheduler, storage, pdf, approval, notifications, llm, execution, email,
|
|
79
|
+
// Generic factory
|
|
80
|
+
createAdapter,
|
|
81
|
+
} from '@elevasis/sdk/worker'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Attio CRM Adapter
|
|
87
|
+
|
|
88
|
+
Factory pattern -- bind a credential once, use 12 typed methods.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
const attio = createAttioAdapter('my-attio-credential')
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Methods
|
|
95
|
+
|
|
96
|
+
| Method | Params | Returns |
|
|
97
|
+
| ----------------- | ----------------------- | ----------------------- |
|
|
98
|
+
| `createRecord` | `CreateRecordParams` | `CreateRecordResult` |
|
|
99
|
+
| `updateRecord` | `UpdateRecordParams` | `UpdateRecordResult` |
|
|
100
|
+
| `listRecords` | `QueryRecordsParams` | `QueryRecordsResult` |
|
|
101
|
+
| `getRecord` | `GetRecordParams` | `GetRecordResult` |
|
|
102
|
+
| `deleteRecord` | `DeleteRecordParams` | `DeleteRecordResult` |
|
|
103
|
+
| `listObjects` | none | `ListObjectsResult` |
|
|
104
|
+
| `listAttributes` | `ListAttributesParams` | `ListAttributesResult` |
|
|
105
|
+
| `createAttribute` | `CreateAttributeParams` | `CreateAttributeResult` |
|
|
106
|
+
| `updateAttribute` | `UpdateAttributeParams` | `UpdateAttributeResult` |
|
|
107
|
+
| `createNote` | `CreateNoteParams` | `CreateNoteResult` |
|
|
108
|
+
| `listNotes` | `ListNotesParams` | `ListNotesResult` |
|
|
109
|
+
| `deleteNote` | `DeleteNoteParams` | `DeleteNoteResult` |
|
|
110
|
+
|
|
111
|
+
### Examples
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Create a company record
|
|
115
|
+
const company = await attio.createRecord({
|
|
116
|
+
object: 'companies',
|
|
117
|
+
values: {
|
|
118
|
+
name: [{ value: 'Acme Corp' }],
|
|
119
|
+
domains: [{ domain: 'acme.com' }],
|
|
120
|
+
},
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
// Query deals with filters
|
|
124
|
+
const deals = await attio.listRecords({
|
|
125
|
+
object: 'deals',
|
|
126
|
+
filter: {
|
|
127
|
+
operator: 'and',
|
|
128
|
+
filters: [
|
|
129
|
+
{ field: 'stage', operator: 'equals', value: 'proposal' },
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
sorts: [{ field: 'created_at', direction: 'desc' }],
|
|
133
|
+
limit: 20,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// Get a specific record
|
|
137
|
+
const record = await attio.getRecord({
|
|
138
|
+
object: 'people',
|
|
139
|
+
recordId: 'rec_abc123',
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// List all objects (no params)
|
|
143
|
+
const objects = await attio.listObjects()
|
|
144
|
+
|
|
145
|
+
// Create a note on a record
|
|
146
|
+
await attio.createNote({
|
|
147
|
+
parentObject: 'deals',
|
|
148
|
+
parentRecordId: 'rec_abc123',
|
|
149
|
+
title: 'Discovery call notes',
|
|
150
|
+
content: 'Key takeaways from the call...',
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Multiple adapters with different credentials work simultaneously:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const prodAttio = createAttioAdapter('prod-attio')
|
|
158
|
+
const testAttio = createAttioAdapter('test-attio')
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Stripe Adapter
|
|
164
|
+
|
|
165
|
+
Factory pattern -- 6 methods for payment links and checkout sessions.
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const stripe = createStripeAdapter('my-stripe-credential')
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Methods
|
|
172
|
+
|
|
173
|
+
| Method | Params | Returns |
|
|
174
|
+
| ----------------------- | ----------------------------- | ----------------------------- |
|
|
175
|
+
| `createPaymentLink` | `CreatePaymentLinkParams` | `CreatePaymentLinkResult` |
|
|
176
|
+
| `getPaymentLink` | `GetPaymentLinkParams` | `GetPaymentLinkResult` |
|
|
177
|
+
| `updatePaymentLink` | `UpdatePaymentLinkParams` | `UpdatePaymentLinkResult` |
|
|
178
|
+
| `listPaymentLinks` | `ListPaymentLinksParams` | `ListPaymentLinksResult` |
|
|
179
|
+
| `createAutoPaymentLink` | `CreateAutoPaymentLinkParams` | `CreateAutoPaymentLinkResult` |
|
|
180
|
+
| `createCheckoutSession` | `CreateCheckoutSessionParams` | `CreateCheckoutSessionResult` |
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Notion Adapter
|
|
185
|
+
|
|
186
|
+
Factory pattern -- 8 methods for page and block operations.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
const notion = createNotionAdapter('my-notion-credential')
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Methods
|
|
193
|
+
|
|
194
|
+
| Method | Params | Returns |
|
|
195
|
+
| ----------------- | ----------------------- | ----------------------- |
|
|
196
|
+
| `listAllPages` | none | `ListAllPagesResult` |
|
|
197
|
+
| `readPage` | `ReadPageParams` | `ReadPageResult` |
|
|
198
|
+
| `createPage` | `CreatePageParams` | `CreatePageResult` |
|
|
199
|
+
| `updatePageTitle` | `UpdatePageTitleParams` | `UpdatePageTitleResult` |
|
|
200
|
+
| `appendBlocks` | `AppendBlocksParams` | `AppendBlocksResult` |
|
|
201
|
+
| `updateBlocks` | `UpdateBlocksParams` | `UpdateBlocksResult` |
|
|
202
|
+
| `deletePage` | `DeletePageParams` | `DeletePageResult` |
|
|
203
|
+
| `deleteBlocks` | `DeleteBlocksParams` | `DeleteBlocksResult` |
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Google Sheets Adapter
|
|
208
|
+
|
|
209
|
+
Factory pattern -- 13 methods including workflow-friendly helpers (getRowByValue, upsertRow, filterRows).
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
const sheets = createGoogleSheetsAdapter('my-google-credential')
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Methods
|
|
216
|
+
|
|
217
|
+
| Method | Params | Returns |
|
|
218
|
+
| ------------------------ | ------------------------------ | ------------------------------ |
|
|
219
|
+
| `readSheet` | `ReadSheetParams` | `ReadSheetResult` |
|
|
220
|
+
| `writeSheet` | `WriteSheetParams` | `WriteSheetResult` |
|
|
221
|
+
| `appendRows` | `AppendRowsParams` | `AppendRowsResult` |
|
|
222
|
+
| `clearRange` | `ClearRangeParams` | `ClearRangeResult` |
|
|
223
|
+
| `getSpreadsheetMetadata` | `GetSpreadsheetMetadataParams` | `GetSpreadsheetMetadataResult` |
|
|
224
|
+
| `batchUpdate` | `BatchUpdateParams` | `BatchUpdateResult` |
|
|
225
|
+
| `getHeaders` | `GetHeadersParams` | `GetHeadersResult` |
|
|
226
|
+
| `getLastRow` | `GetLastRowParams` | `GetLastRowResult` |
|
|
227
|
+
| `getRowByValue` | `GetRowByValueParams` | `GetRowByValueResult` |
|
|
228
|
+
| `updateRowByValue` | `UpdateRowByValueParams` | `UpdateRowByValueResult` |
|
|
229
|
+
| `upsertRow` | `UpsertRowParams` | `UpsertRowResult` |
|
|
230
|
+
| `filterRows` | `FilterRowsParams` | `FilterRowsResult` |
|
|
231
|
+
| `deleteRowByValue` | `DeleteRowByValueParams` | `DeleteRowByValueResult` |
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Instantly Adapter
|
|
236
|
+
|
|
237
|
+
Factory pattern -- 5 methods for email campaign management.
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
const instantly = createInstantlyAdapter('my-instantly-credential')
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Methods
|
|
244
|
+
|
|
245
|
+
| Method | Params | Returns |
|
|
246
|
+
| ----------------------- | ----------------------------- | ----------------------------- |
|
|
247
|
+
| `sendReply` | `SendReplyParams` | `SendReplyResult` |
|
|
248
|
+
| `removeFromSubsequence` | `RemoveFromSubsequenceParams` | `RemoveFromSubsequenceResult` |
|
|
249
|
+
| `getEmails` | `GetEmailsParams` | `GetEmailsResult` |
|
|
250
|
+
| `updateInterestStatus` | `UpdateInterestStatusParams` | `UpdateInterestStatusResult` |
|
|
251
|
+
| `addToCampaign` | `AddToCampaignParams` | `AddToCampaignResult` |
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## SignatureAPI Adapter
|
|
256
|
+
|
|
257
|
+
Factory pattern -- 4 methods for eSignature envelope operations.
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
const signatureApi = createSignatureApiAdapter('my-signatureapi-credential')
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Methods
|
|
264
|
+
|
|
265
|
+
| Method | Params | Returns |
|
|
266
|
+
| ------------------ | ------------------------ | ------------------------ |
|
|
267
|
+
| `createEnvelope` | `CreateEnvelopeParams` | `CreateEnvelopeResult` |
|
|
268
|
+
| `voidEnvelope` | `VoidEnvelopeParams` | `VoidEnvelopeResult` |
|
|
269
|
+
| `downloadDocument` | `DownloadDocumentParams` | `DownloadDocumentResult` |
|
|
270
|
+
| `getEnvelope` | `GetEnvelopeParams` | `GetEnvelopeResult` |
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Resend Adapter
|
|
275
|
+
|
|
276
|
+
Factory pattern -- 2 methods for transactional email.
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
const resend = createResendAdapter('my-resend-credential')
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Methods
|
|
283
|
+
|
|
284
|
+
| Method | Params | Returns |
|
|
285
|
+
| ----------- | ----------------------- | ----------------------- |
|
|
286
|
+
| `sendEmail` | `ResendSendEmailParams` | `ResendSendEmailResult` |
|
|
287
|
+
| `getEmail` | `ResendGetEmailParams` | `ResendGetEmailResult` |
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Dropbox Adapter
|
|
292
|
+
|
|
293
|
+
Factory pattern -- 2 methods for file operations.
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
const dropbox = createDropboxAdapter('my-dropbox-credential')
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Methods
|
|
300
|
+
|
|
301
|
+
| Method | Params | Returns |
|
|
302
|
+
| -------------- | -------------------- | -------------------- |
|
|
303
|
+
| `uploadFile` | `UploadFileParams` | `UploadFileResult` |
|
|
304
|
+
| `createFolder` | `CreateFolderParams` | `CreateFolderResult` |
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Apify Adapter
|
|
309
|
+
|
|
310
|
+
Factory pattern -- 1 method for running web scraping actors.
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
const apify = createApifyAdapter('my-apify-credential')
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Methods
|
|
317
|
+
|
|
318
|
+
| Method | Params | Returns |
|
|
319
|
+
| ---------- | ---------------- | ---------------- |
|
|
320
|
+
| `runActor` | `RunActorParams` | `RunActorResult` |
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Gmail Adapter
|
|
325
|
+
|
|
326
|
+
Factory pattern -- 1 method for sending email via Gmail API.
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
const gmail = createGmailAdapter('my-gmail-credential')
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Methods
|
|
333
|
+
|
|
334
|
+
| Method | Params | Returns |
|
|
335
|
+
| ----------- | ---------------------- | ---------------------- |
|
|
336
|
+
| `sendEmail` | `GmailSendEmailParams` | `GmailSendEmailResult` |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Mailso Adapter
|
|
341
|
+
|
|
342
|
+
Factory pattern -- 1 method for email verification.
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
const mailso = createMailsoAdapter('my-mailso-credential')
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Methods
|
|
349
|
+
|
|
350
|
+
| Method | Params | Returns |
|
|
351
|
+
| ------------- | ------------------------- | ------------------------- |
|
|
352
|
+
| `verifyEmail` | `MailsoVerifyEmailParams` | `MailsoVerifyEmailResult` |
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Scheduler Adapter
|
|
357
|
+
|
|
358
|
+
Singleton -- 9 methods for task schedule management.
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
import { scheduler } from '@elevasis/sdk/worker'
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Methods
|
|
365
|
+
|
|
366
|
+
| Method | Params | Returns |
|
|
367
|
+
| -------------------------------- | ------------------------------ | ---------------------- |
|
|
368
|
+
| `createSchedule` | `CreateScheduleInput` | `TaskSchedule` |
|
|
369
|
+
| `updateAnchor` | `{ scheduleId, anchorAt }` | `TaskSchedule` |
|
|
370
|
+
| `deleteSchedule` | `{ scheduleId }` | `void` |
|
|
371
|
+
| `findByIdempotencyKey` | `{ idempotencyKey }` | `TaskSchedule | null` |
|
|
372
|
+
| `deleteScheduleByIdempotencyKey` | `{ idempotencyKey }` | `void` |
|
|
373
|
+
| `listSchedules` | `{ status?, limit?, offset? }` | `TaskSchedule[]` |
|
|
374
|
+
| `getSchedule` | `{ scheduleId }` | `TaskSchedule` |
|
|
375
|
+
| `cancelSchedule` | `{ scheduleId }` | `void` |
|
|
376
|
+
| `cancelSchedulesByMetadata` | `{ metadata }` | `{ cancelledCount }` |
|
|
377
|
+
|
|
378
|
+
### Examples
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// Create a relative schedule (follow-up sequence)
|
|
382
|
+
const schedule = await scheduler.createSchedule({
|
|
383
|
+
organizationId: context.organizationId,
|
|
384
|
+
name: 'Proposal follow-up',
|
|
385
|
+
target: { resourceType: 'workflow', resourceId: 'send-followup' },
|
|
386
|
+
scheduleConfig: {
|
|
387
|
+
type: 'relative',
|
|
388
|
+
anchorAt: '2026-03-15T10:00:00Z',
|
|
389
|
+
anchorLabel: 'proposal_sent_date',
|
|
390
|
+
items: [
|
|
391
|
+
{ offset: '+3d', payload: { step: 'first-followup' }, label: 'First follow-up' },
|
|
392
|
+
{ offset: '+7d', payload: { step: 'second-followup' }, label: 'Second follow-up' },
|
|
393
|
+
],
|
|
394
|
+
},
|
|
395
|
+
metadata: { dealId: 'deal-123', contactEmail: 'jane@acme.com' },
|
|
396
|
+
idempotencyKey: 'proposal-followup-deal-123',
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
// Reschedule (update anchor)
|
|
400
|
+
await scheduler.updateAnchor({
|
|
401
|
+
scheduleId: schedule.id,
|
|
402
|
+
anchorAt: '2026-03-20T10:00:00Z',
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
// Find by idempotency key (check if already created)
|
|
406
|
+
const existing = await scheduler.findByIdempotencyKey({
|
|
407
|
+
idempotencyKey: 'proposal-followup-deal-123',
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
// Cancel all schedules matching metadata
|
|
411
|
+
await scheduler.cancelSchedulesByMetadata({
|
|
412
|
+
metadata: { dealId: 'deal-123' },
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
// List active schedules
|
|
416
|
+
const schedules = await scheduler.listSchedules({
|
|
417
|
+
status: 'active',
|
|
418
|
+
limit: 50,
|
|
419
|
+
})
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Storage Adapter
|
|
425
|
+
|
|
426
|
+
Singleton -- 5 methods for file storage operations.
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
import { storage } from '@elevasis/sdk/worker'
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
All paths are relative to the organization's storage prefix. The platform injects the organization prefix server-side.
|
|
433
|
+
|
|
434
|
+
### Methods
|
|
435
|
+
|
|
436
|
+
| Method | Params | Returns |
|
|
437
|
+
| ----------------- | ----------------------- | ------------------------ |
|
|
438
|
+
| `upload` | `StorageUploadInput` | `StorageUploadOutput` |
|
|
439
|
+
| `download` | `StorageDownloadInput` | `StorageDownloadOutput` |
|
|
440
|
+
| `createSignedUrl` | `StorageSignedUrlInput` | `StorageSignedUrlOutput` |
|
|
441
|
+
| `delete` | `StorageDeleteInput` | `StorageDeleteOutput` |
|
|
442
|
+
| `list` | `StorageListInput` | `StorageListOutput` |
|
|
443
|
+
|
|
444
|
+
### Examples
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
// Upload a PDF
|
|
448
|
+
await storage.upload({
|
|
449
|
+
bucket: 'acquisition',
|
|
450
|
+
path: 'proposals/deal-123/proposal.pdf',
|
|
451
|
+
content: base64PdfContent,
|
|
452
|
+
contentType: 'application/pdf',
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
// Generate a signed URL (temporary access)
|
|
456
|
+
const { signedUrl } = await storage.createSignedUrl({
|
|
457
|
+
bucket: 'acquisition',
|
|
458
|
+
path: 'proposals/deal-123/proposal.pdf',
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
// Download a file
|
|
462
|
+
const file = await storage.download({
|
|
463
|
+
bucket: 'acquisition',
|
|
464
|
+
path: 'proposals/deal-123/proposal.pdf',
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
// List files under a prefix
|
|
468
|
+
const files = await storage.list({
|
|
469
|
+
bucket: 'acquisition',
|
|
470
|
+
path: 'proposals/deal-123/',
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
// Delete a file
|
|
474
|
+
await storage.delete({
|
|
475
|
+
bucket: 'acquisition',
|
|
476
|
+
path: 'proposals/deal-123/old-proposal.pdf',
|
|
477
|
+
})
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## Notification Adapter
|
|
483
|
+
|
|
484
|
+
Singleton -- 1 method for sending in-app team notifications.
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
import { notifications } from '@elevasis/sdk/worker'
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
`userId` and `organizationId` are injected server-side from the execution context -- you never pass them.
|
|
491
|
+
|
|
492
|
+
### Method
|
|
493
|
+
|
|
494
|
+
| Method | Params | Returns |
|
|
495
|
+
| -------- | ---------------------- | ------- |
|
|
496
|
+
| `create` | `NotificationSDKInput` | `void` |
|
|
497
|
+
|
|
498
|
+
`NotificationSDKInput` fields: `category`, `title`, `message`, `actionUrl?`, `metadata?`
|
|
499
|
+
|
|
500
|
+
### Example
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
await notifications.create({
|
|
504
|
+
category: 'acquisition',
|
|
505
|
+
title: 'New lead qualified',
|
|
506
|
+
message: 'Acme Corp has been qualified and moved to proposal stage.',
|
|
507
|
+
actionUrl: '/deals/deal-123',
|
|
508
|
+
})
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## LLM Adapter
|
|
514
|
+
|
|
515
|
+
Singleton -- 1 method with a generic `<T>` for typed structured output.
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
import { llm } from '@elevasis/sdk/worker'
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
No API keys needed -- keys are resolved server-side from environment variables.
|
|
522
|
+
|
|
523
|
+
### Method
|
|
524
|
+
|
|
525
|
+
| Method | Params | Returns |
|
|
526
|
+
| --------------- | -------------------------------------- | -------------------------- |
|
|
527
|
+
| `generate<T>` | `Omit<LLMGenerateRequest, 'signal'>` | `LLMGenerateResponse<T>` |
|
|
528
|
+
|
|
529
|
+
The `signal` property (AbortSignal) is not serializable over the postMessage boundary. Abort is handled at the worker level via the parent process sending an abort message.
|
|
530
|
+
|
|
531
|
+
### Example
|
|
532
|
+
|
|
533
|
+
```typescript
|
|
534
|
+
interface Classification {
|
|
535
|
+
category: 'interested' | 'not-interested' | 'bounced'
|
|
536
|
+
confidence: number
|
|
537
|
+
summary: string
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const response = await llm.generate<Classification>({
|
|
541
|
+
provider: 'anthropic',
|
|
542
|
+
model: 'claude-sonnet-4-5',
|
|
543
|
+
messages: [
|
|
544
|
+
{ role: 'system', content: 'Classify this email reply.' },
|
|
545
|
+
{ role: 'user', content: emailText },
|
|
546
|
+
],
|
|
547
|
+
responseSchema: {
|
|
548
|
+
type: 'object',
|
|
549
|
+
properties: {
|
|
550
|
+
category: { type: 'string', enum: ['interested', 'not-interested', 'bounced'] },
|
|
551
|
+
confidence: { type: 'number', minimum: 0, maximum: 1 },
|
|
552
|
+
summary: { type: 'string' },
|
|
553
|
+
},
|
|
554
|
+
required: ['category', 'confidence', 'summary'],
|
|
555
|
+
},
|
|
556
|
+
temperature: 0.1,
|
|
557
|
+
})
|
|
558
|
+
|
|
559
|
+
// response.output is typed as Classification
|
|
560
|
+
const { category, confidence, summary } = response.output
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## Lead Adapter
|
|
566
|
+
|
|
567
|
+
Singleton -- 35 methods for acquisition lead management (lists, companies, contacts, deals, deal-sync). `organizationId` is injected server-side -- never pass it.
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
import { lead } from '@elevasis/sdk/worker'
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### Methods
|
|
574
|
+
|
|
575
|
+
**List operations:**
|
|
576
|
+
|
|
577
|
+
| Method | Params | Returns |
|
|
578
|
+
| ------------ | -------------------------------------------- | ----------- |
|
|
579
|
+
| `listLists` | none | `AcqList[]` |
|
|
580
|
+
| `createList` | `Omit<CreateListParams, 'organizationId'>` | `AcqList` |
|
|
581
|
+
| `updateList` | `{ id } & UpdateListParams` | `AcqList` |
|
|
582
|
+
| `deleteList` | `{ id }` | `void` |
|
|
583
|
+
|
|
584
|
+
**Company operations:**
|
|
585
|
+
|
|
586
|
+
| Method | Params | Returns |
|
|
587
|
+
| --------------- | ----------------------------------------------- | -------------------- |
|
|
588
|
+
| `createCompany` | `Omit<CreateCompanyParams, 'organizationId'>` | `AcqCompany` |
|
|
589
|
+
| `upsertCompany` | `Omit<UpsertCompanyParams, 'organizationId'>` | `AcqCompany` |
|
|
590
|
+
| `updateCompany` | `{ id } & UpdateCompanyParams` | `AcqCompany` |
|
|
591
|
+
| `getCompany` | `{ id }` | `AcqCompany | null` |
|
|
592
|
+
| `listCompanies` | `{ filters? }` | `AcqCompany[]` |
|
|
593
|
+
| `deleteCompany` | `{ id }` | `void` |
|
|
594
|
+
|
|
595
|
+
**Contact operations:**
|
|
596
|
+
|
|
597
|
+
| Method | Params | Returns |
|
|
598
|
+
| -------------------- | ----------------------------------------------- | ------------------------------- |
|
|
599
|
+
| `createContact` | `Omit<CreateContactParams, 'organizationId'>` | `AcqContact` |
|
|
600
|
+
| `upsertContact` | `Omit<UpsertContactParams, 'organizationId'>` | `AcqContact` |
|
|
601
|
+
| `updateContact` | `{ id } & UpdateContactParams` | `AcqContact` |
|
|
602
|
+
| `getContact` | `{ id }` | `AcqContact | null` |
|
|
603
|
+
| `getContactByEmail` | `{ email }` | `AcqContact | null` |
|
|
604
|
+
| `listContacts` | `{ filters?, pagination? }` | `PaginatedResult<AcqContact>` |
|
|
605
|
+
| `deleteContact` | `{ id }` | `void` |
|
|
606
|
+
| `bulkImportContacts` | `Omit<BulkImportParams, 'organizationId'>` | `BulkImportResult` |
|
|
607
|
+
|
|
608
|
+
**Deal operations:**
|
|
609
|
+
|
|
610
|
+
| Method | Params | Returns |
|
|
611
|
+
| ---------------------- | -------------------------------------------- | ----------------- |
|
|
612
|
+
| `upsertDeal` | `Omit<UpsertDealParams, 'organizationId'>` | `AcqDeal` |
|
|
613
|
+
| `getDealByEmail` | `{ email }` | `AcqDeal | null` |
|
|
614
|
+
| `getDealByEnvelopeId` | `{ envelopeId }` | `AcqDeal | null` |
|
|
615
|
+
| `updateDealEnvelopeId` | `{ attioDealId, envelopeId }` | `AcqDeal | null` |
|
|
616
|
+
| `getDealByAttioId` | `{ attioDealId }` | `AcqDeal | null` |
|
|
617
|
+
|
|
618
|
+
**Deal-sync operations:**
|
|
619
|
+
|
|
620
|
+
| Method | Params | Returns |
|
|
621
|
+
| ------------------------------- | ------------------------------------------------------- | ------------------------------------- |
|
|
622
|
+
| `updateDiscoveryData` | `Omit<UpdateDiscoveryDataParams, 'organizationId'>` | `void` |
|
|
623
|
+
| `updateProposalData` | `Omit<UpdateProposalDataParams, 'organizationId'>` | `void` |
|
|
624
|
+
| `markProposalSent` | `Omit<MarkProposalSentParams, 'organizationId'>` | `void` |
|
|
625
|
+
| `markProposalReviewed` | `Omit<MarkProposalReviewedParams, 'organizationId'>` | `void` |
|
|
626
|
+
| `updateCloseLostReason` | `Omit<UpdateCloseLostReasonParams, 'organizationId'>` | `void` |
|
|
627
|
+
| `updateFees` | `Omit<UpdateFeesParams, 'organizationId'>` | `void` |
|
|
628
|
+
| `syncDealStage` | `Omit<SyncDealStageParams, 'organizationId'>` | `void` |
|
|
629
|
+
| `setContactNurture` | `Omit<SetContactNurtureParams, 'organizationId'>` | `void` |
|
|
630
|
+
| `cancelSchedulesAndHitlByEmail` | `Omit<..., 'organizationId'>` | `{ schedulesCancelled, hitlDeleted }` |
|
|
631
|
+
| `cancelHitlByDealId` | `Omit<..., 'organizationId'>` | `{ hitlDeleted }` |
|
|
632
|
+
| `clearDealFields` | `Omit<ClearDealFieldsParams, 'organizationId'>` | `void` |
|
|
633
|
+
| `deleteDeal` | `Omit<DeleteDealParams, 'organizationId'>` | `void` |
|
|
634
|
+
|
|
635
|
+
### Example
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
const deal = await lead.getDealByEmail({ email: 'jane@acme.com' })
|
|
639
|
+
if (!deal) {
|
|
640
|
+
await lead.upsertDeal({
|
|
641
|
+
attioDealId: 'deal-123',
|
|
642
|
+
contactEmail: 'jane@acme.com',
|
|
643
|
+
})
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Bulk import contacts
|
|
647
|
+
await lead.bulkImportContacts({
|
|
648
|
+
listId: 'list-abc',
|
|
649
|
+
contacts: [
|
|
650
|
+
{ email: 'a@example.com', firstName: 'Alice' },
|
|
651
|
+
{ email: 'b@example.com', firstName: 'Bob' },
|
|
652
|
+
],
|
|
653
|
+
})
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
## PDF Adapter
|
|
659
|
+
|
|
660
|
+
Singleton -- 2 methods for rendering PDFDocument structures to files or buffers. No credential required.
|
|
661
|
+
|
|
662
|
+
```typescript
|
|
663
|
+
import { pdf } from '@elevasis/sdk/worker'
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
### Methods
|
|
667
|
+
|
|
668
|
+
| Method | Params | Returns |
|
|
669
|
+
| ---------------- | ------------------------------------------------- | --------------------------- |
|
|
670
|
+
| `render` | `{ document, theme?, storage: { bucket, path } }` | `{ success, pdfUrl, size }` |
|
|
671
|
+
| `renderToBuffer` | `{ document, theme? }` | `{ buffer }` |
|
|
672
|
+
|
|
673
|
+
### Example
|
|
674
|
+
|
|
675
|
+
```typescript
|
|
676
|
+
// Render to storage (returns a URL)
|
|
677
|
+
const result = await pdf.render({
|
|
678
|
+
document: proposalDocument,
|
|
679
|
+
storage: { bucket: 'acquisition', path: 'proposals/deal-123/proposal.pdf' },
|
|
680
|
+
})
|
|
681
|
+
console.log(result.pdfUrl)
|
|
682
|
+
|
|
683
|
+
// Render to buffer (for inline processing)
|
|
684
|
+
const { buffer } = await pdf.renderToBuffer({
|
|
685
|
+
document: proposalDocument,
|
|
686
|
+
})
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
---
|
|
690
|
+
|
|
691
|
+
## Approval Adapter
|
|
692
|
+
|
|
693
|
+
Singleton -- 2 methods for creating and managing human-in-the-loop (HITL) approval tasks. No credential required.
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
import { approval } from '@elevasis/sdk/worker'
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
### Methods
|
|
700
|
+
|
|
701
|
+
| Method | Params | Returns |
|
|
702
|
+
| ------------------ | ---------------------------------------------------------------------------------------- | ------------- |
|
|
703
|
+
| `create` | `{ actions, context, description?, priority?, humanCheckpoint?, metadata?, expiresAt? }` | `{ id }` |
|
|
704
|
+
| `deleteByMetadata` | `{ metadata, status? }` | `{ deleted }` |
|
|
705
|
+
|
|
706
|
+
### Example
|
|
707
|
+
|
|
708
|
+
```typescript
|
|
709
|
+
// Create an approval gate
|
|
710
|
+
const task = await approval.create({
|
|
711
|
+
actions: [
|
|
712
|
+
{ id: 'approve', label: 'Approve', type: 'primary' },
|
|
713
|
+
{ id: 'reject', label: 'Reject', type: 'danger' },
|
|
714
|
+
],
|
|
715
|
+
context: { dealId: 'deal-123', proposalUrl: 'https://...' },
|
|
716
|
+
description: 'Review proposal for Acme Corp',
|
|
717
|
+
humanCheckpoint: 'proposal-review',
|
|
718
|
+
metadata: { dealId: 'deal-123' },
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
// Clean up stale tasks
|
|
722
|
+
await approval.deleteByMetadata({
|
|
723
|
+
metadata: { dealId: 'deal-123' },
|
|
724
|
+
status: 'pending',
|
|
725
|
+
})
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
## Execution Adapter
|
|
731
|
+
|
|
732
|
+
Singleton -- 1 method for triggering another resource (workflow or agent) as a nested child execution. No credential required.
|
|
733
|
+
|
|
734
|
+
```typescript
|
|
735
|
+
import { execution } from '@elevasis/sdk/worker'
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### Method
|
|
739
|
+
|
|
740
|
+
| Method | Params | Returns |
|
|
741
|
+
| --------- | ------------------------ | ------------------------------------------ |
|
|
742
|
+
| `trigger` | `{ resourceId, input? }` | `{ success, executionId, output, error? }` |
|
|
743
|
+
|
|
744
|
+
### Example
|
|
745
|
+
|
|
746
|
+
```typescript
|
|
747
|
+
const result = await execution.trigger({
|
|
748
|
+
resourceId: 'send-welcome-sequence',
|
|
749
|
+
input: { userId: newUser.id, email: newUser.email },
|
|
750
|
+
})
|
|
751
|
+
|
|
752
|
+
if (!result.success) {
|
|
753
|
+
throw new Error(`Child workflow failed: ${result.error}`)
|
|
754
|
+
}
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
Nested executions are tracked with depth up to a maximum of 5 levels.
|
|
758
|
+
|
|
759
|
+
---
|
|
760
|
+
|
|
761
|
+
## Email Adapter
|
|
762
|
+
|
|
763
|
+
Singleton -- 1 method for sending platform emails to organization members (from `notifications@elevasis.io`). For client-facing emails, use the Resend or Instantly integration adapters instead.
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
import { email } from '@elevasis/sdk/worker'
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
### Method
|
|
770
|
+
|
|
771
|
+
| Method | Params | Returns |
|
|
772
|
+
| ------ | ------------------------------------------------------------------------------- | --------------------------- |
|
|
773
|
+
| `send` | `{ subject, html?, text?, userIds?, targetRole?, targetAll?, replyTo?, tags? }` | `{ sent, failed, errors? }` |
|
|
774
|
+
|
|
775
|
+
### Example
|
|
776
|
+
|
|
777
|
+
```typescript
|
|
778
|
+
// Notify all org members
|
|
779
|
+
await email.send({
|
|
780
|
+
subject: 'New deal closed',
|
|
781
|
+
text: 'Acme Corp has signed the contract.',
|
|
782
|
+
targetAll: true,
|
|
783
|
+
})
|
|
784
|
+
|
|
785
|
+
// Notify specific users
|
|
786
|
+
await email.send({
|
|
787
|
+
subject: 'Action required',
|
|
788
|
+
html: '\<p\>Please review the proposal.\</p\>',
|
|
789
|
+
userIds: ['user-abc', 'user-def'],
|
|
790
|
+
})
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
---
|
|
794
|
+
|
|
795
|
+
## Custom Adapters with `createAdapter`
|
|
796
|
+
|
|
797
|
+
The generic `createAdapter` factory is exported for building adapters for any tool. Define a type map and call the factory.
|
|
798
|
+
|
|
799
|
+
```typescript
|
|
800
|
+
import { createAdapter } from '@elevasis/sdk/worker'
|
|
801
|
+
|
|
802
|
+
// 1. Define a type map
|
|
803
|
+
type MyToolMap = {
|
|
804
|
+
doSomething: { params: { input: string }; result: { output: string } }
|
|
805
|
+
listItems: { params: { limit?: number }; result: { items: string[] } }
|
|
806
|
+
getStatus: { params: Record<string, never>; result: { healthy: boolean } }
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// 2. Create the adapter
|
|
810
|
+
const myTool = createAdapter<MyToolMap>('my-tool', [
|
|
811
|
+
'doSomething', 'listItems', 'getStatus',
|
|
812
|
+
], 'my-credential') // credential is optional
|
|
813
|
+
|
|
814
|
+
// 3. Use it (fully typed)
|
|
815
|
+
const result = await myTool.doSomething({ input: 'hello' })
|
|
816
|
+
// ^-- { output: string }
|
|
817
|
+
const status = await myTool.getStatus()
|
|
818
|
+
// ^-- { healthy: boolean } (zero-arg because params is Record<string, never>)
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
Method names are compile-time checked against the type map keys -- misspelling a method name is a compile error.
|
|
822
|
+
|
|
823
|
+
---
|
|
824
|
+
|
|
825
|
+
All typed adapters compile to `platform.call()` internally -- you can use either interchangeably.
|
|
826
|
+
|
|
827
|
+
## When to Use Adapters vs `platform.call()`
|
|
828
|
+
|
|
829
|
+
| Scenario | Use |
|
|
830
|
+
| --------------------------------------------------------------------- | ----------------- |
|
|
831
|
+
| Tool has a typed adapter (all integrations + platform tools) | Adapter |
|
|
832
|
+
| Need autocomplete and type safety | Adapter |
|
|
833
|
+
| New dispatcher method added server-side, no SDK update yet | `platform.call()` |
|
|
834
|
+
| Tool without a typed adapter (supabase, session-memory, status, http) | `platform.call()` |
|
|
835
|
+
|
|
836
|
+
`platform.call()` remains the universal escape hatch. Every adapter call compiles down to it. Both approaches work simultaneously with no conflicts.
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
For the full inventory of all platform tools (including those without typed adapters), see [Platform Tools](index.mdx).
|
|
841
|
+
|
|
842
|
+
---
|
|
843
|
+
|
|
844
|
+
## Error Handling
|
|
845
|
+
|
|
846
|
+
All adapter calls throw `PlatformToolError` on failure, with a `code` field and `retryable` flag:
|
|
847
|
+
|
|
848
|
+
```typescript
|
|
849
|
+
import { PlatformToolError } from '@elevasis/sdk/worker'
|
|
850
|
+
|
|
851
|
+
try {
|
|
852
|
+
await attio.listRecords({ object: 'deals' })
|
|
853
|
+
} catch (err) {
|
|
854
|
+
if (err instanceof PlatformToolError) {
|
|
855
|
+
console.log(err.message) // Human-readable error
|
|
856
|
+
console.log(err.code) // e.g., 'rate_limit_exceeded', 'credentials_missing'
|
|
857
|
+
console.log(err.retryable) // true for transient errors
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
Retryable error codes: `rate_limit_exceeded`, `network_error`, `timeout_error`, `api_error`, `service_unavailable`, `server_unavailable`.
|
|
863
|
+
|
|
864
|
+
Timeouts: LLM calls have a 120s timeout. All other tool calls have a 60s timeout.
|
|
865
|
+
|
|
866
|
+
---
|
|
867
|
+
|
|
868
|
+
**Last Updated:** 2026-03-05
|