@mindstudio-ai/remy 0.1.34 → 0.1.35

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 (54) hide show
  1. package/dist/headless.js +578 -393
  2. package/dist/index.js +652 -385
  3. package/dist/prompt/sources/llms.txt +1618 -0
  4. package/dist/prompt/static/instructions.md +1 -1
  5. package/dist/prompt/static/team.md +1 -1
  6. package/dist/subagents/.notes-background-agents.md +60 -48
  7. package/dist/subagents/browserAutomation/prompt.md +14 -11
  8. package/dist/subagents/designExpert/data/sources/dev/index.html +901 -0
  9. package/dist/subagents/designExpert/data/sources/dev/serve.mjs +244 -0
  10. package/dist/subagents/designExpert/data/sources/dev/specimens-fonts.html +126 -0
  11. package/dist/subagents/designExpert/data/sources/dev/specimens-pairings.html +114 -0
  12. package/dist/subagents/designExpert/data/{fonts.json → sources/fonts.json} +0 -97
  13. package/dist/subagents/designExpert/data/sources/inspiration.json +392 -0
  14. package/dist/subagents/designExpert/prompt.md +36 -12
  15. package/dist/subagents/designExpert/prompts/animation.md +14 -6
  16. package/dist/subagents/designExpert/prompts/color.md +25 -5
  17. package/dist/subagents/designExpert/prompts/{icons.md → components.md} +17 -5
  18. package/dist/subagents/designExpert/prompts/frontend-design-notes.md +17 -122
  19. package/dist/subagents/designExpert/prompts/identity.md +15 -61
  20. package/dist/subagents/designExpert/prompts/images.md +35 -10
  21. package/dist/subagents/designExpert/prompts/layout.md +14 -9
  22. package/dist/subagents/designExpert/prompts/typography.md +39 -0
  23. package/package.json +2 -2
  24. package/dist/actions/buildFromInitialSpec.md +0 -15
  25. package/dist/actions/publish.md +0 -12
  26. package/dist/actions/sync.md +0 -19
  27. package/dist/compiled/README.md +0 -100
  28. package/dist/compiled/auth.md +0 -77
  29. package/dist/compiled/design.md +0 -251
  30. package/dist/compiled/dev-and-deploy.md +0 -69
  31. package/dist/compiled/interfaces.md +0 -238
  32. package/dist/compiled/manifest.md +0 -107
  33. package/dist/compiled/media-cdn.md +0 -51
  34. package/dist/compiled/methods.md +0 -225
  35. package/dist/compiled/msfm.md +0 -222
  36. package/dist/compiled/platform.md +0 -105
  37. package/dist/compiled/scenarios.md +0 -103
  38. package/dist/compiled/sdk-actions.md +0 -146
  39. package/dist/compiled/tables.md +0 -263
  40. package/dist/static/authoring.md +0 -101
  41. package/dist/static/coding.md +0 -29
  42. package/dist/static/identity.md +0 -1
  43. package/dist/static/instructions.md +0 -31
  44. package/dist/static/intake.md +0 -44
  45. package/dist/static/lsp.md +0 -4
  46. package/dist/static/projectContext.ts +0 -160
  47. package/dist/static/team.md +0 -39
  48. package/dist/subagents/designExpert/data/inspiration.json +0 -392
  49. package/dist/subagents/designExpert/prompts/instructions.md +0 -18
  50. /package/dist/subagents/designExpert/data/{compile-font-descriptions.sh → sources/compile-font-descriptions.sh} +0 -0
  51. /package/dist/subagents/designExpert/data/{compile-inspiration.sh → sources/compile-inspiration.sh} +0 -0
  52. /package/dist/subagents/designExpert/data/{inspiration.raw.json → sources/inspiration.raw.json} +0 -0
  53. /package/dist/subagents/designExpert/{prompts/tool-prompts → data/sources/prompts}/design-analysis.md +0 -0
  54. /package/dist/subagents/designExpert/{prompts/tool-prompts → data/sources/prompts}/font-analysis.md +0 -0
