@elevasis/sdk 0.5.12 → 0.5.13

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 (32) hide show
  1. package/dist/cli.cjs +92 -81
  2. package/dist/index.d.ts +11 -253
  3. package/dist/index.js +5 -9
  4. package/dist/templates.js +26 -23
  5. package/dist/types/worker/adapters/index.d.ts +0 -1
  6. package/dist/worker/index.js +47 -53
  7. package/package.json +1 -1
  8. package/reference/_navigation.md +13 -57
  9. package/reference/concepts.mdx +203 -0
  10. package/reference/deployment/{command-center-ui.mdx → command-center.mdx} +229 -151
  11. package/reference/deployment/index.mdx +158 -153
  12. package/reference/framework/agent.mdx +168 -151
  13. package/reference/framework/index.mdx +182 -103
  14. package/reference/framework/memory.mdx +347 -347
  15. package/reference/framework/tutorial-system.mdx +253 -0
  16. package/reference/{getting-started/index.mdx → getting-started.mdx} +4 -4
  17. package/reference/index.mdx +117 -114
  18. package/reference/platform-tools/adapters.mdx +175 -32
  19. package/reference/platform-tools/index.mdx +354 -195
  20. package/reference/resources/index.mdx +5 -0
  21. package/reference/{roadmap/index.mdx → roadmap.mdx} +1 -1
  22. package/reference/{runtime/index.mdx → runtime.mdx} +196 -141
  23. package/dist/types/worker/adapters/trello.d.ts +0 -14
  24. package/reference/concepts/index.mdx +0 -203
  25. package/reference/deployment/command-view.mdx +0 -154
  26. package/reference/framework/documentation.mdx +0 -92
  27. package/reference/platform-tools/examples.mdx +0 -170
  28. package/reference/runtime/limits.mdx +0 -75
  29. package/reference/security/credentials.mdx +0 -141
  30. /package/reference/{cli/index.mdx → cli.mdx} +0 -0
  31. /package/reference/{developer → framework}/interaction-guidance.mdx +0 -0
  32. /package/reference/{troubleshooting/common-errors.mdx → troubleshooting.mdx} +0 -0
