Creating Workflows
Workflows are defined using the Tailor Platform SDK with TypeScript. This approach provides type safety, version control, and seamless integration with other platform services.
Directory Structure
src/
├── workflows/
│ ├── order-processing.ts # Workflow definition
│ └── steps/
│ ├── validate-order.ts
│ ├── check-inventory.ts
│ └── process-payment.ts
└── index.tsDefining Workflow Steps
In the SDK, workflow steps are defined as TypeScript functions. Each step contains its logic and is composable:
import { WorkflowStep } from "@tailor-platform/sdk";
export const validateOrderStep: WorkflowStep = {
name: "validate-order",
handler: async (args) => {
if (!args.orderId) {
throw new Error("orderId is required");
}
// Validation logic
return { validated: true, orderId: args.orderId };
},
};import { WorkflowStep } from "@tailor-platform/sdk";
export const checkInventoryStep: WorkflowStep = {
name: "check-inventory",
handler: async (args) => {
// Inventory check logic
return { inStock: true, orderId: args.orderId };
},
};import { WorkflowStep } from "@tailor-platform/sdk";
export const processPaymentStep: WorkflowStep = {
name: "process-payment",
handler: async (args) => {
// Payment processing logic
return { paymentId: "pay_123", status: "completed" };
},
};Defining Workflows
Create a workflow that composes multiple steps:
import { createWorkflow } from "@tailor-platform/sdk";
import { validateOrderStep } from "./steps/validate-order";
import { checkInventoryStep } from "./steps/check-inventory";
import { processPaymentStep } from "./steps/process-payment";
export const orderProcessingWorkflow = createWorkflow({
name: "order-processing",
steps: [validateOrderStep, checkInventoryStep, processPaymentStep],
});Properties:
name(String, Required) - Workflow name (unique within workspace)steps(Array, Required) - Array of workflow steps to execute
Versioning
Job functions are automatically versioned:
- When a job function's script changes, a new version is created
- Unchanged scripts reuse the existing version
- Workflows can reference specific versions or always use the latest
Managing Workflows
List workflows:
npx tailor workflow listGet workflow details:
npx tailor workflow get <workflow-name>Start a workflow execution:
npx tailor workflow start <workflow-name> --args '{"orderId": "123"}'Writing Step Functions
Workflow steps are TypeScript functions that form the building blocks of your workflow. Each step function receives input arguments and returns output:
export const myStep: WorkflowStep = {
name: "my-step",
handler: async (args) => {
// Your code here
return { result: "success" };
},
};Function signature:
- Input:
argsobject with type safety - Output: JSON-serializable object
- Async/await: Supported for asynchronous operations
Composing Steps
In SDK workflows, steps are executed sequentially by the workflow engine. Data flows from one step to the next:
import { createWorkflow } from "@tailor-platform/sdk";
export const myWorkflow = createWorkflow({
name: "my-workflow",
steps: [
{
name: "step1",
handler: async (args) => {
return { data: "from step 1" };
},
},
{
name: "step2",
handler: async (args) => {
// Access output from previous step
console.log(args.data); // "from step 1"
return { result: "complete" };
},
},
],
});Example: Multi-step workflow
Here's a complete example showing how to compose multiple job functions:
export function main(args) {
console.log("Starting workflow with orderId:", args.orderId);
// Step 1: Fetch order data
const order = tailor.workflow.triggerJobFunction("fetchOrder", {
orderId: args.orderId,
});
// Step 2: Validate order
const validated = tailor.workflow.triggerJobFunction("validateOrder", order);
// Step 3: Process payment
const payment = tailor.workflow.triggerJobFunction("processPayment", {
orderId: validated.id,
amount: validated.total,
});
// Step 4: Send confirmation
tailor.workflow.triggerJobFunction("sendConfirmation", {
orderId: validated.id,
email: validated.customerEmail,
paymentId: payment.id,
});
return {
success: true,
orderId: validated.id,
paymentId: payment.id,
};
}export function main(args) {
console.log("Fetching order:", args.orderId);
// Simulate fetching from API
return {
id: args.orderId,
customerEmail: "customer@example.com",
items: [{ name: "Product A", price: 100 }],
total: 100,
};
}export function main(args) {
console.log("Validating order:", args.id);
if (!args.items || args.items.length === 0) {
throw new Error("Order has no items");
}
if (!args.customerEmail) {
throw new Error("Customer email is required");
}
return args; // Return validated order
}Error Handling
Throw errors to mark a job function as failed:
export function main(args) {
if (!args.requiredField) {
throw new Error("requiredField is missing");
}
try {
// Risky operation
const result = performOperation();
return { success: true, result };
} catch (error) {
throw new Error(`Operation failed: ${error.message}`);
}
}When an error occurs:
- The workflow execution is marked as
failed - The error message and stack trace are saved
- The workflow can be resumed using the
resumecommand
Logging
Use console.log() for logging:
export function main(args) {
console.log("Processing started");
console.log("Input:", JSON.stringify(args));
// Your code
console.log("Processing completed");
return { status: "done" };
}