@@ -0,0 +1,1618 @@
1
+ # @mindstudio-ai/agent
2
+
3
+ TypeScript SDK, CLI, and MCP server for MindStudio. One API key gives you access to 200+ AI models (OpenAI, Anthropic, Google, Meta, xAI, DeepSeek, etc.) and 1,000+ actions including 850+ connector actions across third-party services from the open-source MindStudio Connector Registry (https://github.com/mindstudio-ai/mscr). No separate provider API keys required.
4
+
5
+ This file is the complete API reference. No other documentation is needed to use the SDK.
6
+
7
+ ## Recommended workflow
8
+
9
+ There are 150+ actions available. Do NOT try to read or load them all at once. Follow this discovery flow:
10
+
11
+ 1. **Identify yourself** — Call `changeName` to set your display name (use your name or whatever your user calls you). If you have a profile picture or icon, call `uploadFile` to upload it, then `changeProfilePicture` with the returned URL. This helps users identify your requests in their logs.
12
+ 2. **Discover** — Call `listActions` (MCP tool) or `mindstudio list-actions --summary` (CLI) to get a compact `{ action: description }` map of everything available (~3k tokens).
13
+ 3. **Drill in** — Once you identify the right action, look up its full signature in the reference below, or call `mindstudio info <action>` (CLI) for parameter details.
14
+ 4. **Call it** — Invoke the action with the required parameters. All actions share the same calling convention (see below).
15
+
16
+ For specific use cases:
17
+
18
+ - **OAuth third-party integrations** (Slack, Google, HubSpot, etc.): These are optional OAuth connectors from the MindStudio Connector Registry — for most tasks, use actions directly instead. If you need a third-party integration: call `listConnectors()` to browse services → `getConnectorAction(serviceId, actionId)` for input fields → execute via `runFromConnectorRegistry`. Requires an OAuth connection set up in MindStudio first — call `listConnections()` to check available connections.
19
+ - **Pre-built agents**: Call `listAgents()` to see what's available → `runAgent({ appId })` to execute one. **Important:** Not all agents are configured for API use. Do not try to run an agent just because it appears in the list — only run agents the user specifically asks you to run.
20
+ - **Model selection**: Call `listModelsSummary()` or `listModelsSummaryByType("llm_chat")` to browse models, then pass the model ID as `modelOverride.model` to actions like `generateText`. Use the summary endpoints (not `listModels`) to keep token usage low.
21
+ - **Cost estimation**: AI-powered actions (text generation, image generation, video, audio, etc.) cost money. Call `estimateStepCost(stepType, stepInput)` before running these and confirm with the user before proceeding — unless they've explicitly given permission to go ahead. Non-AI actions (data lookups, OAuth connectors, etc.) are generally free.
22
+
23
+ ## Install
24
+
25
+ Standalone binary (CLI/MCP, no dependencies):
26
+ ```bash
27
+ curl -fsSL https://msagent.ai/install.sh | bash
28
+ ```
29
+
30
+ npm (SDK + CLI):
31
+ ```bash
32
+ npm install @mindstudio-ai/agent
33
+ ```
34
+
35
+ Requires Node.js >= 18.
36
+
37
+ ## CLI
38
+
39
+ The package includes a CLI for executing steps from the command line or scripts:
40
+
41
+ ```bash
42
+ # Execute with named flags (kebab-case)
43
+ mindstudio generate-image --prompt "A mountain landscape"
44
+
45
+ # Execute with JSON input (JSON5-tolerant)
46
+ mindstudio generate-image '{prompt: "A mountain landscape"}'
47
+
48
+ # Extract a single output field
49
+ mindstudio generate-image --prompt "A sunset" --output-key imageUrl
50
+
51
+ # List all methods (compact JSON — best for LLM discovery)
52
+ mindstudio list --summary
53
+
54
+ # List all methods (human-readable table)
55
+ mindstudio list
56
+
57
+ # Show method details (params, types, output)
58
+ mindstudio info generate-image
59
+
60
+ # Run via npx without installing
61
+ npx @mindstudio-ai/agent generate-text --message "Hello"
62
+ ```
63
+
64
+ Auth: run `mindstudio login`, set `MINDSTUDIO_API_KEY` env var, or pass `--api-key <key>`.
65
+ Method names are kebab-case on the CLI (camelCase also accepted). Flags are kebab-case (`--video-url` for `videoUrl`).
66
+ Use `--output-key <key>` to extract a single field, `--no-meta` to strip $-prefixed metadata.
67
+
68
+ ### Authentication
69
+
70
+ ```bash
71
+ # Interactive login (opens browser, saves key to ~/.mindstudio/config.json)
72
+ mindstudio login
73
+
74
+ # Check current auth status
75
+ mindstudio whoami
76
+
77
+ # Clear stored credentials
78
+ mindstudio logout
79
+ ```
80
+
81
+ Auth resolution order: `--api-key` flag > `MINDSTUDIO_API_KEY` env > `~/.mindstudio/config.json` > `CALLBACK_TOKEN` env.
82
+
83
+ ## MCP server
84
+
85
+ The package includes an MCP server exposing all methods as tools. Start by calling the `listSteps` tool to discover available methods.
86
+
87
+ ```bash
88
+ mindstudio mcp
89
+ ```
90
+
91
+ MCP client config (standalone binary — recommended):
92
+ ```json
93
+ {
94
+ "mcpServers": {
95
+ "mindstudio": {
96
+ "command": "mindstudio",
97
+ "args": ["mcp"],
98
+ "env": { "MINDSTUDIO_API_KEY": "your-api-key" }
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## Setup
105
+
106
+ ```typescript
107
+ import { MindStudioAgent } from '@mindstudio-ai/agent';
108
+
109
+ // With API key (or set MINDSTUDIO_API_KEY env var)
110
+ const agent = new MindStudioAgent({ apiKey: 'your-key' });
111
+ ```
112
+
113
+ Your MindStudio API key authenticates all requests. MindStudio routes to the correct AI provider (OpenAI, Google, Anthropic, etc.) server-side — you do NOT need separate provider API keys.
114
+
115
+ Constructor options:
116
+ ```typescript
117
+ new MindStudioAgent({
118
+ apiKey?: string, // Auth token. Falls back to MINDSTUDIO_API_KEY env var.
119
+ baseUrl?: string, // API base URL. Defaults to "https://v1.mindstudio-api.com".
120
+ maxRetries?: number, // Retries on 429 rate limit (default: 3). Uses Retry-After header for delay.
121
+ })
122
+ ```
123
+
124
+ ## Models
125
+
126
+ Direct access to 200+ AI models from every major provider — all through a single API key, billed at cost with no markups.
127
+
128
+ Use `listModels()` or `listModelsByType()` for full model details, or `listModelsSummary()` / `listModelsSummaryByType()` for a lightweight list (id, name, type, tags) suitable for LLM context windows. Pass a model ID to `modelOverride.model` in methods like `generateText` to select a specific model:
129
+
130
+ ```typescript
131
+ const { models } = await agent.listModelsByType('llm_chat');
132
+ const model = models.find(m => m.name.includes("Gemini"));
133
+
134
+ const { content } = await agent.generateText({
135
+ message: 'Hello',
136
+ modelOverride: {
137
+ model: model.id,
138
+ temperature: 0.7,
139
+ maxResponseTokens: 1024,
140
+ },
141
+ });
142
+ ```
143
+
144
+ ## Calling convention
145
+
146
+ Every method has the signature:
147
+ ```typescript
148
+ agent.methodName(input: InputType, options?: { appId?: string, threadId?: string }): Promise<OutputType & StepExecutionMeta>
149
+ ```
150
+
151
+ The first argument is the step-specific input object. The optional second argument controls thread/app context.
152
+
153
+ **Results are returned flat** — output fields are spread at the top level alongside metadata:
154
+
155
+ ```typescript
156
+ const { content } = await agent.generateText({ message: 'Hello' });
157
+
158
+ // Full result shape for any method:
159
+ const result = await agent.generateText({ message: `Hello` });
160
+ result.content; // step-specific output field
161
+ result.$appId; // string — app ID for this execution
162
+ result.$threadId; // string — thread ID for this execution
163
+ result.$rateLimitRemaining; // number | undefined — API calls remaining in rate limit window
164
+ result.$billingCost; // number | undefined — cost in credits for this call
165
+ result.$billingEvents; // object[] | undefined — itemized billing events
166
+ ```
167
+
168
+ ## Thread persistence
169
+
170
+ Pass `$appId`/`$threadId` from a previous result to maintain conversation state, variable state, or other context across calls:
171
+
172
+ ```typescript
173
+ const r1 = await agent.generateText({ message: 'My name is Alice' });
174
+ const r2 = await agent.generateText(
175
+ { message: 'What is my name?' },
176
+ { threadId: r1.$threadId, appId: r1.$appId },
177
+ );
178
+ // r2.content => "Your name is Alice"
179
+ ```
180
+
181
+ ## Error handling
182
+
183
+ All errors throw `MindStudioError`:
184
+ ```typescript
185
+ import { MindStudioError } from '@mindstudio-ai/agent';
186
+
187
+ try {
188
+ await agent.generateImage({ prompt: '...' });
189
+ } catch (err) {
190
+ if (err instanceof MindStudioError) {
191
+ err.message; // Human-readable error message
192
+ err.code; // Machine-readable code: "invalid_step_config", "api_error", "call_cap_exceeded", "output_fetch_error"
193
+ err.status; // HTTP status code (400, 401, 429, etc.)
194
+ err.details; // Raw error body from the API
195
+ }
196
+ }
197
+ ```
198
+
199
+ 429 rate limit errors are retried automatically (configurable via `maxRetries`).
200
+
201
+ ## Low-level access
202
+
203
+ For action types not covered by generated methods:
204
+ ```typescript
205
+ const result = await agent.executeStep('stepType', { ...params });
206
+ ```
207
+
208
+ ## Batch execution
209
+
210
+ Execute multiple steps in parallel in a single request. Maximum 50 steps per batch.
211
+ Individual step failures do not affect other steps — partial success is possible.
212
+
213
+ ```typescript
214
+ const result = await agent.executeStepBatch([
215
+ { stepType: 'generateImage', step: { prompt: 'a sunset' } },
216
+ { stepType: 'textToSpeech', step: { text: 'hello world' } },
217
+ ], { appId?, threadId? });
218
+
219
+ // Result:
220
+ result.results; // BatchStepResult[] — same order as input
221
+ result.results[0].stepType; // string
222
+ result.results[0].output; // object | undefined (step output on success)
223
+ result.results[0].error; // string | undefined (error message on failure)
224
+ result.results[0].billingCost; // number | undefined (cost on success)
225
+ result.totalBillingCost; // number | undefined
226
+ result.appId; // string
227
+ result.threadId; // string
228
+ ```
229
+
230
+ CLI:
231
+ ```bash
232
+ mindstudio batch '[{"stepType":"generateImage","step":{"prompt":"a cat"}}]'
233
+ cat steps.json | mindstudio batch
234
+ ```
235
+
236
+ ## Methods
237
+
238
+ All methods below are called on a `MindStudioAgent` instance (`agent.methodName(...)`).
239
+ Input shows the first argument object. Output shows the fields available on the returned result.
240
+
241
+ ### General
242
+
243
+ #### addSubtitlesToVideo
244
+ Automatically add subtitles to a video
245
+ - Can control style of text and animation
246
+ - Input: `{ videoUrl: string, language: string, fontName: string, fontSize: number, fontWeight: "normal" | "bold" | "black", fontColor: "white" | "black" | "red" | "green" | "blue" | "yellow" | "orange" | "purple" | "pink" | "brown" | "gray" | "cyan" | "magenta", highlightColor: "white" | "black" | "red" | "green" | "blue" | "yellow" | "orange" | "purple" | "pink" | "brown" | "gray" | "cyan" | "magenta", strokeWidth: number, strokeColor: "black" | "white" | "red" | "green" | "blue" | "yellow" | "orange" | "purple" | "pink" | "brown" | "gray" | "cyan" | "magenta", backgroundColor: "black" | "white" | "red" | "green" | "blue" | "yellow" | "orange" | "purple" | "pink" | "brown" | "gray" | "cyan" | "magenta" | "none", backgroundOpacity: number, position: "top" | "center" | "bottom", yOffset: number, wordsPerSubtitle: number, enableAnimation: boolean, intermediateAsset?: boolean }`
247
+ - Output: `{ videoUrl: string }`
248
+
249
+ #### analyzeImage
250
+ Analyze an image using a vision model based on a text prompt.
251
+ - Uses the configured vision model to generate a text analysis of the image.
252
+ - The prompt should describe what to look for or extract from the image.
253
+ - Input: `{ prompt: string, imageUrl: string, visionModelOverride?: { model: string, config?: object } | { model: string, temperature: number, maxResponseTokens: number, ignorePreamble?: boolean, userMessagePreprocessor?: { dataSource?: string, messageTemplate?: string, maxResults?: number, enabled?: boolean, shouldInherit?: boolean }, preamble?: string, multiModelEnabled?: boolean, editResponseEnabled?: boolean, config?: object } }`
254
+ - Output: `{ analysis: string }`
255
+
256
+ #### analyzeVideo
257
+ Analyze a video using a video analysis model based on a text prompt.
258
+ - Uses the configured video analysis model to generate a text analysis of the video.
259
+ - The prompt should describe what to look for or extract from the video.
260
+ - Input: `{ prompt: string, videoUrl: string, videoAnalysisModelOverride?: { model: string, config?: object } | { model: string, temperature: number, maxResponseTokens: number, ignorePreamble?: boolean, userMessagePreprocessor?: { dataSource?: string, messageTemplate?: string, maxResults?: number, enabled?: boolean, shouldInherit?: boolean }, preamble?: string, multiModelEnabled?: boolean, editResponseEnabled?: boolean, config?: object } }`
261
+ - Output: `{ analysis: string }`
262
+
263
+ #### captureThumbnail
264
+ Capture a thumbnail from a video at a specified timestamp
265
+ - Input: `{ videoUrl: string, at: number | string }`
266
+ - Output: `{ thumbnailUrl: string }`
267
+
268
+ #### checkAppRole
269
+ Check whether the current user has a specific app role and branch accordingly.
270
+ - Checks if the current user has been assigned a specific role in this app.
271
+ - If the user has the role, transitions to the "has role" path.
272
+ - If the user does not have the role, transitions to the "no role" path, or errors if no path is configured.
273
+ - Role names are defined by the app creator and assigned to users via the app roles system.
274
+ - The roleName field supports {{variables}} for dynamic role checks.
275
+ - Input: `{ roleName: string, hasRoleStepId?: string, hasRoleWorkflowId?: string, noRoleStepId?: string, noRoleWorkflowId?: string }`
276
+ - Output: `{ hasRole: boolean, userRoles: string[] }`
277
+
278
+ #### convertPdfToImages
279
+ Convert each page of a PDF document into a PNG image.
280
+ - Each page is converted to a separate PNG and re-hosted on the CDN.
281
+ - Returns an array of image URLs, one per page.
282
+ - Input: `{ pdfUrl: string }`
283
+ - Output: `{ imageUrls: string[] }`
284
+
285
+ #### createDataSource
286
+ Create a new empty vector data source for the current app.
287
+ - Creates a new data source (vector database) associated with the current app version.
288
+ - The data source is created empty — use the "Upload Data Source Document" block to add documents.
289
+ - Returns the new data source ID which can be used in subsequent blocks.
290
+ - Input: `{ name: string }`
291
+ - Output: `unknown`
292
+
293
+ #### createGmailDraft
294
+ Create a draft email in the connected Gmail account.
295
+ - Requires a Google OAuth connection with Gmail compose scope.
296
+ - The draft appears in the user's Gmail Drafts folder but is not sent.
297
+ - messageType controls the body format: "plain" for plain text, "html" for raw HTML, "markdown" for auto-converted markdown.
298
+ - Input: `{ to: string, subject: string, message: string, connectionId?: string, messageType: "plain" | "html" | "markdown" }`
299
+ - Output: `{ draftId: string }`
300
+
301
+ #### deleteDataSource
302
+ Delete a vector data source from the current app.
303
+ - Soft-deletes a data source (vector database) by marking it as deleted.
304
+ - The Milvus partition is cleaned up asynchronously by a background cron job.
305
+ - The data source must belong to the current app version.
306
+ - Input: `{ dataSourceId: string }`
307
+ - Output: `unknown`
308
+
309
+ #### deleteDataSourceDocument
310
+ Delete a single document from a data source.
311
+ - Soft-deletes a document by marking it as deleted.
312
+ - Requires both the data source ID and document ID.
313
+ - After deletion, reloads vectors into Milvus so the data source reflects the change immediately.
314
+ - Input: `{ dataSourceId: string, documentId: string }`
315
+ - Output: `unknown`
316
+
317
+ #### detectChanges
318
+ Detect changes between runs by comparing current input against previously stored state. Routes execution based on whether a change occurred.
319
+ - Persists state across runs using a global variable keyed to the step ID.
320
+ - Two modes: "comparison" (default) uses strict string inequality; "ai" uses an LLM to determine if a meaningful change occurred.
321
+ - First run always treats the value as "changed" since there is no previous state.
322
+ - Each mode supports transitions to different steps/workflows for the "changed" and "unchanged" paths.
323
+ - AI mode bills normally for the LLM call.
324
+ - Input: `{ mode: "ai" | "comparison", input: string, prompt?: string, modelOverride?: { model: string, temperature: number, maxResponseTokens: number, ignorePreamble?: boolean, userMessagePreprocessor?: { dataSource?: string, messageTemplate?: string, maxResults?: number, enabled?: boolean, shouldInherit?: boolean }, preamble?: string, multiModelEnabled?: boolean, editResponseEnabled?: boolean, config?: object }, previousValueVariable?: string, changedStepId?: string, changedWorkflowId?: string, unchangedStepId?: string, unchangedWorkflowId?: string }`
325
+ - Output: `{ hasChanged: boolean, currentValue: string, previousValue: string, isFirstRun: boolean }`
326
+
327
+ #### detectPII
328
+ Scan text for personally identifiable information using Microsoft Presidio.
329
+ - In workflow mode, transitions to detectedStepId if PII is found, notDetectedStepId otherwise.
330
+ - In direct execution, returns the detection results without transitioning.
331
+ - If entities is empty, returns immediately with no detections.
332
+ - Input: `{ input: string, language: string, entities: string[], detectedStepId?: string, notDetectedStepId?: string, outputLogVariable?: string | null }`
333
+ - Output: `{ detected: boolean, detections: { entity_type: string, start: number, end: number, score: number }[] }`
334
+
335
+ #### discordEditMessage
336
+ Edit a previously sent Discord channel message. Use with the message ID returned by Send Discord Message.
337
+ - Only messages sent by the bot can be edited.
338
+ - The messageId is returned by the Send Discord Message step.
339
+ - Optionally attach a file by providing a URL to attachmentUrl. The file is downloaded and uploaded to Discord.
340
+ - When editing with an attachment, the new attachment replaces any previous attachments on the message.
341
+ - URLs in the text are automatically embedded by Discord (link previews for images, videos, etc.).
342
+ - Input: `{ botToken: string, channelId: string, messageId: string, text: string, attachmentUrl?: string }`
343
+ - Output: `unknown`
344
+
345
+ #### discordSendFollowUp
346
+ Send a follow-up message to a Discord slash command interaction.
347
+ - Requires the applicationId and interactionToken from the Discord trigger variables.
348
+ - Follow-up messages appear as new messages in the channel after the initial response.
349
+ - Returns the sent message ID.
350
+ - Interaction tokens expire after 15 minutes.
351
+ - Optionally attach a file by providing a URL to attachmentUrl. The file is downloaded and uploaded to Discord.
352
+ - URLs in the text are automatically embedded by Discord (link previews for images, videos, etc.).
353
+ - Input: `{ applicationId: string, interactionToken: string, text: string, attachmentUrl?: string }`
354
+ - Output: `{ messageId: string }`
355
+
356
+ #### discordSendMessage
357
+ Send a message to Discord — either edit the loading message or send a new channel message.
358
+ - mode "edit" replaces the loading message (interaction response) with the final result. Uses applicationId and interactionToken from trigger variables. No bot permissions required.
359
+ - mode "send" sends a new message to a channel. Uses botToken and channelId from trigger variables. Returns a messageId that can be used with Edit Discord Message.
360
+ - Optionally attach a file by providing a URL to attachmentUrl. The file is downloaded and uploaded to Discord.
361
+ - URLs in the text are automatically embedded by Discord (link previews for images, videos, etc.).
362
+ - Interaction tokens expire after 15 minutes.
363
+ - Input: `{ mode: "edit" | "send", text: string, applicationId?: string, interactionToken?: string, botToken?: string, channelId?: string, attachmentUrl?: string }`
364
+ - Output: `{ messageId?: string }`
365
+
366
+ #### downloadVideo
367
+ Download a video file
368
+ - Works with YouTube, TikTok, etc., by using ytdlp behind the scenes
369
+ - Can save as mp4 or mp3
370
+ - Input: `{ videoUrl: string, format: "mp4" | "mp3" }`
371
+ - Output: `{ videoUrl: string }`
372
+
373
+ #### enhanceImageGenerationPrompt
374
+ Generate or enhance an image generation prompt using a language model. Optionally generates a negative prompt.
375
+ - Rewrites the user's prompt with added detail about style, lighting, colors, and composition.
376
+ - Also useful for initial generation, it doesn't always need to be enhancing an existing prompt
377
+ - When includeNegativePrompt is true, a second model call generates a negative prompt.
378
+ - Input: `{ initialPrompt: string, includeNegativePrompt: boolean, negativePromptDestinationVariableName?: string, systemPrompt: string, modelOverride?: unknown }`
379
+ - Output: `{ prompt: string, negativePrompt?: string }`
380
+
381
+ #### enhanceVideoGenerationPrompt
382
+ Generate or enhance a video generation prompt using a language model. Optionally generates a negative prompt.
383
+ - Rewrites the user's prompt with added detail about style, camera movement, lighting, and composition.
384
+ - Also useful for initial generation, it doesn't always need to be enhancing an existing prompt
385
+ - When includeNegativePrompt is true, a second model call generates a negative prompt.
386
+ - Input: `{ initialPrompt: string, includeNegativePrompt: boolean, negativePromptDestinationVariableName?: string, systemPrompt: string, modelOverride?: unknown }`
387
+ - Output: `{ prompt: string, negativePrompt?: string }`
388
+
389
+ #### extractAudioFromVideo
390
+ Extract audio MP3 from a video file
391
+ - Input: `{ videoUrl: string }`
392
+ - Output: `{ audioUrl: string }`
393
+
394
+ #### extractText
395
+ Download a file from a URL and extract its text content. Supports PDFs, plain text files, and other document formats.
396
+ - Best suited for PDFs and raw text/document files. For web pages, use the scrapeUrl step instead.
397
+ - Accepts a single URL, a comma-separated list of URLs, or a JSON array of URLs.
398
+ - Files are rehosted on the MindStudio CDN before extraction.
399
+ - Maximum file size is 50MB per URL.
400
+ - Input: `{ url: string | string[] }`
401
+ - Output: `{ text: string | string[] }`
402
+
403
+ #### fetchDataSourceDocument
404
+ Fetch the full extracted text contents of a document in a data source.
405
+ - Loads a document by ID and returns its full extracted text content.
406
+ - The document must have been successfully processed (status "done").
407
+ - Also returns document metadata (name, summary, word count).
408
+ - Input: `{ dataSourceId: string, documentId: string }`
409
+ - Output: `unknown`
410
+
411
+ #### fetchSlackChannelHistory
412
+ Fetch recent message history from a Slack channel.
413
+ - The user is responsible for connecting their Slack workspace and selecting the channel
414
+ - Input: `{ connectionId?: string, channelId: string, limit?: number, startDate?: string, endDate?: string, includeImages?: boolean, includeRawMessage?: boolean }`
415
+ - Output: `{ messages: { from: string, content: string, timestamp?: string, images?: string[], rawMessage?: { app_id?: string, assistant_app_thread?: { first_user_thread_reply?: string, title?: string, title_blocks?: unknown[] }, attachments?: { actions?: unknown[], app_id?: string, app_unfurl_url?: string, author_icon?: string, author_id?: string, author_link?: string, author_name?: string, author_subname?: string, blocks?: unknown[], bot_id?: string, bot_team_id?: string, callback_id?: string, channel_id?: string, channel_name?: string, channel_team?: string, color?: string, fallback?: string, fields?: unknown[], file_id?: string, filename?: string, files?: unknown[], footer?: string, footer_icon?: string, from_url?: string, hide_border?: boolean, hide_color?: boolean, id?: number, image_bytes?: number, image_height?: number, image_url?: string, image_width?: number, indent?: boolean, is_app_unfurl?: boolean, is_file_attachment?: boolean, is_msg_unfurl?: boolean, is_reply_unfurl?: boolean, is_thread_root_unfurl?: boolean, list?: unknown, list_record?: unknown, list_record_id?: string, list_records?: unknown[], list_schema?: unknown[], list_view?: unknown, list_view_id?: string, message_blocks?: unknown[], metadata?: unknown, mimetype?: string, mrkdwn_in?: string[], msg_subtype?: string, original_url?: string, pretext?: string, preview?: unknown, service_icon?: string, service_name?: string, service_url?: string, size?: number, text?: string, thumb_height?: number, thumb_url?: string, thumb_width?: number, title?: string, title_link?: string, ts?: string, url?: string, video_html?: string, video_html_height?: number, video_html_width?: number, video_url?: string }[], blocks?: { accessory?: unknown, alt_text?: string, api_decoration_available?: boolean, app_collaborators?: string[], app_id?: string, author_name?: string, block_id?: string, bot_user_id?: string, button_label?: string, call?: unknown, call_id?: string, description?: unknown, developer_trace_id?: string, dispatch_action?: boolean, element?: unknown, elements?: unknown[], expand?: boolean, external_id?: string, fallback?: string, fields?: unknown[], file?: unknown, file_id?: string, function_trigger_id?: string, hint?: unknown, image_bytes?: number, image_height?: number, image_url?: string, image_width?: number, is_animated?: boolean, is_workflow_app?: boolean, label?: unknown, optional?: boolean, owning_team_id?: string, provider_icon_url?: string, provider_name?: string, sales_home_workflow_app_type?: number, share_url?: string, slack_file?: unknown, source?: string, text?: unknown, thumbnail_url?: string, title?: unknown, title_url?: string, trigger_subtype?: string, trigger_type?: string, type?: unknown, url?: string, video_url?: string, workflow_id?: string }[], bot_id?: string, bot_profile?: { app_id?: string, deleted?: boolean, icons?: unknown, id?: string, name?: string, team_id?: string, updated?: number }, client_msg_id?: string, display_as_bot?: boolean, edited?: { ts?: string, user?: string }, files?: { access?: string, alt_txt?: string, app_id?: string, app_name?: string, attachments?: unknown[], blocks?: unknown[], bot_id?: string, can_toggle_canvas_lock?: boolean, canvas_printing_enabled?: boolean, canvas_template_mode?: string, cc?: unknown[], channel_actions_count?: number, channel_actions_ts?: string, channels?: string[], comments_count?: number, converted_pdf?: string, created?: number, deanimate?: string, deanimate_gif?: string, display_as_bot?: boolean, dm_mpdm_users_with_file_access?: unknown[], duration_ms?: number, edit_link?: string, edit_timestamp?: number, editable?: boolean, editor?: string, editors?: string[], external_id?: string, external_type?: string, external_url?: string, favorites?: unknown[], file_access?: string, filetype?: string, from?: unknown[], groups?: string[], has_more?: boolean, has_more_shares?: boolean, has_rich_preview?: boolean, headers?: unknown, hls?: string, hls_embed?: string, id?: string, image_exif_rotation?: number, ims?: string[], initial_comment?: unknown, is_channel_space?: boolean, is_external?: boolean, is_public?: boolean, is_restricted_sharing_enabled?: boolean, is_starred?: boolean, last_editor?: string, last_read?: number, lines?: number, lines_more?: number, linked_channel_id?: string, list_csv_download_url?: string, list_limits?: unknown, list_metadata?: unknown, media_display_type?: string, media_progress?: unknown, mimetype?: string, mode?: string, mp4?: string, mp4_low?: string, name?: string, non_owner_editable?: boolean, num_stars?: number, org_or_workspace_access?: string, original_attachment_count?: number, original_h?: string, original_w?: string, permalink?: string, permalink_public?: string, pinned_to?: string[], pjpeg?: string, plain_text?: string, pretty_type?: string, preview?: string, preview_highlight?: string, preview_is_truncated?: boolean, preview_plain_text?: string, private_channels_with_file_access_count?: number, private_file_with_access_count?: number, public_url_shared?: boolean, quip_thread_id?: string, reactions?: unknown[], saved?: unknown, sent_to_self?: boolean, shares?: unknown, show_badge?: boolean, simplified_html?: string, size?: number, source_team?: string, subject?: string, subtype?: string, team_pref_version_history_enabled?: boolean, teams_shared_with?: unknown[], template_conversion_ts?: number, template_description?: string, template_icon?: string, template_name?: string, template_title?: string, thumb_1024?: string, thumb_1024_gif?: string, thumb_1024_h?: string, thumb_1024_w?: string, thumb_160?: string, thumb_160_gif?: string, thumb_160_h?: string, thumb_160_w?: string, thumb_360?: string, thumb_360_gif?: string, thumb_360_h?: string, thumb_360_w?: string, thumb_480?: string, thumb_480_gif?: string, thumb_480_h?: string, thumb_480_w?: string, thumb_64?: string, thumb_64_gif?: string, thumb_64_h?: string, thumb_64_w?: string, thumb_720?: string, thumb_720_gif?: string, thumb_720_h?: string, thumb_720_w?: string, thumb_80?: string, thumb_800?: string, thumb_800_gif?: string, thumb_800_h?: string, thumb_800_w?: string, thumb_80_gif?: string, thumb_80_h?: string, thumb_80_w?: string, thumb_960?: string, thumb_960_gif?: string, thumb_960_h?: string, thumb_960_w?: string, thumb_gif?: string, thumb_pdf?: string, thumb_pdf_h?: string, thumb_pdf_w?: string, thumb_tiny?: string, thumb_video?: string, thumb_video_h?: number, thumb_video_w?: number, timestamp?: number, title?: string, title_blocks?: unknown[], to?: unknown[], transcription?: unknown, update_notification?: number, updated?: number, url_private?: string, url_private_download?: string, url_static_preview?: string, user?: string, user_team?: string, username?: string, vtt?: string }[], icons?: { emoji?: string, image_36?: string, image_48?: string, image_64?: string, image_72?: string }, inviter?: string, is_locked?: boolean, latest_reply?: string, metadata?: { event_payload?: unknown, event_type?: string }, parent_user_id?: string, purpose?: string, reactions?: { count?: number, name?: string, url?: string, users?: string[] }[], reply_count?: number, reply_users?: string[], reply_users_count?: number, root?: { bot_id?: string, icons?: unknown, latest_reply?: string, parent_user_id?: string, reply_count?: number, reply_users?: string[], reply_users_count?: number, subscribed?: boolean, subtype?: string, text?: string, thread_ts?: string, ts?: string, type?: string, username?: string }, subscribed?: boolean, subtype?: string, team?: string, text?: string, thread_ts?: string, topic?: string, ts?: string, type?: string, upload?: boolean, user?: string, username?: string, x_files?: string[] } }[] }`
416
+
417
+ #### generateAsset
418
+ Generate an HTML asset and export it as a webpage, PDF, or image
419
+ - Agents can generate HTML documents and export as webpage, PDFs, images, or videos. They do this by using the "generatePdf" block, which defines an HTML page with variables, and then the generation process renders the page to create the output and save its URL at the specified variable.
420
+ - The template for the HTML page is generated by a separate process, and it can only use variables that have already been defined in the workflow at the time of its execution. It has full access to handlebars to render the HTML template, including a handlebars helper to render a markdown variable string as HTML (which can be useful for creating templates that render long strings). The template can also create its own simple JavaScript to do things like format dates and strings.
421
+ - If PDF or composited image generation are part of the workflow, assistant adds the block and leaves the "source" empty. In a separate step, assistant generates a detailed request for the developer who will write the HTML.
422
+ - Can also auto-generate HTML from a prompt (like a generate text block to generate HTML). In these cases, create a prompt with variables in the dynamicPrompt variable describing, in detail, the document to generate
423
+ - Can either display output directly to user (foreground mode) or save the URL of the asset to a variable (background mode)
424
+ - Input: `{ source: string, sourceType: "html" | "markdown" | "spa" | "raw" | "dynamic" | "customInterface", outputFormat: "pdf" | "png" | "html" | "mp4" | "openGraph", pageSize: "full" | "letter" | "A4" | "custom", testData: object, options?: { pageWidthPx?: number, pageHeightPx?: number, pageOrientation?: "portrait" | "landscape", rehostMedia?: boolean, videoDurationSeconds?: number }, spaSource?: { source?: string, lastCompiledSource?: string, files?: object, paths: string[], root: string, zipUrl: string }, rawSource?: string, dynamicPrompt?: string, dynamicSourceModelOverride?: { model: string, temperature: number, maxResponseTokens: number, ignorePreamble?: boolean, userMessagePreprocessor?: { dataSource?: string, messageTemplate?: string, maxResults?: number, enabled?: boolean, shouldInherit?: boolean }, preamble?: string, multiModelEnabled?: boolean, editResponseEnabled?: boolean, config?: object }, transitionControl?: "default" | "native", shareControl?: "default" | "hidden", shareImageUrl?: string, intermediateAsset?: boolean }`
425
+ - Output: `{ url: string }`
426
+
427
+ #### generateChart
428
+ Create a chart image using QuickChart (Chart.js) and return the URL.
429
+ - The data field must be a Chart.js-compatible JSON object serialized as a string.
430
+ - Supported chart types: bar, line, pie.
431
+ - Input: `{ chart: { chartType: "bar" | "line" | "pie", data: string, options: { width: string, height: string } } }`
432
+ - Output: `{ chartUrl: string }`
433
+
434
+ #### generateImage
435
+ Generate an image from a text prompt using an AI model.
436
+ - Prompts should be descriptive but concise (roughly 3–6 sentences).
437
+ - Images are automatically hosted on a CDN.
438
+ - In foreground mode, the image is displayed to the user. In background mode, the URL is saved to a variable.
439
+ - When generateVariants is true with numVariants > 1, multiple images are generated in parallel.
440
+ - In direct execution, foreground mode behaves as background, and userSelect variant behavior behaves as saveAll.
441
+ - Input: `{ prompt: string, intermediateAsset?: boolean, imageModelOverride?: { model: string, config?: object }, generateVariants?: boolean, numVariants?: number, addWatermark?: boolean }`
442
+ - Output: `{ imageUrl: string | string[] }`
443
+
444
+ #### generateLipsync
445
+ Generate a lip sync video from provided audio and image.
446
+ - In foreground mode, the video is displayed to the user. In background mode, the URL is saved to a variable.
447
+ - Input: `{ intermediateAsset?: boolean, addWatermark?: boolean, lipsyncModelOverride?: { model: string, config?: object } }`
448
+ - Output: `unknown`
449
+
450
+ #### generateMusic
451
+ Generate an audio file from provided instructions (text) using a music model.
452
+ - The text field contains the instructions (prompt) for the music generation.
453
+ - In foreground mode, the audio is displayed to the user. In background mode, the URL is saved to a variable.
454
+ - Input: `{ text: string, intermediateAsset?: boolean, musicModelOverride?: { model: string, config?: object } }`
455
+ - Output: `unknown`
456
+
457
+ #### generateStaticVideoFromImage
458
+ Convert a static image to an MP4
459
+ - Can use to create slides/intertitles/slates for video composition
460
+ - Input: `{ imageUrl: string, duration: string }`
461
+ - Output: `{ videoUrl: string }`
462
+
463
+ #### generateText
464
+ Send a message to an AI model and return the response, or echo a system message.
465
+ - Source "user" sends the message to an LLM and returns the model's response.
466
+ - Source "system" echoes the message content directly (no AI call).
467
+ - Mode "background" saves the result to a variable. Mode "foreground" streams it to the user (not available in direct execution).
468
+ - Structured output (JSON/CSV) can be enforced via structuredOutputType and structuredOutputExample.
469
+ - Input: `{ message: string, source?: "user" | "system", modelOverride?: { model: string, temperature: number, maxResponseTokens: number, ignorePreamble?: boolean, userMessagePreprocessor?: { dataSource?: string, messageTemplate?: string, maxResults?: number, enabled?: boolean, shouldInherit?: boolean }, preamble?: string, multiModelEnabled?: boolean, editResponseEnabled?: boolean, config?: object }, structuredOutputType?: "text" | "json" | "csv", structuredOutputExample?: string, chatHistoryMode?: "include" | "exclude" }`
470
+ - Output: `{ content: string }`
471
+
472
+ #### generateVideo
473
+ Generate a video from a text prompt using an AI model.
474
+ - Prompts should be descriptive but concise (roughly 3–6 sentences).
475
+ - Videos are automatically hosted on a CDN.
476
+ - In foreground mode, the video is displayed to the user. In background mode, the URL is saved to a variable.
477
+ - When generateVariants is true with numVariants > 1, multiple videos are generated in parallel.
478
+ - In direct execution, foreground mode behaves as background, and userSelect variant behavior behaves as saveAll.
479
+ - Input: `{ prompt: string, intermediateAsset?: boolean, videoModelOverride?: { model: string, config?: object }, generateVariants?: boolean, numVariants?: number, addWatermark?: boolean }`
480
+ - Output: `{ videoUrl: string | string[] }`
481
+
482
+ #### getGmailAttachments
483
+ Download attachments from a Gmail email and re-host them on CDN.
484
+ - Requires a Google OAuth connection with Gmail readonly scope.
485
+ - Attachments are uploaded to CDN and returned as URLs.
486
+ - Attachments larger than 25MB are skipped.
487
+ - Use the message ID from Search Gmail Emails, List Recent Gmail Emails, or Get Gmail Email steps.
488
+ - Input: `{ messageId: string, connectionId?: string }`
489
+ - Output: `unknown`
490
+
491
+ #### getGmailUnreadCount
492
+ Get the number of unread emails in the connected Gmail inbox.
493
+ - Requires a Google OAuth connection with Gmail readonly scope.
494
+ - Returns the unread message count for the inbox label.
495
+ - This is a lightweight call that does not fetch any email content.
496
+ - Input: `{ connectionId?: string }`
497
+ - Output: `unknown`
498
+
499
+ #### getMediaMetadata
500
+ Get info about a media file
501
+ - Input: `{ mediaUrl: string }`
502
+ - Output: `{ metadata: string }`
503
+
504
+ #### httpRequest
505
+ Make an HTTP request to an external endpoint and return the response.
506
+ - Supports GET, POST, PATCH, DELETE, and PUT methods.
507
+ - Body can be raw JSON/text, URL-encoded form data, or multipart form data.
508
+ - Input: `{ url: string, method: string, headers: object, queryParams: object, body: string, bodyItems: object, contentType: "none" | "application/json" | "application/x-www-form-urlencoded" | "multipart/form-data" | "custom", customContentType: string, testData?: object }`
509
+ - Output: `{ ok: boolean, status: number, statusText: string, response: string }`
510
+
511
+ #### imageFaceSwap
512
+ Replace a face in an image with a face from another image using AI.
513
+ - Requires both a target image and a face source image.
514
+ - Output is re-hosted on the CDN as a PNG.
515
+ - Input: `{ imageUrl: string, faceImageUrl: string, engine: string }`
516
+ - Output: `{ imageUrl: string }`
517
+
518
+ #### imageRemoveWatermark
519
+ Remove watermarks from an image using AI.
520
+ - Output is re-hosted on the CDN as a PNG.
521
+ - Input: `{ imageUrl: string, engine: string, intermediateAsset?: boolean }`
522
+ - Output: `{ imageUrl: string }`
523
+
524
+ #### insertVideoClips
525
+ Insert b-roll clips into a base video at a timecode, optionally with an xfade transition.
526
+ - Input: `{ baseVideoUrl: string, overlayVideos: { videoUrl: string, startTimeSec: number }[], transition?: string, transitionDuration?: number, useOverlayAudio?: boolean, intermediateAsset?: boolean }`
527
+ - Output: `{ videoUrl: string }`
528
+
529
+ #### listDataSources
530
+ List all data sources for the current app.
531
+ - Returns metadata for every data source associated with the current app version.
532
+ - Each entry includes the data source ID, name, description, status, and document list.
533
+ - Input: `object`
534
+ - Output: `unknown`
535
+
536
+ #### listGmailLabels
537
+ List all labels in the connected Gmail account. Use these label IDs or names with the Update Gmail Labels step.
538
+ - Requires a Google OAuth connection with Gmail readonly scope.
539
+ - Returns both system labels (INBOX, SENT, TRASH, etc.) and user-created labels.
540
+ - Label type is "system" for built-in labels or "user" for custom labels.
541
+ - Input: `{ connectionId?: string }`
542
+ - Output: `unknown`
543
+
544
+ #### listRecentGmailEmails
545
+ List recent emails from the connected Gmail inbox.
546
+ - Requires a Google OAuth connection with Gmail readonly scope.
547
+ - Returns up to 100 emails (default 5), ordered by most recent first.
548
+ - Functionally equivalent to Search Gmail Emails with an "in:inbox" query.
549
+ - Input: `{ connectionId?: string, exportType: "json" | "text", limit: string }`
550
+ - Output: `unknown`
551
+
552
+ #### logic
553
+ Route execution to different branches based on AI evaluation, comparison operators, or workflow jumps.
554
+ - Supports two modes: "ai" (default) uses an AI model to pick the most accurate statement; "comparison" uses operator-based checks.
555
+ - In AI mode, the model picks the most accurate statement from the list. All possible cases must be specified.
556
+ - In comparison mode, the context is the left operand and each case's condition is the right operand. First matching case wins. Use operator "default" as a fallback.
557
+ - Requires at least two cases.
558
+ - Each case can transition to a step in the current workflow (destinationStepId) or jump to another workflow (destinationWorkflowId).
559
+ - Input: `{ mode?: "ai" | "comparison", context: string, cases: ({ id: string, condition: string, operator?: "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "exists" | "not_exists" | "contains" | "not_contains" | "default", destinationStepId?: string, destinationWorkflowId?: string } | string)[], modelOverride?: { model: string, temperature: number, maxResponseTokens: number, ignorePreamble?: boolean, userMessagePreprocessor?: { dataSource?: string, messageTemplate?: string, maxResults?: number, enabled?: boolean, shouldInherit?: boolean }, preamble?: string, multiModelEnabled?: boolean, editResponseEnabled?: boolean, config?: object } }`
560
+ - Output: `{ selectedCase: number }`
561
+
562
+ #### makeDotComRunScenario
563
+ Trigger a Make.com (formerly Integromat) scenario via webhook and return the response.
564
+ - The webhook URL must be configured in your Make.com scenario.
565
+ - Input key-value pairs are sent as JSON in the POST body.
566
+ - Response format depends on the Make.com scenario configuration.
567
+ - Input: `{ webhookUrl: string, input: object }`
568
+ - Output: `{ data: unknown }`
569
+
570
+ #### mergeAudio
571
+ Merge one or more clips into a single audio file.
572
+ - Input: `{ mp3Urls: string[], fileMetadata?: object, albumArtUrl?: string, intermediateAsset?: boolean }`
573
+ - Output: `{ audioUrl: string }`
574
+
575
+ #### mergeVideos
576
+ Merge one or more clips into a single video.
577
+ - Input: `{ videoUrls: string[], transition?: string, transitionDuration?: number, intermediateAsset?: boolean }`
578
+ - Output: `{ videoUrl: string }`
579
+
580
+ #### mixAudioIntoVideo
581
+ Mix an audio track into a video
582
+ - Input: `{ videoUrl: string, audioUrl: string, options: { keepVideoAudio?: boolean, audioGainDb?: number, videoGainDb?: number, loopAudio?: boolean }, intermediateAsset?: boolean }`
583
+ - Output: `{ videoUrl: string }`
584
+
585
+ #### muteVideo
586
+ Mute a video file
587
+ - Input: `{ videoUrl: string, intermediateAsset?: boolean }`
588
+ - Output: `{ videoUrl: string }`
589
+
590
+ #### n8nRunNode
591
+ Trigger an n8n workflow node via webhook and return the response.
592
+ - The webhook URL must be configured in your n8n workflow.
593
+ - Supports GET and POST methods with optional Basic authentication.
594
+ - For GET requests, input values are sent as query parameters. For POST, they are sent as JSON body.
595
+ - Input: `{ method: string, authentication: "none" | "basic" | "string", user: string, password: string, webhookUrl: string, input: object }`
596
+ - Output: `{ data: unknown }`
597
+
598
+ #### postToSlackChannel
599
+ Send a message to a Slack channel via a connected bot.
600
+ - The user is responsible for connecting their Slack workspace and selecting the channel
601
+ - Supports both simple text messages and slack blocks messages
602
+ - Text messages can use limited markdown (slack-only fomatting—e.g., headers are just rendered as bold)
603
+ - Input: `{ channelId: string, messageType: "string" | "blocks", message: string, connectionId?: string }`
604
+ - Output: `unknown`
605
+
606
+ #### postToZapier
607
+ Send data to a Zapier Zap via webhook and return the response.
608
+ - The webhook URL must be configured in the Zapier Zap settings
609
+ - Input keys and values are sent as the JSON body of the POST request
610
+ - The webhook response (JSON or plain text) is returned as the output
611
+ - Input: `{ webhookUrl: string, input: object }`
612
+ - Output: `{ data: unknown }`
613
+
614
+ #### queryAppDatabase
615
+ Execute a SQL query against the app managed database.
616
+ - Executes raw SQL against a SQLite database managed by the app.
617
+ - For SELECT queries, returns rows as JSON.
618
+ - For INSERT/UPDATE/DELETE, returns the number of affected rows.
619
+ - Use {{variables}} directly in your SQL. By default they are automatically extracted
620
+ and passed as safe parameterized values (preventing SQL injection).
621
+ Example: INSERT INTO contacts (name, comment) VALUES ({{name}}, {{comment}})
622
+ - Full MindStudio handlebars syntax is supported, including helpers like {{json myVar}},
623
+ {{get myVar "$.path"}}, {{global.orgName}}, etc.
624
+ - Set parameterize to false for raw/dynamic SQL where variables are interpolated directly
625
+ into the query string. Use this when another step generates full or partial SQL, e.g.
626
+ a bulk INSERT with a precomputed VALUES list. The user is responsible for sanitization
627
+ when parameterize is false.
628
+ - Input: `{ databaseId: string, sql: string, parameterize?: boolean }`
629
+ - Output: `{ rows: unknown[], changes: number }`
630
+
631
+ #### queryDataSource
632
+ Search a vector data source (RAG) and return relevant document chunks.
633
+ - Queries a vectorized data source and returns the most relevant chunks.
634
+ - Useful for retrieval-augmented generation (RAG) workflows.
635
+ - Input: `{ dataSourceId: string, query: string, maxResults: number }`
636
+ - Output: `{ text: string, chunks: string[], query: string, citations: unknown[], latencyMs: number }`
637
+
638
+ #### queryExternalDatabase
639
+ Execute a SQL query against an external database connected to the workspace.
640
+ - Requires a database connection configured in the workspace.
641
+ - Supports PostgreSQL (including Supabase), MySQL, and MSSQL.
642
+ - Results can be returned as JSON or CSV.
643
+ - Input: `{ connectionId?: string, query: string, outputFormat: "json" | "csv" }`
644
+ - Output: `{ data: unknown }`
645
+
646
+ #### redactPII
647
+ Replace personally identifiable information in text with placeholders using Microsoft Presidio.
648
+ - PII is replaced with entity type placeholders (e.g. "Call me at <PHONE_NUMBER>").
649
+ - If entities is empty, returns empty text immediately without processing.
650
+ - Input: `{ input: string, language: string, entities: string[] }`
651
+ - Output: `{ text: string }`
652
+
653
+ #### removeBackgroundFromImage
654
+ Remove the background from an image using AI, producing a transparent PNG.
655
+ - Uses the Bria background removal model via fal.ai.
656
+ - Output is re-hosted on the CDN as a PNG with transparency.
657
+ - Input: `{ imageUrl: string }`
658
+ - Output: `{ imageUrl: string }`
659
+
660
+ #### resizeVideo
661
+ Resize a video file
662
+ - Input: `{ videoUrl: string, mode: "fit" | "exact", maxWidth?: number, maxHeight?: number, width?: number, height?: number, strategy?: "pad" | "crop", intermediateAsset?: boolean }`
663
+ - Output: `{ videoUrl: string }`
664
+
665
+ #### runFromConnectorRegistry
666
+ Run a raw API connector to a third-party service
667
+ - Use the /developer/v2/helpers/connectors endpoint to list available services and actions.
668
+ - Use /developer/v2/helpers/connectors/{serviceId}/{actionId} to get the full input configuration for an action.
669
+ - Use /developer/v2/helpers/connections to list your available OAuth connections.
670
+ - The actionId format is "serviceId/actionId" (e.g., "slack/send-message").
671
+ - Pass a __connectionId to authenticate the request with a specific OAuth connection, otherwise the default will be used (if configured).
672
+ - Input: `{ actionId: string, displayName: string, icon: string, configurationValues: object, __connectionId?: string }`
673
+ - Output: `{ data: object }`
674
+
675
+ #### runPackagedWorkflow
676
+ Run a packaged workflow ("custom block")
677
+ - From the user's perspective, packaged workflows are just ordinary blocks. Behind the scenes, they operate like packages/libraries in a programming language, letting the user execute custom functionality.
678
+ - Some of these packaged workflows are available as part of MindStudio's "Standard Library" and available to every user.
679
+ - Available packaged workflows are documented here as individual blocks, but the runPackagedWorkflow block is how they need to be wrapped in order to be executed correctly.
680
+ - Input: `{ appId: string, workflowId: string, inputVariables: object, outputVariables: object, name: string }`
681
+ - Output: `{ data: unknown }`
682
+
683
+ #### scrapeLinkedInCompany
684
+ Scrape public company data from a LinkedIn company page.
685
+ - Requires a LinkedIn company URL (e.g. https://www.linkedin.com/company/mindstudioai).
686
+ - Returns structured company data including description, employees, updates, and similar companies.
687
+ - Input: `{ url: string }`
688
+ - Output: `{ company: unknown }`
689
+
690
+ #### scrapeLinkedInProfile
691
+ Scrape public profile data from a LinkedIn profile page.
692
+ - Requires a LinkedIn profile URL (e.g. https://www.linkedin.com/in/username).
693
+ - Returns structured profile data including experience, education, articles, and activities.
694
+ - Input: `{ url: string }`
695
+ - Output: `{ profile: unknown }`
696
+
697
+ #### scrapeUrl
698
+ Extract text, HTML, or structured content from one or more web pages.
699
+ - Accepts a single URL or multiple URLs (as a JSON array, comma-separated, or newline-separated).
700
+ - Output format controls the result shape: "text" returns markdown, "html" returns raw HTML, "json" returns structured scraper data.
701
+ - Can optionally capture a screenshot of each page.
702
+ - Input: `{ url: string, service?: "default" | "firecrawl", autoEnhance?: boolean, pageOptions?: { onlyMainContent: boolean, screenshot: boolean, waitFor: number, replaceAllPathsWithAbsolutePaths: boolean, headers: object, removeTags: string[], mobile: boolean } }`
703
+ - Output: `{ content: string | string[] | { text: string, html: string, json?: object, screenshotUrl?: string, metadata?: { title: string, description: string, url: string, image: string } } | { text: string, html: string, json?: object, screenshotUrl?: string, metadata?: { title: string, description: string, url: string, image: string } }[], screenshot?: string }`
704
+
705
+ #### scrapeXPost
706
+ Scrape data from a single X (Twitter) post by URL.
707
+ - Returns structured post data (text, html, optional json/screenshot/metadata).
708
+ - Optionally saves the text content to a variable.
709
+ - Input: `{ url: string }`
710
+ - Output: `{ post: { text: string, html: string, json?: object, screenshotUrl?: string, metadata?: { title: string, description: string, url: string, image: string } } }`
711
+
712
+ #### scrapeXProfile
713
+ Scrape public profile data from an X (Twitter) account by URL.
714
+ - Returns structured profile data.
715
+ - Optionally saves the result to a variable.
716
+ - Input: `{ url: string }`
717
+ - Output: `{ profile: { text: string, html: string, json?: object, screenshotUrl?: string, metadata?: { title: string, description: string, url: string, image: string } } }`
718
+
719
+ #### searchGmailEmails
720
+ Search for emails in the connected Gmail account using a Gmail search query. To list recent inbox emails, pass an empty query string.
721
+ - Requires a Google OAuth connection with Gmail readonly scope.
722
+ - Uses Gmail search syntax (e.g. "from:user@example.com", "subject:invoice", "is:unread").
723
+ - To list recent inbox emails, use an empty query string or "in:inbox".
724
+ - Returns up to 100 emails (default 5). The variable receives text or JSON depending on exportType.
725
+ - The direct execution output always returns structured email objects.
726
+ - Input: `{ query: string, connectionId?: string, exportType: "json" | "text", limit: string }`
727
+ - Output: `{ emails: { id: string, subject: string, from: string, to: string, date: string, plainBody: string, htmlBody: string, labels: string }[] }`
728
+
729
+ #### searchGoogle
730
+ Search the web using Google and return structured results.
731
+ - Defaults to us/english, but can optionally specify country and/or language.
732
+ - Defaults to any time, but can optionally specify last hour, last day, week, month, or year.
733
+ - Defaults to top 30 results, but can specify 1 to 100 results to return.
734
+ - Input: `{ query: string, exportType: "text" | "json", countryCode?: string, languageCode?: string, dateRange?: "hour" | "day" | "week" | "month" | "year" | "any", numResults?: number }`
735
+ - Output: `{ results: { title: string, description: string, url: string }[] }`
736
+
737
+ #### searchGoogleImages
738
+ Search Google Images and return image results with URLs and metadata.
739
+ - Defaults to us/english, but can optionally specify country and/or language.
740
+ - Defaults to any time, but can optionally specify last hour, last day, week, month, or year.
741
+ - Defaults to top 30 results, but can specify 1 to 100 results to return.
742
+ - Input: `{ query: string, exportType: "text" | "json", countryCode?: string, languageCode?: string, dateRange?: "hour" | "day" | "week" | "month" | "year" | "any", numResults?: number }`
743
+ - Output: `{ images: { title: string, imageUrl: string, imageWidth: number, imageHeight: number, thumbnailUrl: string, thumbnailWidth: number, thumbnailHeight: number, source: string, domain: string, link: string, googleUrl: string, position: number }[] }`
744
+
745
+ #### searchGoogleNews
746
+ Search Google News for recent news articles matching a query.
747
+ - Defaults to top 30 results, but can specify 1 to 100 results to return.
748
+ - Input: `{ text: string, exportType: "text" | "json", numResults?: number }`
749
+ - Output: `{ articles: { title: string, link: string, date: string, source: { name: string }, snippet?: string }[] }`
750
+
751
+ #### searchGoogleTrends
752
+ Fetch Google Trends data for a search term.
753
+ - date accepts shorthand ("now 1-H", "today 1-m", "today 5-y", etc.) or custom "yyyy-mm-dd yyyy-mm-dd" ranges.
754
+ - data_type controls the shape of returned data: TIMESERIES, GEO_MAP, GEO_MAP_0, RELATED_TOPICS, or RELATED_QUERIES.
755
+ - Input: `{ text: string, hl: string, geo: string, data_type: "TIMESERIES" | "GEO_MAP" | "GEO_MAP_0" | "RELATED_TOPICS" | "RELATED_QUERIES", cat: string, date: string, ts: string }`
756
+ - Output: `{ trends: object }`
757
+
758
+ #### searchPerplexity
759
+ Search the web using the Perplexity API and return structured results.
760
+ - Defaults to US results. Use countryCode (ISO code) to filter by country.
761
+ - Returns 10 results by default, configurable from 1 to 20.
762
+ - The variable receives text or JSON depending on exportType. The direct execution output always returns structured results.
763
+ - Input: `{ query: string, exportType: "text" | "json", countryCode?: string, numResults?: number }`
764
+ - Output: `{ results: { title: string, description: string, url: string }[] }`
765
+
766
+ #### sendEmail
767
+ Send an email to one or more configured recipient addresses.
768
+ - Recipient email addresses are resolved from OAuth connections configured by the app creator. The user running the workflow does not specify the recipient directly.
769
+ - If the body is a URL to a hosted HTML file on the CDN, the HTML is fetched and used as the email body.
770
+ - When generateHtml is enabled, the body text is converted to a styled HTML email using an AI model.
771
+ - connectionId can be a comma-separated list to send to multiple recipients.
772
+ - The special connectionId "trigger_email" uses the email address that triggered the workflow.
773
+ - Input: `{ subject: string, body: string, connectionId?: string, generateHtml?: boolean, generateHtmlInstructions?: string, generateHtmlModelOverride?: { model: string, temperature: number, maxResponseTokens: number, ignorePreamble?: boolean, userMessagePreprocessor?: { dataSource?: string, messageTemplate?: string, maxResults?: number, enabled?: boolean, shouldInherit?: boolean }, preamble?: string, multiModelEnabled?: boolean, editResponseEnabled?: boolean, config?: object }, attachments?: string[] }`
774
+ - Output: `{ recipients: string[] }`
775
+
776
+ #### sendGmailDraft
777
+ Send an existing draft from the connected Gmail account.
778
+ - Requires a Google OAuth connection with Gmail compose scope.
779
+ - The draft is sent and removed from the Drafts folder.
780
+ - Use the draft ID returned by the Create Gmail Draft or List Gmail Drafts steps.
781
+ - Input: `{ draftId: string, connectionId?: string }`
782
+ - Output: `unknown`
783
+
784
+ #### sendGmailMessage
785
+ Send an email from the connected Gmail account.
786
+ - Requires a Google OAuth connection with Gmail compose scope.
787
+ - messageType controls the body format: "plain" for plain text, "html" for raw HTML, "markdown" for auto-converted markdown.
788
+ - Input: `{ to: string, subject: string, message: string, connectionId?: string, messageType: "plain" | "html" | "markdown" }`
789
+ - Output: `{ messageId: string }`
790
+
791
+ #### sendSMS
792
+ Send an SMS or MMS message to a phone number configured via OAuth connection.
793
+ - User is responsible for configuring the connection to the number (MindStudio requires double opt-in to prevent spam)
794
+ - If mediaUrls are provided, the message is sent as MMS instead of SMS
795
+ - MMS supports up to 10 media URLs (images, video, audio, PDF) with a 5MB limit per file
796
+ - MMS is only supported on US and Canadian carriers; international numbers will receive SMS only (media silently dropped)
797
+ - Input: `{ body: string, connectionId?: string, mediaUrls?: string[] }`
798
+ - Output: `unknown`
799
+
800
+ #### setGmailReadStatus
801
+ Mark one or more Gmail emails as read or unread.
802
+ - Requires a Google OAuth connection with Gmail modify scope.
803
+ - Accepts one or more message IDs as a comma-separated string or array.
804
+ - Set markAsRead to true to mark as read, false to mark as unread.
805
+ - Input: `{ messageIds: string, markAsRead: boolean, connectionId?: string }`
806
+ - Output: `unknown`
807
+
808
+ #### setRunTitle
809
+ Set the title of the agent run for the user's history
810
+ - Input: `{ title: string }`
811
+ - Output: `unknown`
812
+
813
+ #### setVariable
814
+ Explicitly set a variable to a given value.
815
+ - Useful for bootstrapping global variables or setting constants.
816
+ - The variable name and value both support variable interpolation.
817
+ - The type field is a UI hint only (controls input widget in the editor).
818
+ - Input: `{ value: string | string[] }`
819
+ - Output: `object`
820
+
821
+ #### telegramEditMessage
822
+ Edit a previously sent Telegram message. Use with the message ID returned by Send Telegram Message.
823
+ - Only text messages sent by the bot can be edited.
824
+ - The messageId is returned by the Send Telegram Message step.
825
+ - Common pattern: send a "Processing..." message, do work, then edit it with the result.
826
+ - Input: `{ botToken: string, chatId: string, messageId: string, text: string }`
827
+ - Output: `unknown`
828
+
829
+ #### telegramReplyToMessage
830
+ Send a reply to a specific Telegram message. The reply will be visually threaded in the chat.
831
+ - Use the rawMessage.message_id from the incoming trigger variables to reply to the user's message.
832
+ - Especially useful in group chats where replies provide context.
833
+ - Returns the sent message ID, which can be used with Edit Telegram Message.
834
+ - Input: `{ botToken: string, chatId: string, replyToMessageId: string, text: string }`
835
+ - Output: `{ messageId: number }`
836
+
837
+ #### telegramSendAudio
838
+ Send an audio file to a Telegram chat as music or a voice note via a bot.
839
+ - "audio" mode sends as a standard audio file. "voice" mode sends as a voice message (re-uploads the file for large file support).
840
+ - Input: `{ botToken: string, chatId: string, audioUrl: string, mode: "audio" | "voice", caption?: string }`
841
+ - Output: `unknown`
842
+
843
+ #### telegramSendFile
844
+ Send a document/file to a Telegram chat via a bot.
845
+ - Input: `{ botToken: string, chatId: string, fileUrl: string, caption?: string }`
846
+ - Output: `unknown`
847
+
848
+ #### telegramSendImage
849
+ Send an image to a Telegram chat via a bot.
850
+ - Input: `{ botToken: string, chatId: string, imageUrl: string, caption?: string }`
851
+ - Output: `unknown`
852
+
853
+ #### telegramSendMessage
854
+ Send a text message to a Telegram chat via a bot.
855
+ - Messages are sent using MarkdownV2 formatting. Special characters are auto-escaped.
856
+ - botToken format is "botId:token" — both parts are required.
857
+ - Returns the sent message ID, which can be used with Edit Telegram Message to update the message later.
858
+ - Input: `{ botToken: string, chatId: string, text: string }`
859
+ - Output: `{ messageId: number }`
860
+
861
+ #### telegramSendVideo
862
+ Send a video to a Telegram chat via a bot.
863
+ - Input: `{ botToken: string, chatId: string, videoUrl: string, caption?: string }`
864
+ - Output: `unknown`
865
+
866
+ #### telegramSetTyping
867
+ Show the "typing..." indicator in a Telegram chat via a bot.
868
+ - The typing indicator automatically expires after a few seconds. Use this right before sending a message for a natural feel.
869
+ - Input: `{ botToken: string, chatId: string }`
870
+ - Output: `unknown`
871
+
872
+ #### textToSpeech
873
+ Generate an audio file from provided text using a speech model.
874
+ - The text field contains the exact words to be spoken (not instructions).
875
+ - In foreground mode, the audio is displayed to the user. In background mode, the URL is saved to a variable.
876
+ - Input: `{ text: string, intermediateAsset?: boolean, speechModelOverride?: { model: string, config?: object } }`
877
+ - Output: `{ audioUrl: string }`
878
+
879
+ #### transcribeAudio
880
+ Convert an audio file to text using a transcription model.
881
+ - The prompt field provides optional context to improve transcription accuracy (e.g. language, speaker names, domain).
882
+ - Input: `{ audioUrl: string, prompt: string, transcriptionModelOverride?: { model: string, config?: object } }`
883
+ - Output: `{ text: string }`
884
+
885
+ #### trimMedia
886
+ Trim an audio or video clip
887
+ - Input: `{ inputUrl: string, start?: number | string, duration?: string | number, intermediateAsset?: boolean }`
888
+ - Output: `{ mediaUrl: string }`
889
+
890
+ #### updateGmailLabels
891
+ Add or remove labels on Gmail messages, identified by message IDs or a search query.
892
+ - Requires a Google OAuth connection with Gmail modify scope.
893
+ - Provide either a query (Gmail search syntax) or explicit messageIds to target messages.
894
+ - Label IDs can be label names or Gmail label IDs — names are resolved automatically.
895
+ - Input: `{ query: string, connectionId?: string, messageIds: string, addLabelIds: string, removeLabelIds: string }`
896
+ - Output: `{ updatedMessageIds: string[] }`
897
+
898
+ #### uploadDataSourceDocument
899
+ Upload a file into an existing data source from a URL or raw text content.
900
+ - If "file" is a single URL, the file is downloaded from that URL and uploaded.
901
+ - If "file" is any other string, a .txt document is created from that content and uploaded.
902
+ - The block waits (polls) for processing to complete before transitioning, up to 5 minutes.
903
+ - Once processing finishes, vectors are loaded into Milvus so the data source is immediately queryable.
904
+ - Supported file types (when using a URL) are the same as the data source upload UI (PDF, DOCX, TXT, etc.).
905
+ - Input: `{ dataSourceId: string, file: string, fileName: string }`
906
+ - Output: `unknown`
907
+
908
+ #### upscaleImage
909
+ Increase the resolution of an image using AI upscaling.
910
+ - Output is re-hosted on the CDN as a PNG.
911
+ - Input: `{ imageUrl: string, targetResolution: "2k" | "4k" | "8k", engine: "standard" | "pro" }`
912
+ - Output: `{ imageUrl: string }`
913
+
914
+ #### upscaleVideo
915
+ Upscale a video file
916
+ - Input: `{ videoUrl: string, targetResolution: "720p" | "1080p" | "2K" | "4K", engine: "standard" | "pro" | "ultimate" | "flashvsr" | "seedance" | "seedvr2" | "runwayml/upscale-v1", intermediateAsset?: boolean }`
917
+ - Output: `{ videoUrl: string }`
918
+
919
+ #### videoFaceSwap
920
+ Swap faces in a video file
921
+ - Input: `{ videoUrl: string, faceImageUrl: string, targetIndex: number, engine: string, intermediateAsset?: boolean }`
922
+ - Output: `{ videoUrl: string }`
923
+
924
+ #### videoRemoveBackground
925
+ Remove or replace background from a video
926
+ - Input: `{ videoUrl: string, newBackground: "transparent" | "image", newBackgroundImageUrl?: string, engine: string, intermediateAsset?: boolean }`
927
+ - Output: `{ videoUrl: string }`
928
+
929
+ #### videoRemoveWatermark
930
+ Remove a watermark from a video
931
+ - Input: `{ videoUrl: string, engine: string, intermediateAsset?: boolean }`
932
+ - Output: `{ videoUrl: string }`
933
+
934
+ #### watermarkImage
935
+ Overlay a watermark image onto another image.
936
+ - The watermark is placed at the specified corner with configurable padding and width.
937
+ - Input: `{ imageUrl: string, watermarkImageUrl: string, corner: "top-left" | "top-right" | "bottom-left" | "bottom-right", paddingPx: number, widthPx: number, intermediateAsset?: boolean }`
938
+ - Output: `{ imageUrl: string }`
939
+
940
+ #### watermarkVideo
941
+ Add an image watermark to a video
942
+ - Input: `{ videoUrl: string, imageUrl: string, corner: "top-left" | "top-right" | "bottom-left" | "bottom-right", paddingPx: number, widthPx: number, intermediateAsset?: boolean }`
943
+ - Output: `{ videoUrl: string }`
944
+
945
+ ### ActiveCampaign
946
+
947
+ #### activeCampaignAddNote
948
+ Add a note to an existing contact in ActiveCampaign.
949
+ - Requires an ActiveCampaign OAuth connection (connectionId).
950
+ - The contact must already exist — use the contact ID from a previous create or search step.
951
+ - Input: `{ contactId: string, note: string, connectionId?: string }`
952
+ - Output: `unknown`
953
+
954
+ #### activeCampaignCreateContact
955
+ Create or sync a contact in ActiveCampaign.
956
+ - Requires an ActiveCampaign OAuth connection (connectionId).
957
+ - If a contact with the email already exists, it may be updated depending on ActiveCampaign settings.
958
+ - Custom fields are passed as a key-value map where keys are field IDs.
959
+ - Input: `{ email: string, firstName: string, lastName: string, phone: string, accountId: string, customFields: object, connectionId?: string }`
960
+ - Output: `{ contactId: string }`
961
+
962
+ ### Airtable
963
+
964
+ #### airtableCreateUpdateRecord
965
+ Create a new record or update an existing record in an Airtable table.
966
+ - If recordId is provided, updates that record. Otherwise, creates a new one.
967
+ - When updating with updateMode "onlySpecified", unspecified fields are left as-is. With "all", unspecified fields are cleared.
968
+ - Array fields (e.g. multipleAttachments) accept arrays of values.
969
+ - Input: `{ connectionId?: string, baseId: string, tableId: string, recordId?: string, updateMode?: "onlySpecified" | "all", fields: unknown, recordData: object }`
970
+ - Output: `{ recordId: string }`
971
+
972
+ #### airtableDeleteRecord
973
+ Delete a record from an Airtable table by its record ID.
974
+ - Requires an active Airtable OAuth connection (connectionId).
975
+ - Silently succeeds if the record does not exist.
976
+ - Input: `{ connectionId?: string, baseId: string, tableId: string, recordId: string }`
977
+ - Output: `{ deleted: boolean }`
978
+
979
+ #### airtableGetRecord
980
+ Fetch a single record from an Airtable table by its record ID.
981
+ - Requires an active Airtable OAuth connection (connectionId).
982
+ - If the record is not found, returns a string message instead of a record object.
983
+ - Input: `{ connectionId?: string, baseId: string, tableId: string, recordId: string }`
984
+ - Output: `{ record: { id: string, createdTime: string, fields: object } | null }`
985
+
986
+ #### airtableGetTableRecords
987
+ Fetch multiple records from an Airtable table with optional pagination.
988
+ - Requires an active Airtable OAuth connection (connectionId).
989
+ - Default limit is 100 records. Maximum is 1000.
990
+ - When outputFormat is 'csv', the variable receives CSV text. The direct execution output always returns parsed records.
991
+ - Input: `{ connectionId?: string, baseId: string, tableId: string, outputFormat?: "json" | "csv", limit?: number }`
992
+ - Output: `{ records: { id: string, createdTime: string, fields: object }[] }`
993
+
994
+ ### Apollo
995
+
996
+ #### enrichPerson
997
+ Look up professional information about a person using Apollo.io. Search by ID, name, LinkedIn URL, email, or domain.
998
+ - At least one search parameter must be provided.
999
+ - Returns enriched data from Apollo including contact details, employment info, and social profiles.
1000
+ - Input: `{ params: { id: string, name: string, linkedinUrl: string, email: string, domain: string } }`
1001
+ - Output: `{ data: unknown }`
1002
+
1003
+ #### peopleSearch
1004
+ Search for people matching specific criteria using Apollo.io. Supports natural language queries and advanced filters.
1005
+ - Can use a natural language "smartQuery" which is converted to Apollo search parameters by an AI model.
1006
+ - Advanced params can override or supplement the smart query results.
1007
+ - Optionally enriches returned people and/or their organizations for additional detail.
1008
+ - Results are paginated. Use limit and page to control the result window.
1009
+ - Input: `{ smartQuery: string, enrichPeople: boolean, enrichOrganizations: boolean, limit: string, page: string, params: { personTitles: string, includeSimilarTitles: string, qKeywords: string, personLocations: string, personSeniorities: string, organizationLocations: string, qOrganizationDomainsList: string, contactEmailStatus: string, organizationNumEmployeesRanges: string, revenueRangeMin: string, revenueRangeMax: string, currentlyUsingAllOfTechnologyUids: string, currentlyUsingAnyOfTechnologyUids: string, currentlyNotUsingAnyOfTechnologyUids: string } }`
1010
+ - Output: `{ results: unknown }`
1011
+
1012
+ ### Coda
1013
+
1014
+ #### codaCreateUpdatePage
1015
+ Create a new page or update an existing page in a Coda document.
1016
+ - Requires a Coda OAuth connection (connectionId).
1017
+ - If pageData.pageId is provided, updates that page. Otherwise, creates a new one.
1018
+ - Page content is provided as markdown and converted to Coda's canvas format.
1019
+ - When updating, insertionMode controls how content is applied (default: 'append').
1020
+ - Input: `{ connectionId?: string, pageData: { docId: string, pageId?: string, name: string, subtitle: string, iconName: string, imageUrl: string, parentPageId?: string, pageContent: string | unknown, contentUpdate?: unknown, insertionMode?: string } }`
1021
+ - Output: `{ pageId: string }`
1022
+
1023
+ #### codaCreateUpdateRow
1024
+ Create a new row or update an existing row in a Coda table.
1025
+ - Requires a Coda OAuth connection (connectionId).
1026
+ - If rowId is provided, updates that row. Otherwise, creates a new one.
1027
+ - Row data keys are column IDs. Empty values are excluded.
1028
+ - Input: `{ connectionId?: string, docId: string, tableId: string, rowId?: string, rowData: object }`
1029
+ - Output: `{ rowId: string }`
1030
+
1031
+ #### codaFindRow
1032
+ Search for a row in a Coda table by matching column values.
1033
+ - Requires a Coda OAuth connection (connectionId).
1034
+ - Returns the first row matching all specified column values, or null if no match.
1035
+ - Search criteria in rowData are ANDed together.
1036
+ - Input: `{ connectionId?: string, docId: string, tableId: string, rowData: object }`
1037
+ - Output: `{ row: { id: string, values: object } | null }`
1038
+
1039
+ #### codaGetPage
1040
+ Export and read the contents of a page from a Coda document.
1041
+ - Requires a Coda OAuth connection (connectionId).
1042
+ - Page export is asynchronous on Coda's side — there may be a brief delay while it processes.
1043
+ - If a page was just created in a prior step, there is an automatic 20-second retry if the first export attempt fails.
1044
+ - Input: `{ connectionId?: string, docId: string, pageId: string, outputFormat?: "html" | "markdown" }`
1045
+ - Output: `{ content: string }`
1046
+
1047
+ #### codaGetTableRows
1048
+ Fetch rows from a Coda table with optional pagination.
1049
+ - Requires a Coda OAuth connection (connectionId).
1050
+ - Default limit is 10000 rows. Rows are fetched in pages of 500.
1051
+ - When outputFormat is 'csv', the variable receives CSV text. The direct execution output always returns parsed rows.
1052
+ - Input: `{ connectionId?: string, docId: string, tableId: string, limit?: number | string, outputFormat?: "json" | "csv" }`
1053
+ - Output: `{ rows: { id: string, values: object }[] }`
1054
+
1055
+ ### Facebook
1056
+
1057
+ #### scrapeFacebookPage
1058
+ Scrape a Facebook page
1059
+ - Input: `{ pageUrl: string }`
1060
+ - Output: `{ data: unknown }`
1061
+
1062
+ #### scrapeFacebookPosts
1063
+ Get all the posts for a Facebook page
1064
+ - Input: `{ pageUrl: string }`
1065
+ - Output: `{ data: unknown }`
1066
+
1067
+ ### Gmail
1068
+
1069
+ #### deleteGmailEmail
1070
+ Move an email to trash in the connected Gmail account (recoverable delete).
1071
+ - Requires a Google OAuth connection with Gmail modify scope.
1072
+ - Uses trash (recoverable) rather than permanent delete.
1073
+ - Input: `{ messageId: string, connectionId?: string }`
1074
+ - Output: `unknown`
1075
+
1076
+ #### getGmailDraft
1077
+ Retrieve a specific draft from Gmail by draft ID.
1078
+ - Requires a Google OAuth connection with Gmail readonly scope.
1079
+ - Returns the draft content including subject, recipients, sender, and body.
1080
+ - Input: `{ draftId: string, connectionId?: string }`
1081
+ - Output: `{ draftId: string, messageId: string, subject: string, to: string, from: string, body: string }`
1082
+
1083
+ #### getGmailEmail
1084
+ Retrieve a specific email from Gmail by message ID.
1085
+ - Requires a Google OAuth connection with Gmail readonly scope.
1086
+ - Returns the email subject, sender, recipient, date, body (plain text preferred, falls back to HTML), and labels.
1087
+ - Input: `{ messageId: string, connectionId?: string }`
1088
+ - Output: `{ messageId: string, subject: string, from: string, to: string, date: string, body: string, labels: string }`
1089
+
1090
+ #### listGmailDrafts
1091
+ List drafts in the connected Gmail account.
1092
+ - Requires a Google OAuth connection with Gmail readonly scope.
1093
+ - Returns up to 50 drafts (default 10).
1094
+ - The variable receives text or JSON depending on exportType.
1095
+ - Input: `{ connectionId?: string, limit?: string, exportType: "json" | "text" }`
1096
+ - Output: `{ drafts: { draftId: string, messageId: string, subject: string, to: string, snippet: string }[] }`
1097
+
1098
+ #### replyToGmailEmail
1099
+ Reply to an existing email in Gmail. The reply is threaded under the original message.
1100
+ - Requires a Google OAuth connection with Gmail compose and readonly scopes.
1101
+ - The reply is sent to the original sender and threaded under the original message.
1102
+ - messageType controls the body format: "plain", "html", or "markdown".
1103
+ - Input: `{ messageId: string, message: string, messageType: "plain" | "html" | "markdown", connectionId?: string }`
1104
+ - Output: `{ messageId: string }`
1105
+
1106
+ ### Google
1107
+
1108
+ #### createGoogleDoc
1109
+ Create a new Google Document and optionally populate it with content.
1110
+ - textType determines how the text field is interpreted: "plain" for plain text, "html" for HTML markup, "markdown" for Markdown.
1111
+ - Input: `{ title: string, text: string, connectionId?: string, textType: "plain" | "html" | "markdown" }`
1112
+ - Output: `{ documentUrl: string }`
1113
+
1114
+ #### createGoogleSheet
1115
+ Create a new Google Spreadsheet and populate it with CSV data.
1116
+ - Input: `{ title: string, text: string, connectionId?: string }`
1117
+ - Output: `{ spreadsheetUrl: string }`
1118
+
1119
+ #### deleteGoogleSheetRows
1120
+ Delete a range of rows from a Google Spreadsheet.
1121
+ - Requires a Google OAuth connection with Drive scope.
1122
+ - startRow and endRow are 1-based row numbers (inclusive).
1123
+ - If sheetName is omitted, operates on the first sheet.
1124
+ - Input: `{ documentId: string, sheetName?: string, startRow: string, endRow: string, connectionId?: string }`
1125
+ - Output: `unknown`
1126
+
1127
+ #### fetchGoogleDoc
1128
+ Fetch the contents of an existing Google Document.
1129
+ - exportType controls the output format: "html" for HTML markup, "markdown" for Markdown, "json" for structured JSON, "plain" for plain text.
1130
+ - Input: `{ documentId: string, connectionId?: string, exportType: "html" | "markdown" | "json" | "plain" }`
1131
+ - Output: `{ content: string }`
1132
+
1133
+ #### fetchGoogleSheet
1134
+ Fetch contents of a Google Spreadsheet range.
1135
+ - range uses A1 notation (e.g. "Sheet1!A1:C10"). Omit to fetch the entire first sheet.
1136
+ - exportType controls the output format: "csv" for comma-separated values, "json" for structured JSON.
1137
+ - Input: `{ spreadsheetId: string, range: string, connectionId?: string, exportType: "csv" | "json" }`
1138
+ - Output: `{ content: string }`
1139
+
1140
+ #### getGoogleSheetInfo
1141
+ Get metadata about a Google Spreadsheet including sheet names, row counts, and column counts.
1142
+ - Requires a Google OAuth connection with Drive scope.
1143
+ - Returns the spreadsheet title and a list of all sheets with their dimensions.
1144
+ - Input: `{ documentId: string, connectionId?: string }`
1145
+ - Output: `{ title: string, sheets: { sheetId: number, title: string, rowCount: number, columnCount: number }[] }`
1146
+
1147
+ #### updateGoogleDoc
1148
+ Update the contents of an existing Google Document.
1149
+ - operationType controls how content is applied: "addToTop" prepends, "addToBottom" appends, "overwrite" replaces all content.
1150
+ - textType determines how the text field is interpreted: "plain" for plain text, "html" for HTML markup, "markdown" for Markdown.
1151
+ - Input: `{ documentId: string, connectionId?: string, text: string, textType: "plain" | "html" | "markdown", operationType: "addToTop" | "addToBottom" | "overwrite" }`
1152
+ - Output: `{ documentUrl: string }`
1153
+
1154
+ #### updateGoogleSheet
1155
+ Update a Google Spreadsheet with new data.
1156
+ - operationType controls how data is written: "addToBottom" appends rows, "overwrite" replaces all data, "range" writes to a specific cell range.
1157
+ - Data should be provided as CSV in the text field.
1158
+ - Input: `{ text: string, connectionId?: string, spreadsheetId: string, range: string, operationType: "addToBottom" | "overwrite" | "range" }`
1159
+ - Output: `{ spreadsheetUrl: string }`
1160
+
1161
+ ### Google Calendar
1162
+
1163
+ #### createGoogleCalendarEvent
1164
+ Create a new event on a Google Calendar.
1165
+ - Requires a Google OAuth connection with Calendar events scope.
1166
+ - Date/time values must be ISO 8601 format (e.g. "2025-07-02T10:00:00-07:00").
1167
+ - Attendees are specified as one email address per line in a single string.
1168
+ - Set addMeetLink to true to automatically attach a Google Meet video call.
1169
+ - Input: `{ connectionId?: string, summary: string, description?: string, location?: string, startDateTime: string, endDateTime: string, attendees?: string, addMeetLink?: boolean, calendarId?: string }`
1170
+ - Output: `{ eventId: string, htmlLink: string }`
1171
+
1172
+ #### deleteGoogleCalendarEvent
1173
+ Retrieve a specific event from a Google Calendar by event ID.
1174
+ - Requires a Google OAuth connection with Calendar events scope.
1175
+ - The variable receives JSON or XML-like text depending on exportType. The direct execution output always returns the structured event.
1176
+ - Input: `{ connectionId?: string, eventId: string, calendarId?: string }`
1177
+ - Output: `unknown`
1178
+
1179
+ #### getGoogleCalendarEvent
1180
+ Retrieve a specific event from a Google Calendar by event ID.
1181
+ - Requires a Google OAuth connection with Calendar events scope.
1182
+ - The variable receives JSON or XML-like text depending on exportType. The direct execution output always returns the structured event.
1183
+ - Input: `{ connectionId?: string, eventId: string, exportType: "json" | "text", calendarId?: string }`
1184
+ - Output: `{ event: { id?: string | null, status?: string | null, htmlLink?: string | null, created?: string | null, updated?: string | null, summary?: string | null, description?: string | null, location?: string | null, organizer?: { displayName?: string | null, email?: string | null } | null, start?: { dateTime?: string | null, timeZone?: string | null } | null, end?: { dateTime?: string | null, timeZone?: string | null } | null, attendees?: ({ displayName?: string | null, email?: string | null, responseStatus?: string | null })[] | null } }`
1185
+
1186
+ #### listGoogleCalendarEvents
1187
+ List upcoming events from a Google Calendar, ordered by start time.
1188
+ - Requires a Google OAuth connection with Calendar events scope.
1189
+ - Only returns future events (timeMin = now).
1190
+ - The variable receives JSON or XML-like text depending on exportType. The direct execution output always returns structured events.
1191
+ - Input: `{ connectionId?: string, limit: number, exportType: "json" | "text", calendarId?: string }`
1192
+ - Output: `{ events: ({ id?: string | null, status?: string | null, htmlLink?: string | null, created?: string | null, updated?: string | null, summary?: string | null, description?: string | null, location?: string | null, organizer?: { displayName?: string | null, email?: string | null } | null, start?: { dateTime?: string | null, timeZone?: string | null } | null, end?: { dateTime?: string | null, timeZone?: string | null } | null, attendees?: ({ displayName?: string | null, email?: string | null, responseStatus?: string | null })[] | null })[] }`
1193
+
1194
+ #### searchGoogleCalendarEvents
1195
+ Search for events in a Google Calendar by keyword, date range, or both.
1196
+ - Requires a Google OAuth connection with Calendar events scope.
1197
+ - Supports keyword search via "query" and date filtering via "timeMin"/"timeMax" (ISO 8601 format).
1198
+ - Unlike "List Events" which only shows future events, this allows searching past events too.
1199
+ - Input: `{ query?: string, timeMin?: string, timeMax?: string, calendarId?: string, limit?: number, exportType: "json" | "text", connectionId?: string }`
1200
+ - Output: `{ events: ({ id?: string | null, status?: string | null, htmlLink?: string | null, created?: string | null, updated?: string | null, summary?: string | null, description?: string | null, location?: string | null, organizer?: { displayName?: string | null, email?: string | null } | null, start?: { dateTime?: string | null, timeZone?: string | null } | null, end?: { dateTime?: string | null, timeZone?: string | null } | null, attendees?: ({ displayName?: string | null, email?: string | null, responseStatus?: string | null })[] | null })[] }`
1201
+
1202
+ #### updateGoogleCalendarEvent
1203
+ Update an existing event on a Google Calendar. Only specified fields are changed.
1204
+ - Requires a Google OAuth connection with Calendar events scope.
1205
+ - Fetches the existing event first, then applies only the provided updates. Omitted fields are left unchanged.
1206
+ - Attendees are specified as one email address per line, and replace the entire attendee list.
1207
+ - Input: `{ connectionId?: string, eventId: string, summary?: string, description?: string, location?: string, startDateTime?: string, endDateTime?: string, attendees?: string, calendarId?: string }`
1208
+ - Output: `{ eventId: string, htmlLink: string }`
1209
+
1210
+ ### Google Drive
1211
+
1212
+ #### getGoogleDriveFile
1213
+ Download a file from Google Drive and rehost it on the CDN. Returns a public CDN URL.
1214
+ - Requires a Google OAuth connection with Drive scope.
1215
+ - Google-native files (Docs, Sheets, Slides) cannot be downloaded — use dedicated steps instead.
1216
+ - Maximum file size: 200MB.
1217
+ - The file is downloaded and re-uploaded to the CDN; the returned URL is publicly accessible.
1218
+ - Input: `{ fileId: string, connectionId?: string }`
1219
+ - Output: `{ url: string, name: string, mimeType: string, size: number }`
1220
+
1221
+ #### listGoogleDriveFiles
1222
+ List files in a Google Drive folder.
1223
+ - Requires a Google OAuth connection with Drive scope.
1224
+ - If folderId is omitted, lists files in the root folder.
1225
+ - Returns file metadata including name, type, size, and links.
1226
+ - Input: `{ folderId?: string, limit?: number, connectionId?: string, exportType: "json" | "text" }`
1227
+ - Output: `{ files: { id: string, name: string, mimeType: string, size: string, webViewLink: string, createdTime: string, modifiedTime: string }[] }`
1228
+
1229
+ #### searchGoogleDrive
1230
+ Search for files in Google Drive by keyword.
1231
+ - Requires a Google OAuth connection with Drive scope.
1232
+ - Searches file content and names using Google Drive's fullText search.
1233
+ - Input: `{ query: string, limit?: number, connectionId?: string, exportType: "json" | "text" }`
1234
+ - Output: `{ files: { id: string, name: string, mimeType: string, size: string, webViewLink: string, createdTime: string, modifiedTime: string }[] }`
1235
+
1236
+ ### HubSpot
1237
+
1238
+ #### hubspotCreateCompany
1239
+ Create a new company or update an existing one in HubSpot. Matches by domain.
1240
+ - Requires a HubSpot OAuth connection (connectionId).
1241
+ - If a company with the given domain already exists, it is updated. Otherwise, a new one is created.
1242
+ - Property values are type-checked against enabledProperties before being sent to HubSpot.
1243
+ - Input: `{ connectionId?: string, company: { domain: string, name: string }, enabledProperties: ({ label: string, value: string, type: "string" | "number" | "bool" })[] }`
1244
+ - Output: `{ companyId: string }`
1245
+
1246
+ #### hubspotCreateContact
1247
+ Create a new contact or update an existing one in HubSpot. Matches by email address.
1248
+ - Requires a HubSpot OAuth connection (connectionId).
1249
+ - If a contact with the given email already exists, it is updated. Otherwise, a new one is created.
1250
+ - If companyDomain is provided, the contact is associated with that company (creating the company if needed).
1251
+ - Property values are type-checked against enabledProperties before being sent to HubSpot.
1252
+ - Input: `{ connectionId?: string, contact: { email: string, firstname: string, lastname: string }, enabledProperties: ({ label: string, value: string, type: "string" | "number" | "bool" })[], companyDomain: string }`
1253
+ - Output: `{ contactId: string }`
1254
+
1255
+ #### hubspotGetCompany
1256
+ Look up a HubSpot company by domain name or company ID.
1257
+ - Requires a HubSpot OAuth connection (connectionId).
1258
+ - Returns null if the company is not found.
1259
+ - When searching by domain, performs a search query then fetches the full company record.
1260
+ - Use additionalProperties to request specific HubSpot properties beyond the defaults.
1261
+ - Input: `{ connectionId?: string, searchBy: "domain" | "id", companyDomain: string, companyId: string, additionalProperties: string[] }`
1262
+ - Output: `{ company: { id: string, properties: object, createdAt: string, updatedAt: string, archived: boolean } | null }`
1263
+
1264
+ #### hubspotGetContact
1265
+ Look up a HubSpot contact by email address or contact ID.
1266
+ - Requires a HubSpot OAuth connection (connectionId).
1267
+ - Returns null if the contact is not found.
1268
+ - Use additionalProperties to request specific HubSpot properties beyond the defaults.
1269
+ - Input: `{ connectionId?: string, searchBy: "email" | "id", contactEmail: string, contactId: string, additionalProperties: string[] }`
1270
+ - Output: `{ contact: { id: string, properties: object, createdAt: string, updatedAt: string, archived: boolean } | null }`
1271
+
1272
+ ### Hunter.io
1273
+
1274
+ #### hunterApiCompanyEnrichment
1275
+ Look up company information by domain using Hunter.io.
1276
+ - Returns company name, description, location, industry, size, technologies, and more.
1277
+ - If the domain input is a full URL, the hostname is automatically extracted.
1278
+ - Returns null if the company is not found.
1279
+ - Input: `{ domain: string }`
1280
+ - Output: `{ data: { name: string, domain: string, description: string | null, country: string | null, state: string | null, city: string | null, industry: string | null, employees_range: string | null, logo_url: string | null, technologies: string[] } | null }`
1281
+
1282
+ #### hunterApiDomainSearch
1283
+ Search for email addresses associated with a domain using Hunter.io.
1284
+ - If the domain input is a full URL, the hostname is automatically extracted.
1285
+ - Returns a list of email addresses found for the domain along with organization info.
1286
+ - Input: `{ domain: string }`
1287
+ - Output: `{ data: { domain: string, disposable: boolean, webmail: boolean, accept_all: boolean, pattern: string, organization: string, country: string | null, state: string | null, emails: ({ value: string, type: string, confidence: number, first_name: string | null, last_name: string | null, position: string | null, seniority: string | null, department: string | null, linkedin: string | null, twitter: string | null, phone_number: string | null })[], linked_domains: string[] } }`
1288
+
1289
+ #### hunterApiEmailFinder
1290
+ Find an email address for a specific person at a domain using Hunter.io.
1291
+ - Requires a first name, last name, and domain.
1292
+ - If the domain input is a full URL, the hostname is automatically extracted.
1293
+ - Returns the most likely email address with a confidence score.
1294
+ - Input: `{ domain: string, firstName: string, lastName: string }`
1295
+ - Output: `{ data: { first_name: string, last_name: string, email: string, score: number, domain: string, accept_all: boolean, position: string | null, twitter: string | null, linkedin_url: string | null, phone_number: string | null, company: string | null, sources: { domain: string, uri: string, extracted_on: string }[] } }`
1296
+
1297
+ #### hunterApiEmailVerification
1298
+ Verify whether an email address is valid and deliverable using Hunter.io.
1299
+ - Checks email format, MX records, SMTP server, and mailbox deliverability.
1300
+ - Returns a status ("valid", "invalid", "accept_all", "webmail", "disposable", "unknown") and a score.
1301
+ - Input: `{ email: string }`
1302
+ - Output: `{ data: { status: string, result: string, score: number, email: string, regexp: boolean, gibberish: boolean, disposable: boolean, webmail: boolean, mx_records: boolean, smtp_server: boolean, smtp_check: boolean, accept_all: boolean, block: boolean, sources: { domain: string, uri: string, extracted_on: string }[] } }`
1303
+
1304
+ #### hunterApiPersonEnrichment
1305
+ Look up professional information about a person by their email address using Hunter.io.
1306
+ - Returns name, job title, social profiles, and company information.
1307
+ - If the person is not found, returns an object with an error message instead of throwing.
1308
+ - Input: `{ email: string }`
1309
+ - Output: `{ data: { first_name: string, last_name: string, email: string, position: string | null, seniority: string | null, department: string | null, linkedin_url: string | null, twitter: string | null, phone_number: string | null, company: { name: string, domain: string, industry: string | null } | null } | { error: string } }`
1310
+
1311
+ ### Instagram
1312
+
1313
+ #### scrapeInstagramComments
1314
+ Get all the comments for an Instagram post
1315
+ - Input: `{ postUrl: string, resultsLimit: string }`
1316
+ - Output: `{ data: unknown }`
1317
+
1318
+ #### scrapeInstagramMentions
1319
+ Scrape an Instagram profile's mentions
1320
+ - Input: `{ profileUrl: string, resultsLimit: string }`
1321
+ - Output: `{ data: unknown }`
1322
+
1323
+ #### scrapeInstagramPosts
1324
+ Get all the posts for an Instagram profile
1325
+ - Input: `{ profileUrl: string, resultsLimit: string, onlyPostsNewerThan: string }`
1326
+ - Output: `{ data: unknown }`
1327
+
1328
+ #### scrapeInstagramProfile
1329
+ Scrape an Instagram profile
1330
+ - Input: `{ profileUrl: string }`
1331
+ - Output: `{ data: unknown }`
1332
+
1333
+ #### scrapeInstagramReels
1334
+ Get all the reels for an Instagram profile
1335
+ - Input: `{ profileUrl: string, resultsLimit: string }`
1336
+ - Output: `{ data: unknown }`
1337
+
1338
+ ### LinkedIn
1339
+
1340
+ #### postToLinkedIn
1341
+ Create a post on LinkedIn from the connected account.
1342
+ - Requires a LinkedIn OAuth connection (connectionId).
1343
+ - Supports text posts, image posts, video posts, document posts, and article posts.
1344
+ - Attach one media type per post: image, video, document, or article.
1345
+ - Documents support PDF, PPT, PPTX, DOC, DOCX (max 100MB, 300 pages). Displays as a slideshow carousel.
1346
+ - Articles create a link preview with optional custom title, description, and thumbnail.
1347
+ - Visibility controls who can see the post.
1348
+ - Input: `{ message: string, visibility: "PUBLIC" | "CONNECTIONS", imageUrl?: string, videoUrl?: string, documentUrl?: string, articleUrl?: string, titleText?: string, descriptionText?: string, connectionId?: string }`
1349
+ - Output: `unknown`
1350
+
1351
+ ### Meta Threads
1352
+
1353
+ #### scrapeMetaThreadsProfile
1354
+ Scrape a Meta Threads profile
1355
+ - Input: `{ profileUrl: string }`
1356
+ - Output: `{ data: unknown }`
1357
+
1358
+ ### Notion
1359
+
1360
+ #### notionCreatePage
1361
+ Create a new page in Notion as a child of an existing page.
1362
+ - Requires a Notion OAuth connection (connectionId).
1363
+ - Content is provided as markdown and converted to Notion blocks (headings, paragraphs, lists, code, quotes).
1364
+ - The page is created as a child of the specified parent page (pageId).
1365
+ - Input: `{ pageId: string, content: string, title: string, connectionId?: string }`
1366
+ - Output: `{ pageId: string, pageUrl: string }`
1367
+
1368
+ #### notionUpdatePage
1369
+ Update the content of an existing Notion page.
1370
+ - Requires a Notion OAuth connection (connectionId).
1371
+ - Content is provided as markdown and converted to Notion blocks.
1372
+ - "append" mode adds content to the end of the page. "overwrite" mode deletes all existing blocks first.
1373
+ - Input: `{ pageId: string, content: string, mode: "append" | "overwrite", connectionId?: string }`
1374
+ - Output: `{ pageId: string, pageUrl: string }`
1375
+
1376
+ ### X
1377
+
1378
+ #### postToX
1379
+ Create a post on X (Twitter) from the connected account.
1380
+ - Requires an X OAuth connection (connectionId).
1381
+ - Maximum 280 characters of text.
1382
+ - Optionally attach up to 4 media items (images, GIFs, or videos) via mediaUrls.
1383
+ - Media URLs must be publicly accessible. The service fetches and uploads them to X.
1384
+ - Supported formats: JPEG, PNG, GIF, WEBP, MP4. Images up to 5MB, videos up to 512MB.
1385
+ - Input: `{ text: string, connectionId?: string, mediaUrls?: string[] }`
1386
+ - Output: `unknown`
1387
+
1388
+ #### searchXPosts
1389
+ Search recent X (Twitter) posts matching a query.
1390
+ - Searches only the past 7 days of posts.
1391
+ - Query supports X API v2 search operators (up to 512 characters).
1392
+ Available search operators in query:
1393
+ | Operator | Description |
1394
+ | -----------------| -------------------------------------------------|
1395
+ | from: | Posts from a specific user (e.g., from:elonmusk) |
1396
+ | to: | Posts sent to a specific user (e.g., to:NASA) |
1397
+ | @ | Mentions a user (e.g., @openai) |
1398
+ | # | Hashtag search (e.g., #AI) |
1399
+ | is:retweet | Filters retweets |
1400
+ | is:reply | Filters replies |
1401
+ | has:media | Posts containing media (images, videos, or GIFs) |
1402
+ | has:links | Posts containing URLs |
1403
+ | lang: | Filters by language (e.g., lang:en) |
1404
+ | - | Excludes specific terms (e.g., -spam) |
1405
+ | () | Groups terms or operators (e.g., (AI OR ML)) |
1406
+ | AND, OR, NOT | Boolean logic for combining or excluding terms |
1407
+ Conjunction-Required Operators (must be combined with a standalone operator):
1408
+ | Operator | Description |
1409
+ | ------------ | -----------------------------------------------|
1410
+ | has:media | Posts containing media (images, videos, or GIFs) |
1411
+ | has:links | Posts containing URLs |
1412
+ | is:retweet | Filters retweets |
1413
+ | is:reply | Filters replies |
1414
+ For example, has:media alone is invalid, but #AI has:media is valid.
1415
+ - Input: `{ query: string, scope: "recent" | "all", options: { startTime?: string, endTime?: string, maxResults?: number } }`
1416
+ - Output: `{ posts: { id: string, authorId: string, dateCreated: string, text: string, stats: { retweets: number, replies: number, likes: number } }[] }`
1417
+
1418
+ ### YouTube
1419
+
1420
+ #### fetchYoutubeCaptions
1421
+ Retrieve the captions/transcript for a YouTube video.
1422
+ - Supports multiple languages via the language parameter.
1423
+ - "text" export produces timestamped plain text; "json" export produces structured transcript data.
1424
+ - Input: `{ videoUrl: string, exportType: "text" | "json", language: string }`
1425
+ - Output: `{ transcripts: { text: string, start: number }[] }`
1426
+
1427
+ #### fetchYoutubeChannel
1428
+ Retrieve metadata and recent videos for a YouTube channel.
1429
+ - Accepts a YouTube channel URL (e.g. https://www.youtube.com/@ChannelName or /channel/ID).
1430
+ - Returns channel info and video listings as a JSON object.
1431
+ - Input: `{ channelUrl: string }`
1432
+ - Output: `{ channel: object }`
1433
+
1434
+ #### fetchYoutubeComments
1435
+ Retrieve comments for a YouTube video.
1436
+ - Paginates through comments (up to 5 pages).
1437
+ - "text" export produces markdown-formatted text; "json" export produces structured comment data.
1438
+ - Input: `{ videoUrl: string, exportType: "text" | "json", limitPages: string }`
1439
+ - Output: `{ comments: { id: string, link: string, publishedDate: string, text: string, likes: number, replies: number, author: string, authorLink: string, authorImg: string }[] }`
1440
+
1441
+ #### fetchYoutubeVideo
1442
+ Retrieve metadata for a YouTube video (title, description, stats, channel info).
1443
+ - Returns video metadata, channel info, and engagement stats.
1444
+ - Video format data is excluded from the response.
1445
+ - Input: `{ videoUrl: string }`
1446
+ - Output: `{ video: object }`
1447
+
1448
+ #### searchYoutube
1449
+ Search for YouTube videos by keyword.
1450
+ - Supports pagination (up to 5 pages) and country/language filters.
1451
+ - Use the filter/filterType fields for YouTube search parameter (sp) filters.
1452
+ - Input: `{ query: string, limitPages: string, filter: string, filterType: string, countryCode?: string, languageCode?: string }`
1453
+ - Output: `{ results: object }`
1454
+
1455
+ #### searchYoutubeTrends
1456
+ Retrieve trending videos on YouTube by category and region.
1457
+ - Categories: "now" (trending now), "music", "gaming", "films".
1458
+ - Supports country and language filtering.
1459
+ - Input: `{ bp: "now" | "music" | "gaming" | "films", hl: string, gl: string }`
1460
+ - Output: `{ trends: object }`
1461
+
1462
+ ### Helpers
1463
+
1464
+ #### `listModels()`
1465
+ List all available AI models across all categories.
1466
+
1467
+ Output:
1468
+ ```typescript
1469
+ {
1470
+ models: {
1471
+ id: string;
1472
+ name: string; // Display name
1473
+ type: "llm_chat" | "image_generation" | "video_generation" | "video_analysis" | "text_to_speech" | "vision" | "transcription";
1474
+ maxTemperature: number;
1475
+ maxResponseSize: number;
1476
+ inputs: object[]; // Accepted input types
1477
+ }[]
1478
+ }
1479
+ ```
1480
+
1481
+ #### `listModelsByType(modelType)`
1482
+ List AI models filtered by type.
1483
+ - `modelType`: `"llm_chat"` | `"image_generation"` | `"video_generation"` | `"video_analysis"` | `"text_to_speech"` | `"vision"` | `"transcription"`
1484
+ - Output: same as `listModels()`
1485
+
1486
+ #### `listModelsSummary()`
1487
+ List all available AI models (summary). Returns only id, name, type, and tags. Suitable for display or consumption inside a model context window.
1488
+
1489
+ Output:
1490
+ ```typescript
1491
+ {
1492
+ models: {
1493
+ id: string;
1494
+ name: string;
1495
+ type: "llm_chat" | "image_generation" | "video_generation" | "video_analysis" | "text_to_speech" | "vision" | "transcription";
1496
+ tags: string; // Comma-separated tags
1497
+ }[]
1498
+ }
1499
+ ```
1500
+
1501
+ #### `listModelsSummaryByType(modelType)`
1502
+ List AI models (summary) filtered by type.
1503
+ - `modelType`: `"llm_chat"` | `"image_generation"` | `"video_generation"` | `"video_analysis"` | `"text_to_speech"` | `"vision"` | `"transcription"`
1504
+ - Output: same as `listModelsSummary()`
1505
+
1506
+ #### `listConnectors()`
1507
+ List available OAuth connector services (Slack, Google, HubSpot, etc.) and their actions. These are third-party integrations — for most tasks, use actions directly instead.
1508
+
1509
+ Output:
1510
+ ```typescript
1511
+ {
1512
+ services: {
1513
+ id: string;
1514
+ name: string;
1515
+ icon: string;
1516
+ actions: { id: string; name: string }[];
1517
+ }[]
1518
+ }
1519
+ ```
1520
+
1521
+ #### `getConnector(serviceId)`
1522
+ Get details for a single OAuth connector service by ID.
1523
+
1524
+ Output:
1525
+ ```typescript
1526
+ {
1527
+ service: {
1528
+ id: string;
1529
+ name: string;
1530
+ icon: string;
1531
+ actions: { id: string; name: string }[];
1532
+ }
1533
+ }
1534
+ ```
1535
+
1536
+ #### `getConnectorAction(serviceId, actionId)`
1537
+ Get the full configuration for an OAuth connector action, including all input fields needed to call it via `runFromConnectorRegistry`. OAuth connectors are sourced from the open-source MindStudio Connector Registry (MSCR) with 850+ actions across third-party services.
1538
+
1539
+ Output:
1540
+ ```typescript
1541
+ {
1542
+ action: {
1543
+ id: string;
1544
+ name: string;
1545
+ description: string;
1546
+ quickHelp: string;
1547
+ configuration: { title: string; items: { label: string; helpText: string; variable: string; type: string; defaultValue: string; placeholder: string; selectOptions?: object }[] }[];
1548
+ }
1549
+ }
1550
+ ```
1551
+
1552
+ #### `listConnections()`
1553
+ List OAuth connections for the organization (authenticated third-party service links). Use the returned connection IDs when calling OAuth connector actions. Connectors require the user to connect to the third-party service in MindStudio before they can be used.
1554
+
1555
+ Output:
1556
+ ```typescript
1557
+ {
1558
+ connections: {
1559
+ id: string; // Connection ID to pass to connector actions
1560
+ provider: string; // Integration provider (e.g. slack, google)
1561
+ name: string; // Display name or account identifier
1562
+ }[]
1563
+ }
1564
+ ```
1565
+
1566
+ #### `estimateStepCost(stepType, step?, options?)`
1567
+ Estimate the cost of executing a step before running it. Pass the same step config you would use for execution.
1568
+
1569
+ ```typescript
1570
+ const estimate = await agent.estimateStepCost('generateText', { message: 'Hello' });
1571
+ ```
1572
+
1573
+ - `stepType`: string — The action name (e.g. `"generateText"`).
1574
+ - `step`: object — Optional action input parameters for more accurate estimates.
1575
+ - `options`: `{ appId?: string, workflowId?: string }` — Optional context for pricing.
1576
+
1577
+ Output:
1578
+ ```typescript
1579
+ {
1580
+ costType?: string; // "free" when the step has no cost
1581
+ estimates?: {
1582
+ eventType: string; // Billing event type
1583
+ label: string; // Human-readable cost label
1584
+ unitPrice: number; // Price per unit in billing units
1585
+ unitType: string; // What constitutes a unit (e.g. "token", "request")
1586
+ estimatedCost?: number; // Estimated total cost, or null if not estimable
1587
+ quantity: number; // Number of billable units
1588
+ }[]
1589
+ }
1590
+ ```
1591
+
1592
+ #### `changeName(displayName)`
1593
+ Update the display name of the authenticated agent. Useful for agents to set their own name after connecting.
1594
+
1595
+ ```typescript
1596
+ await agent.changeName('My Agent');
1597
+ ```
1598
+
1599
+ #### `changeProfilePicture(profilePictureUrl)`
1600
+ Update the profile picture of the authenticated agent. Useful for agents to set their own avatar after connecting.
1601
+
1602
+ ```typescript
1603
+ await agent.changeProfilePicture('https://example.com/avatar.png');
1604
+ ```
1605
+
1606
+ #### `uploadFile(content, options)`
1607
+ Upload a file to the MindStudio CDN. Gets a signed upload URL, PUTs the file content, and returns the permanent public URL.
1608
+
1609
+ ```typescript
1610
+ import { readFileSync } from 'fs';
1611
+ const { url } = await agent.uploadFile(readFileSync('photo.png'), { extension: 'png', type: 'image/png' });
1612
+ ```
1613
+
1614
+ - `content`: `Buffer | Uint8Array` — The file content.
1615
+ - `options.extension`: string — File extension without the dot (e.g. `"png"`, `"jpg"`, `"mp4"`).
1616
+ - `options.type`: string (optional) — MIME type (e.g. `"image/png"`). Determines which CDN subdomain is used.
1617
+
1618
+ Output: `{ url: string }` — The permanent public CDN URL.