@@ -1,195 +1,354 @@
1
- ---
2
- title: Platform Tools
3
- description: Access 70+ tools across integration adapters and platform services from your SDK workflows -- typed adapters with full autocomplete for all tools, plus platform.call() as a fallback
4
- loadWhen: "Connecting to external services"
5
- ---
6
-
7
- Your SDK workflows have access to 70+ tools -- Gmail, Stripe, Google Sheets, PDF generation, human-in-the-loop approvals, storage, scheduling, and more. Credentials are managed server-side and never appear in your code.
8
-
9
- **Typed adapters** are the recommended way to call tools. They provide full TypeScript autocomplete, compile-time method checking, and eliminate boilerplate. Use `platform.call()` only for tools that don't have an adapter yet.
10
-
11
- ## Usage
12
-
13
- **Preferred: Typed adapters** (available for all integration tools + key platform services)
14
-
15
- ```typescript
16
- import { createResendAdapter, scheduler, llm } from '@elevasis/sdk/worker'
17
-
18
- // Integration tools: factory pattern (credential bound once)
19
- const resend = createResendAdapter('my-resend')
20
- await resend.sendEmail({ from: 'hi@app.com', to: 'user@example.com', subject: '...' })
21
-
22
- // Platform services: singleton (no credential needed)
23
- await scheduler.createSchedule({ ... })
24
- const result = await llm.generate({ messages: [...] })
25
- ```
26
-
27
- **Fallback: `platform.call()`** (for tools without typed adapters)
28
-
29
- ```typescript
30
- import { platform } from '@elevasis/sdk/worker'
31
-
32
- const result = await platform.call({
33
- tool: 'lead', // tool name
34
- method: 'upsertDeal', // method exposed by that tool
35
- params: { ... }, // method-specific parameters
36
- })
37
- ```
38
-
39
- Both patterns return a Promise that resolves with the tool result or rejects with a `PlatformToolError` containing a message, error code, and a `retryable` flag.
40
-
41
- ## Integration Adapters
42
-
43
- Twelve integration adapters give you access to 60+ tool methods covering third-party APIs. Pass the `credential` field with the name of the stored credential for that service. Supabase is listed separately under [Database Access](#database-access) below.
44
-
45
- | Adapter | Tools | Credential Shape |
46
- | --- | --- | --- |
47
- | Attio | 12 (CRUD + schema + notes) | `{ apiKey }` |
48
- | Google Sheets | 13 (read/write/filter/upsert) | OAuth2 / service account |
49
- | Trello | 10 (cards/lists/checklists) | `{ apiKey, token }` |
50
- | Notion | 8 (pages + blocks) | `{ token }` |
51
- | Stripe | 6 (payment links + checkout) | `{ secretKey }` |
52
- | Instantly | 5 (email campaigns) | `{ apiKey }` |
53
- | Gmail | 2 (send email) | OAuth2 / service account |
54
- | Resend | 2 (send/get email) | `{ apiKey }` |
55
- | SignatureAPI | 4 (envelopes) | `{ apiKey }` |
56
- | Dropbox | 2 (upload/folder) | `{ accessToken }` |
57
- | Apify | 1 (run actor) | `{ token }` |
58
- | Mailso | 1 (verify email) | `{ apiKey }` |
59
-
60
- Credentials are stored in the Elevasis credentials table and injected server-side. The credential name you pass in `credential` must match the name you set when storing the credential.
61
-
62
- ## Platform Services
63
-
64
- Nine built-in platform services are available without a `credential` field. These are Elevasis-managed capabilities. All have typed singleton adapters imported from `@elevasis/sdk/worker`.
65
-
66
- | Tool Key | Methods | Purpose |
67
- | --- | --- | --- |
68
- | `lead` | 35 methods (CRUD + sync) | Lead management -- `lead` singleton adapter |
69
- | `email` | `send` | Send platform email to org members -- `email` singleton adapter |
70
- | `storage` | `upload`, `download`, `createSignedUrl`, `delete`, `list` | File storage -- `storage` singleton adapter |
71
- | `pdf` | `render`, `renderToBuffer` | PDF rendering -- `pdf` singleton adapter |
72
- | `notification` | `create` | In-app notifications -- `notifications` singleton adapter |
73
- | `approval` | `create`, `deleteByMetadata` | HITL approval gates -- `approval` singleton adapter |
74
- | `scheduler` | `createSchedule`, `updateAnchor`, `deleteSchedule`, `findByIdempotencyKey`, `deleteScheduleByIdempotencyKey`, `listSchedules`, `getSchedule`, `cancelSchedule`, `cancelSchedulesByMetadata` | Task scheduling -- `scheduler` singleton adapter |
75
- | `llm` | `generate` | LLM inference -- `llm` singleton adapter |
76
- | `execution` | `trigger` | Nested child execution -- `execution` singleton adapter |
77
-
78
- ## LLM Tool
79
-
80
- Call any supported LLM from your workflow with no API keys required. Keys are resolved server-side from environment variables. Use the `llm` typed adapter for full autocomplete.
81
-
82
- ```typescript
83
- import { llm } from '@elevasis/sdk/worker'
84
-
85
- const result = await llm.generate({
86
- provider: 'google',
87
- model: 'gemini-3-flash-preview',
88
- messages: [
89
- { role: 'system', content: 'Classify this email reply.' },
90
- { role: 'user', content: emailText }
91
- ],
92
- responseSchema: {
93
- type: 'object',
94
- properties: {
95
- category: { type: 'string', enum: ['interested', 'not-interested', 'bounced'] },
96
- confidence: { type: 'number', minimum: 0, maximum: 1 }
97
- },
98
- required: ['category', 'confidence']
99
- },
100
- temperature: 0.2
101
- })
102
- ```
103
-
104
- **Supported models:**
105
-
106
- | Provider | Models |
107
- | --- | --- |
108
- | `google` | `gemini-3-flash-preview` |
109
- | `openai` | `gpt-5`, `gpt-5-mini` |
110
- | `anthropic` | `claude-opus-4-5`, `claude-sonnet-4-5`, `claude-haiku-4-5` |
111
- | `openrouter` | `openrouter/anthropic/claude-sonnet-4.5`, `openrouter/deepseek/deepseek-v3.2`, `openrouter/x-ai/grok-4.1-fast` |
112
-
113
- **Key params:**
114
-
115
- - `provider` -- one of `google`, `openai`, `anthropic`, `openrouter`
116
- - `model` -- model identifier from the table above
117
- - `messages` -- array of `{ role, content }` objects
118
- - `responseSchema` -- optional JSON Schema for structured output
119
- - `temperature` -- optional, controls output randomness
120
-
121
- ## Execution Tool
122
-
123
- Trigger another resource (workflow or agent) as a nested child of the current execution. The child runs synchronously and its result is returned. Depth is tracked automatically up to a maximum of 5 levels to prevent infinite recursion.
124
-
125
- ```typescript
126
- import { execution } from '@elevasis/sdk/worker'
127
-
128
- const result = await execution.trigger({
129
- resourceId: 'my-other-workflow',
130
- input: { key: 'value' },
131
- })
132
- // result = { success: true, executionId: '...', output: { ... }, error: undefined }
133
- ```
134
-
135
- The invoked resource must belong to the same organization. The `organizationId` is always taken from the parent execution context -- you cannot invoke resources across organizations.
136
-
137
- ## Managing Environment Variables
138
-
139
- Use the `elevasis-sdk env` CLI to manage environment variables for your deployed workers:
140
-
141
- ```bash
142
- elevasis-sdk env list
143
- elevasis-sdk env set KEY value
144
- elevasis-sdk env remove KEY
145
- ```
146
-
147
- Environment variables set this way are injected into your worker process at startup and are available via `process.env`.
148
-
149
- ## Database Access
150
-
151
- Supabase is a first-class integration adapter that gives your workflows persistent storage using the same `platform.call()` interface as every other tool. Pass the `credential` field with the name of your stored Supabase credential.
152
-
153
- **Methods:** `insert`, `select`, `update`, `delete`, `upsert`, `rpc`, `count`
154
-
155
- ```typescript
156
- // Select rows with filters
157
- const qualified = await platform.call({
158
- tool: 'supabase',
159
- credential: 'my-database',
160
- method: 'select',
161
- params: {
162
- table: 'leads',
163
- filter: { status: 'eq.qualified', score: 'gte.80' },
164
- order: { column: 'score', ascending: false },
165
- limit: 50,
166
- },
167
- })
168
- // Returns: [{ id: '...', name: 'Jane Doe', score: 92, ... }, ...]
169
- ```
170
-
171
- **Filter syntax** uses PostgREST string format (`operator.value`):
172
-
173
- | Filter | Example | Meaning |
174
- | --- | --- | --- |
175
- | `eq` | `{ status: 'eq.qualified' }` | Equals |
176
- | `neq` | `{ status: 'neq.lost' }` | Not equals |
177
- | `gt`, `gte`, `lt`, `lte` | `{ score: 'gte.80' }` | Comparisons |
178
- | `like`, `ilike` | `{ name: 'ilike.%jane%' }` | Pattern match |
179
- | `in` | `{ status: 'in.(new,contacted)' }` | In set |
180
- | `is` | `{ deleted_at: 'is.null' }` | Null check |
181
-
182
- **Credential setup:** Create a credential with provider `supabase` in the command center. The config fields are `url` (your Supabase project URL) and `serviceRoleKey` (the service role key from Settings > API). Workflows always use the service role key -- server-side execution, no RLS.
183
-
184
- **`/database init`:** A guided setup command that stores your Supabase credential, generates `data/schema.ts`, and creates `docs/database.mdx`.
185
-
186
- **`data/schema.ts`:** An agent-readable Zod schema that documents your table structure. It is NOT deployed and NOT executed -- the agent reads it to understand your data model when writing workflow steps or generating queries.
187
-
188
- ## Documentation
189
-
190
- - [Typed Adapters](adapters.mdx) - Type-safe wrappers for all 12 integrations + 9 platform services with full autocomplete (recommended)
191
- - [Integration Examples](examples.mdx) - Working code examples for email, CRM, PDF, LLM, and more
192
-
193
- ---
194
-
195
- **Last Updated:** 2026-03-02
1
+ ---
2
+ title: Platform Tools
3
+ description: Access 70+ tools across integration adapters and platform services from your SDK workflows -- typed adapters, credential security model, and working code examples
4
+ loadWhen: "Connecting to external services"
5
+ ---
6
+
7
+ Your SDK workflows have access to 70+ tools -- Gmail, Stripe, Google Sheets, PDF generation, human-in-the-loop approvals, storage, scheduling, and more. Credentials are managed server-side and never appear in your code.
8
+
9
+ **Typed adapters** are the recommended way to call tools. They provide full TypeScript autocomplete, compile-time method checking, and eliminate boilerplate. Use `platform.call()` only for tools that don't have an adapter yet.
10
+
11
+ ## Usage
12
+
13
+ **Preferred: Typed adapters** (available for all integration tools + key platform services)
14
+
15
+ ```typescript
16
+ import { createResendAdapter, scheduler, llm } from '@elevasis/sdk/worker'
17
+
18
+ // Integration tools: factory pattern (credential bound once)
19
+ const resend = createResendAdapter('my-resend')
20
+ await resend.sendEmail({ from: 'hi@app.com', to: 'user@example.com', subject: '...' })
21
+
22
+ // Platform services: singleton (no credential needed)
23
+ await scheduler.createSchedule({ ... })
24
+ const result = await llm.generate({ messages: [...] })
25
+ ```
26
+
27
+ **Fallback: `platform.call()`** (for tools without typed adapters)
28
+
29
+ ```typescript
30
+ import { platform } from '@elevasis/sdk/worker'
31
+
32
+ const result = await platform.call({
33
+ tool: 'lead', // tool name
34
+ method: 'upsertDeal', // method exposed by that tool
35
+ params: { ... }, // method-specific parameters
36
+ })
37
+ ```
38
+
39
+ Both patterns return a Promise that resolves with the tool result or rejects with a `PlatformToolError` containing a message, error code, and a `retryable` flag.
40
+
41
+ ## Integration Adapters
42
+
43
+ Twelve integration adapters give you access to 60+ tool methods covering third-party APIs. Pass the `credential` field with the name of the stored credential for that service. Supabase is listed separately under [Database Access](#database-access) below.
44
+
45
+ | Adapter | Tools | Credential Shape |
46
+ | ------------- | ----------------------------- | ------------------------ |
47
+ | Attio | 12 (CRUD + schema + notes) | `{ apiKey }` |
48
+ | Google Sheets | 13 (read/write/filter/upsert) | OAuth2 / service account |
49
+ | Notion | 8 (pages + blocks) | `{ token }` |
50
+ | Stripe | 6 (payment links + checkout) | `{ secretKey }` |
51
+ | Instantly | 5 (email campaigns) | `{ apiKey }` |
52
+ | Gmail | 2 (send email) | OAuth2 / service account |
53
+ | Resend | 2 (send/get email) | `{ apiKey }` |
54
+ | SignatureAPI | 4 (envelopes) | `{ apiKey }` |
55
+ | Dropbox | 2 (upload/folder) | `{ accessToken }` |
56
+ | Apify | 1 (run actor) | `{ token }` |
57
+ | Mailso | 1 (verify email) | `{ apiKey }` |
58
+
59
+ ## Credential Security
60
+
61
+ Integration credentials are never stored in `.env` and never available via `process.env` inside worker threads. Credentials live in the platform credential system (created via the command center UI or CLI) and are accessed through three controlled channels.
62
+
63
+ ### Layer 1: Platform Tools (Default)
64
+
65
+ All platform tools resolve credentials server-side. The credential value never crosses the postMessage boundary into the worker.
66
+
67
+ ```typescript
68
+ // Credential 'my-gmail' is resolved server-side -- value never enters worker memory
69
+ const result = await platform.call({
70
+ tool: 'gmail',
71
+ method: 'sendEmail',
72
+ credential: 'my-gmail',
73
+ params: { to: '...', subject: '...', body: '...' },
74
+ })
75
+ ```
76
+
77
+ ### Layer 2: HTTP Platform Tool
78
+
79
+ For APIs without a dedicated adapter, use the `http` platform tool. Credentials are injected server-side before the outgoing request.
80
+
81
+ ```typescript
82
+ const result = await platform.call({
83
+ tool: 'http',
84
+ method: 'request',
85
+ credential: 'my-custom-api',
86
+ params: {
87
+ url: 'https://api.example.com/v1/data',
88
+ method: 'GET',
89
+ headers: { 'Content-Type': 'application/json' },
90
+ },
91
+ })
92
+ ```
93
+
94
+ **Supported injection patterns:**
95
+
96
+ | Pattern | Credential Config | How Injected |
97
+ | --------------- | ---------------------------------------------------------------- | ---------------------------------------- |
98
+ | Bearer token | `{ type: 'bearer', token: 'sk_...' }` | `Authorization: Bearer sk_...` header |
99
+ | API key header | `{ type: 'api-key-header', header: 'X-API-Key', key: 'ak_...' }` | Custom header |
100
+ | Basic auth | `{ type: 'basic', username: '...', password: '...' }` | `Authorization: Basic base64(user:pass)` |
101
+ | Query parameter | `{ type: 'query-param', param: 'api_key', value: 'ak_...' }` | Appended to URL |
102
+ | Body field | `{ type: 'body-field', field: 'apiKey', value: 'ak_...' }` | Merged into JSON body |
103
+ | Custom header | `{ type: 'custom-header', header: 'X-Custom', value: '...' }` | Arbitrary header |
104
+
105
+ ### Layer 3: getCredential() (Explicit Opt-In)
106
+
107
+ For third-party SDKs that require a raw key (e.g., `new Stripe(key)`), use `platform.getCredential()`. This explicitly causes the credential value to enter worker memory.
108
+
109
+ ```typescript
110
+ import { platform } from '@elevasis/sdk/worker'
111
+
112
+ const cred = await platform.getCredential('my-stripe-key')
113
+ const stripe = new Stripe(cred.credentials.secretKey)
114
+ ```
115
+
116
+ All `getCredential()` calls are logged. Use `platform.call()` with the `http` tool when possible.
117
+
118
+ ### Credential Setup
119
+
120
+ Credentials are created in the command center UI: navigate to Credentials → Add Credential → select type → enter values → save. The name you give the credential is what you pass as `credential: 'my-cred-name'` in `platform.call()`. Credential names are case-sensitive -- a mismatch causes `PlatformToolError: credential not found`.
121
+
122
+ ### Choosing a Pattern
123
+
124
+ | Situation | Pattern |
125
+ | ------------------------------------------------------ | --------------------------------------- |
126
+ | Using a supported adapter (Gmail, Attio, Stripe, etc.) | `platform.call()` with the adapter tool |
127
+ | Calling an API not in the catalog | `platform.call()` with `tool: 'http'` |
128
+ | Third-party SDK that requires a raw key | `platform.getCredential()` |
129
+
130
+ `.env` contains only `ELEVASIS_API_KEY` for CLI authentication -- never integration credentials.
131
+
132
+ ---
133
+
134
+ ## Platform Services
135
+
136
+ Nine built-in platform services are available without a `credential` field. All have typed singleton adapters imported from `@elevasis/sdk/worker`.
137
+
138
+ | Tool Key | Methods | Purpose |
139
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
140
+ | `lead` | 35 methods (CRUD + sync) | Lead management -- `lead` singleton adapter |
141
+ | `email` | `send` | Send platform email to org members -- `email` singleton adapter |
142
+ | `storage` | `upload`, `download`, `createSignedUrl`, `delete`, `list` | File storage -- `storage` singleton adapter |
143
+ | `pdf` | `render`, `renderToBuffer` | PDF rendering -- `pdf` singleton adapter |
144
+ | `notification` | `create` | In-app notifications -- `notifications` singleton adapter |
145
+ | `approval` | `create`, `deleteByMetadata` | HITL approval gates -- `approval` singleton adapter |
146
+ | `scheduler` | `createSchedule`, `updateAnchor`, `deleteSchedule`, `findByIdempotencyKey`, `deleteScheduleByIdempotencyKey`, `listSchedules`, `getSchedule`, `cancelSchedule`, `cancelSchedulesByMetadata` | Task scheduling -- `scheduler` singleton adapter |
147
+ | `llm` | `generate` | LLM inference -- `llm` singleton adapter |
148
+ | `execution` | `trigger` | Nested child execution -- `execution` singleton adapter |
149
+
150
+ ## LLM Tool
151
+
152
+ Call any supported LLM from your workflow with no API keys required. Keys are resolved server-side from environment variables.
153
+
154
+ ```typescript
155
+ import { llm } from '@elevasis/sdk/worker'
156
+
157
+ const result = await llm.generate({
158
+ provider: 'google',
159
+ model: 'gemini-3-flash-preview',
160
+ messages: [
161
+ { role: 'system', content: 'Classify this email reply.' },
162
+ { role: 'user', content: emailText }
163
+ ],
164
+ responseSchema: {
165
+ type: 'object',
166
+ properties: {
167
+ category: { type: 'string', enum: ['interested', 'not-interested', 'bounced'] },
168
+ confidence: { type: 'number', minimum: 0, maximum: 1 }
169
+ },
170
+ required: ['category', 'confidence']
171
+ },
172
+ temperature: 0.2
173
+ })
174
+ ```
175
+
176
+ **Supported models:**
177
+
178
+ | Provider | Models |
179
+ | ------------ | -------------------------------------------------------------------------------------------------------------- |
180
+ | `google` | `gemini-3-flash-preview` |
181
+ | `openai` | `gpt-5`, `gpt-5-mini` |
182
+ | `anthropic` | `claude-opus-4-5`, `claude-sonnet-4-5`, `claude-haiku-4-5` |
183
+ | `openrouter` | `openrouter/anthropic/claude-sonnet-4.5`, `openrouter/deepseek/deepseek-v3.2`, `openrouter/x-ai/grok-4.1-fast` |
184
+
185
+ **Key params:** `provider`, `model`, `messages` (`{ role, content }[]`), `responseSchema` (optional JSON Schema), `temperature` (optional).
186
+
187
+ ## Execution Tool
188
+
189
+ Trigger another resource as a nested child of the current execution. The child runs synchronously and its result is returned. Maximum depth: 5 levels.
190
+
191
+ ```typescript
192
+ import { execution } from '@elevasis/sdk/worker'
193
+
194
+ const result = await execution.trigger({
195
+ resourceId: 'my-other-workflow',
196
+ input: { key: 'value' },
197
+ })
198
+ // result = { success: true, executionId: '...', output: { ... }, error: undefined }
199
+ ```
200
+
201
+ The invoked resource must belong to the same organization.
202
+
203
+ ## Database Access
204
+
205
+ Supabase is a first-class integration adapter for persistent storage. Pass the `credential` field with your stored Supabase credential name.
206
+
207
+ **Methods:** `insert`, `select`, `update`, `delete`, `upsert`, `rpc`, `count`
208
+
209
+ ```typescript
210
+ const qualified = await platform.call({
211
+ tool: 'supabase',
212
+ credential: 'my-database',
213
+ method: 'select',
214
+ params: {
215
+ table: 'leads',
216
+ filter: { status: 'eq.qualified', score: 'gte.80' },
217
+ order: { column: 'score', ascending: false },
218
+ limit: 50,
219
+ },
220
+ })
221
+ ```
222
+
223
+ **Filter syntax** uses PostgREST format (`operator.value`):
224
+
225
+ | Filter | Example | Meaning |
226
+ | ------------------------ | ---------------------------------- | ------------- |
227
+ | `eq` | `{ status: 'eq.qualified' }` | Equals |
228
+ | `neq` | `{ status: 'neq.lost' }` | Not equals |
229
+ | `gt`, `gte`, `lt`, `lte` | `{ score: 'gte.80' }` | Comparisons |
230
+ | `like`, `ilike` | `{ name: 'ilike.%jane%' }` | Pattern match |
231
+ | `in` | `{ status: 'in.(new,contacted)' }` | In set |
232
+ | `is` | `{ deleted_at: 'is.null' }` | Null check |
233
+
234
+ **Credential setup:** Create a credential with provider `supabase` — config fields are `url` and `serviceRoleKey`. Workflows always use the service role key (server-side, no RLS).
235
+
236
+ **`/database init`:** Guided setup that stores your Supabase credential, generates `data/schema.ts`, and creates `docs/database.mdx`.
237
+
238
+ **`data/schema.ts`:** An agent-readable Zod schema documenting your table structure. Not deployed or executed — the agent reads it to understand your data model.
239
+
240
+ ---
241
+
242
+ ## Code Examples
243
+
244
+ ### Email via Resend
245
+
246
+ ```typescript
247
+ import { createResendAdapter } from '@elevasis/sdk/worker'
248
+
249
+ const resend = createResendAdapter('resend')
250
+ await resend.sendEmail({
251
+ from: 'hello@yourapp.com',
252
+ to: 'customer@example.com',
253
+ subject: 'Your order is confirmed',
254
+ html: '\<p\>Thank you for your order!\</p\>',
255
+ })
256
+ ```
257
+
258
+ ### CRM Record via Attio
259
+
260
+ ```typescript
261
+ import { createAttioAdapter } from '@elevasis/sdk/worker'
262
+
263
+ const attio = createAttioAdapter('attio')
264
+ const result = await attio.createRecord({
265
+ object: 'people',
266
+ values: {
267
+ name: [{ full_name: 'Jane Smith' }],
268
+ email_addresses: [{ email_address: 'jane@example.com' }],
269
+ },
270
+ })
271
+ const recordId = result.data.id
272
+ ```
273
+
274
+ ### PDF Generation
275
+
276
+ ```typescript
277
+ import { pdf, storage } from '@elevasis/sdk/worker'
278
+
279
+ // Render to storage directly
280
+ const result = await pdf.render({
281
+ document: proposalDocument,
282
+ storage: { bucket: 'invoices', path: 'invoice-1042.pdf' },
283
+ })
284
+
285
+ // Or render to buffer for inline processing
286
+ const { buffer } = await pdf.renderToBuffer({ document: proposalDocument })
287
+ await storage.upload({ bucket: 'invoices', path: 'invoice-1042.pdf', content: buffer, contentType: 'application/pdf' })
288
+ ```
289
+
290
+ ### LLM with Structured Output
291
+
292
+ ```typescript
293
+ import { llm } from '@elevasis/sdk/worker'
294
+
295
+ interface TicketClassification {
296
+ priority: 'low' | 'medium' | 'high' | 'critical'
297
+ category: 'billing' | 'technical' | 'account' | 'other'
298
+ summary: string
299
+ }
300
+
301
+ const response = await llm.generate\<TicketClassification\>({
302
+ provider: 'anthropic',
303
+ model: 'claude-sonnet-4-5',
304
+ messages: [
305
+ { role: 'system', content: 'Extract structured data from support tickets.' },
306
+ { role: 'user', content: ticketText },
307
+ ],
308
+ responseSchema: {
309
+ type: 'object',
310
+ properties: {
311
+ priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
312
+ category: { type: 'string', enum: ['billing', 'technical', 'account', 'other'] },
313
+ summary: { type: 'string' },
314
+ },
315
+ required: ['priority', 'category', 'summary'],
316
+ },
317
+ temperature: 0.1,
318
+ })
319
+ const { priority, category, summary } = response.output
320
+ ```
321
+
322
+ ### Triggering Another Resource
323
+
324
+ ```typescript
325
+ import { execution } from '@elevasis/sdk/worker'
326
+
327
+ const outcome = await execution.trigger({
328
+ resourceId: 'send-welcome-sequence',
329
+ input: { userId: newUser.id, email: newUser.email, plan: 'pro' },
330
+ })
331
+ if (!outcome.success) throw new Error(`Child workflow failed: ${outcome.error}`)
332
+ ```
333
+
334
+ ### File Storage
335
+
336
+ ```typescript
337
+ import { storage } from '@elevasis/sdk/worker'
338
+
339
+ const reportPath = `exports/report-${Date.now()}.csv`
340
+ await storage.upload({ bucket: 'exports', path: reportPath, content: csvContent, contentType: 'text/csv' })
341
+
342
+ const { signedUrl } = await storage.createSignedUrl({ bucket: 'exports', path: reportPath })
343
+ // signedUrl is valid for 1 hour (3600 seconds) -- share with user or include in email
344
+ ```
345
+
346
+ ---
347
+
348
+ ## Documentation
349
+
350
+ - [Typed Adapters](adapters.mdx) - Type-safe wrappers for all 12 integrations + 9 platform services with full autocomplete (recommended)
351
+
352
+ ---
353
+
354
+ **Last Updated:** 2026-03-06
@@ -331,6 +331,11 @@ const config: ElevasConfig = {
331
331
  export default config;
332
332
  ```
333
333
 
334
+ ## Documentation
335
+
336
+ - [SDK Types](types.mdx) - Complete type reference for `@elevasis/sdk` exports, config, and step handler context
337
+ - [Common Patterns](patterns.mdx) - Sequential steps, conditional branching, error handling, and resource status patterns
338
+
334
339
  ---
335
340
 
336
341
  **Last Updated:** 2026-02-25
@@ -6,7 +6,7 @@ loadWhen: "Asking about future features or planned capabilities"
6
6
 
7
7
  **Status:** Planned -- none of these features are implemented yet.
8
8
 
9
- For currently implemented behavior, see [Runtime](../runtime/index.mdx).
9
+ For currently implemented behavior, see [Runtime](runtime.mdx).
10
10
 
11
11
  ---
12
12