Package Exports
- @avallo/workflow-sdk
Readme
@avallo/workflow-sdk
Official SDK for building custom integrations with Avallo Workflow Engine
Build production-ready workflow actions and triggers for the Avallo Workflow Engine with a simple, TypeScript-first API.
Features
- ✨ Simple API: Define actions and triggers with minimal boilerplate
- 🔒 Type-Safe: Full TypeScript support with intelligent autocomplete
- 🎯 Best-in-Class DX: Optimized for developer experience
- 🔄 Variable Interpolation: Built-in support for
{{variable}}syntax - 📊 Schema Generation: Automatic JSON Schema + UI Schema generation
- 🔌 Plug & Play: Works seamlessly with the Avallo Workflow Engine
Installation
npm install @avallo/workflow-sdk
# or
pnpm add @avallo/workflow-sdk
# or
yarn add @avallo/workflow-sdkQuick Start
Creating an Action
import { defineAction } from '@avallo/workflow-sdk';
export default defineAction({
id: 'send-email',
name: 'Send Email',
description: 'Sends an email via SMTP',
config: {
to: {
type: 'string',
label: 'To',
description: 'Recipient email address',
required: true,
supportsVariables: true,
},
subject: {
type: 'string',
label: 'Subject',
required: true,
supportsVariables: true,
},
body: {
type: 'textarea',
label: 'Body',
required: true,
supportsVariables: true,
},
},
async execute(context) {
// Interpolate variables like {{previous_node.email}}
const to = context.utils.interpolate(context.config.to);
const subject = context.utils.interpolate(context.config.subject);
const body = context.utils.interpolate(context.config.body);
// Your email sending logic here
await sendEmail({ to, subject, body });
return {
success: true,
message_id: 'msg_123',
sent_at: new Date().toISOString(),
};
},
outputs: {
success: {
type: 'boolean',
label: 'Success',
description: 'Whether the email was sent successfully',
},
message_id: {
type: 'string',
label: 'Message ID',
description: 'Unique identifier for the sent email',
},
sent_at: {
type: 'string',
label: 'Sent At',
description: 'Timestamp when the email was sent',
},
},
});Creating a Trigger
import { defineTrigger } from '@avallo/workflow-sdk';
export default defineTrigger({
id: 'new-email',
name: 'New Email',
description: 'Triggers when a new email arrives',
type: 'polling',
config: {
folder: {
type: 'select',
label: 'Folder',
description: 'Which folder to monitor',
required: true,
options: [
{ label: 'Inbox', value: 'inbox' },
{ label: 'Sent', value: 'sent' },
{ label: 'Drafts', value: 'drafts' },
],
},
},
async execute(context) {
const folder = context.trigger_config.folder;
// Fetch new emails
const emails = await fetchNewEmails(folder);
// Return result
return context.utils.createResult(
emails.length > 0,
emails,
{
checked_at: new Date(),
items_found: emails.length,
}
);
},
outputs: {
from: {
type: 'string',
label: 'From',
description: 'Sender email address',
},
subject: {
type: 'string',
label: 'Subject',
description: 'Email subject',
},
body: {
type: 'string',
label: 'Body',
description: 'Email body content',
},
received_at: {
type: 'string',
label: 'Received At',
description: 'Timestamp when email was received',
},
},
polling_config: {
interval_seconds: 300, // Check every 5 minutes
dedupe_key: 'email_id',
},
});Creating a Complete App
import { defineApp } from '@avallo/workflow-sdk';
import sendEmailAction from './actions/send-email';
import newEmailTrigger from './triggers/new-email';
export default defineApp({
app_id: 'my-email-app',
name: 'My Email App',
description: 'Email integration for workflows',
category: 'communication',
icon_url: 'https://example.com/icon.png',
actions: [sendEmailAction],
triggers: [newEmailTrigger],
});API Reference
defineAction(options)
Define a workflow action node.
Options:
id(string): Unique identifier for the actionname(string): Display namedescription(string): Short descriptioncategory(string, optional): Category for groupingicon(string, optional): Icon name or URLconfig(SimplifiedConfigSchema): Configuration fieldsexecute(function): Execution handleroutputs(SimplifiedOutputSchema): Output field definitionsrequires_connection(boolean, optional): Whether connection is neededis_premium(boolean, optional): Whether action requires premium plandocumentation_url(string, optional): Link to documentation
Returns: { definition, execute }
defineTrigger(options)
Define a workflow trigger node.
Options:
id(string): Unique identifier for the triggername(string): Display namedescription(string): Short descriptiontype('webhook' | 'polling' | 'event'): Trigger typecategory(string, optional): Category for groupingicon(string, optional): Icon name or URLconfig(SimplifiedConfigSchema): Configuration fieldsexecute(function): Execution handleroutputs(SimplifiedOutputSchema): Output field definitionspolling_config(object, optional): Polling configurationinterval_seconds(number): Check interval in secondsdedupe_key(string, optional): Field to deduplicate on
requires_connection(boolean, optional): Whether connection is neededis_premium(boolean, optional): Whether trigger requires premium plandocumentation_url(string, optional): Link to documentation
Returns: { definition, execute }
defineApp(options)
Define a complete app with multiple actions and triggers.
Options:
app_id(string): Unique app identifiername(string): App namedescription(string, optional): App descriptionicon_url(string, optional): App icon URLcategory(string, optional): App categoryactions(array): Array of defined actionstriggers(array, optional): Array of defined triggers
Returns: App registration object
Configuration Field Types
| Type | Description | Example |
|---|---|---|
string |
Text input | Email address, name |
number |
Numeric input | Age, count |
boolean |
Checkbox | Enable feature |
select |
Dropdown | Choose option |
multiselect |
Multi-select | Tags |
textarea |
Multi-line text | Message body |
date |
Date picker | Birth date |
datetime |
Date + time picker | Scheduled time |
Context Utilities
Action Context
context.config // Parsed configuration
context.workflow_id // Current workflow ID
context.execution_id // Current execution ID
context.node_id // Current node ID
context.previous_outputs // All previous node outputs
// Utilities
context.utils.interpolate(str) // Interpolate {{variables}}
context.utils.fetch(url, options) // Make HTTP requests
context.utils.log(level, msg) // Log messagesTrigger Context
context.trigger_config // Trigger configuration
context.workflow_id // Workflow ID
context.client_id // Client ID
context.account_id // Account ID
// Utilities
context.utils.interpolate(str) // Interpolate {{variables}}
context.utils.fetch(url, options) // Make HTTP requests
context.utils.log(level, msg) // Log messages
context.utils.createResult(hasData, data) // Create trigger resultVariable Interpolation
The SDK supports variable interpolation using {{variable}} syntax:
// In config
{
email: {
type: 'string',
label: 'Email',
supportsVariables: true, // Enable variable interpolation
}
}
// In execute function
const email = context.utils.interpolate(context.config.email);
// "{{webhook.body.email}}" → "user@example.com"Error Handling
import { createActionError, createActionSuccess } from '@avallo/workflow-sdk';
async execute(context) {
try {
const result = await doSomething();
return createActionSuccess(result, {
duration_ms: 150,
records_processed: 5,
});
} catch (error) {
return createActionError(error.message, {
error_code: error.code,
});
}
}Best Practices
- Validate Configuration: Use the
validatehook to validate configuration before execution - Use Type Safety: Leverage TypeScript for better DX
- Log Appropriately: Use
context.utils.log()for debugging - Handle Errors Gracefully: Always wrap execution in try/catch
- Document Outputs: Provide clear descriptions for all output fields
- Support Variables: Enable
supportsVariablesfor user-facing strings - Test Thoroughly: Test with real workflow executions
Examples
See the examples directory for more complete examples:
Support
License
MIT © Avallo