Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tailor-platform/sdk/llms.txt

Use this file to discover all available pages before exploring further.

Workflows enable you to orchestrate multiple jobs that can depend on each other, providing durable execution and automatic state management.

Overview

Workflows provide:
  • Job orchestration with dependencies
  • Durable execution with automatic state management
  • Resume capabilities from failure points
  • Access to TailorDB via Kysely query builder
  • Job triggering to compose multi-step logic
For the official Tailor Platform documentation, see Workflow Guide.

Workflow Rules

All workflow components must follow these rules:
Definition Rules:
  • One workflow + multiple jobs per file: Each file can define multiple jobs (named exports) and one workflow (default export)
  • Workflow export method: Must use export default
  • Job export method: Must use named exports (export const)
  • Job name uniqueness: Job names must be unique across the entire project (not just within one file)
  • mainJob required: Every workflow must specify a mainJob
RuleDescription
createWorkflow result must be default exportWorkflow files must export the workflow as default
All jobs must be named exportsIncludes mainJob and any job triggered via .trigger() (even if referenced only within the same file)
Job name values must be uniqueJob names must be unique across the entire project
mainJob is requiredEvery workflow must specify a mainJob

Creating a Workflow Job

Define workflow jobs using createWorkflowJob:
example/workflows/jobs/fetch-customer.ts
import { createWorkflowJob } from "@tailor-platform/sdk";
import { getDB } from "../../generated/tailordb";

// All jobs must be named exports
export const fetchCustomer = createWorkflowJob({
  name: "fetch-customer",
  body: async (input: { customerId: string }) => {
    const db = getDB("tailordb");
    const customer = await db
      .selectFrom("Customer")
      .selectAll()
      .where("id", "=", input.customerId)
      .executeTakeFirst();
    return customer;
  },
});

Input and Output Type Constraints

Workflow job inputs and outputs are serialized as JSON when passed between jobs. This imposes type constraints:
Input types must be JSON-compatible — only primitives (string, number, boolean, null), arrays, and plain objects are allowed. Date, Map, Set, functions, and other non-serializable types cannot be used.
// OK
export const myJob = createWorkflowJob({
  name: "my-job",
  body: async (input: { id: string; count: number; tags: string[] }) => {
    // ...
  },
});

// Compile error — Date is not allowed in input
export const badJob = createWorkflowJob({
  name: "bad-job",
  body: async (input: { createdAt: Date }) => {
    // ...
  },
});
Output types are more permissive — Date and objects with toJSON() are allowed because they are serialized via JSON.stringify at runtime (e.g., Date becomes a string).
These constraints are enforced at compile time — you will get a type error if you use an unsupported type.

Triggering Jobs

Use .trigger() to start other jobs from within a job.
example/workflows/sample.ts
import { createWorkflow, createWorkflowJob } from "@tailor-platform/sdk";
import { format } from "date-fns";
import { getDB } from "../generated/tailordb";

export const process_payment = createWorkflowJob({
  name: "process-payment",
  body: async () => {
    const db = getDB("tailordb");
    const invoices = await db.selectFrom("Invoice").selectAll().execute();
    return invoices.reduce(
      (sum, invoice) => [...sum, invoice.status],
      [] as (typeof invoices)[number]["status"][],
    );
  },
});

export const check_inventory = createWorkflowJob({
  name: "check-inventory",
  body: () => format(new Date(), "yyyy-MM-dd HH:mm:ss"),
});

export const validate_order = createWorkflowJob({
  name: "validate-order",
  body: async (input: { orderId: string }) => {
    console.log("Order ID:", input.orderId);
    const inventoryResult = await check_inventory.trigger();
    const paymentResult = await process_payment.trigger();
    return { inventoryResult, paymentResult };
  },
});

export default createWorkflow({
  name: "sample-workflow",
  mainJob: validate_order,
});
Important: On the Tailor runtime, job triggers are executed synchronously. This means Promise.all([jobA.trigger(), jobB.trigger()]) will not run jobs in parallel.

Workflow Definition

Define a workflow using createWorkflow and export it as default:
example/workflows/order-processing.ts
import { createWorkflow, createWorkflowJob } from "@tailor-platform/sdk";
import { fetchCustomer } from "./jobs/fetch-customer";
import { sendNotification } from "./jobs/send-notification";

export const processOrder = createWorkflowJob({
  name: "process-order",
  body: async (input: { orderId: string; customerId: string }, { env, user }) => {
    // `env` contains values from `tailor.config.ts` -> `env`.
    console.log("Environment:", env);
    console.log("User:", user.id);

    // Fetch customer information using trigger
    const customer = await fetchCustomer.trigger({
      customerId: input.customerId,
    });

    if (!customer) {
      throw new Error(`Customer ${input.customerId} not found`);
    }

    // Send notification to customer using trigger
    const notification = await sendNotification.trigger({
      message: `Your order ${input.orderId} is being processed`,
      recipient: customer.email,
    });

    return {
      orderId: input.orderId,
      customerId: input.customerId,
      customerEmail: customer.email,
      notificationSent: notification.sent,
      processedAt: notification.timestamp,
    };
  },
});

// Workflow must be default export
export default createWorkflow({
  name: "order-processing",
  mainJob: processOrder,
});

Triggering a Workflow from a Resolver

You can start a workflow execution from a resolver using workflow.trigger().
  • workflow.trigger(args, options?) returns a workflow run ID (Promise<string>)
  • To run with machine-user permissions, pass { authInvoker: auth.invoker("<machine-user>") }
example/resolvers/triggerWorkflow.ts
import { createResolver, t } from "@tailor-platform/sdk";
import { auth } from "../tailor.config";
import orderProcessingWorkflow from "../workflows/order-processing";

export default createResolver({
  name: "triggerOrderProcessing",
  description: "Trigger the order processing workflow",
  operation: "mutation",
  input: {
    orderId: t.string().description("Order ID to process"),
    customerId: t.string().description("Customer ID for the order"),
  },
  body: async ({ input }) => {
    // Trigger the workflow with authInvoker
    const workflowRunId = await orderProcessingWorkflow.trigger(
      {
        orderId: input.orderId,
        customerId: input.customerId,
      },
      { authInvoker: auth.invoker("manager-machine-user") },
    );

    return {
      workflowRunId,
      message: `Workflow triggered for order ${input.orderId}`,
    };
  },
  output: t.object({
    workflowRunId: t.string(),
    message: t.string(),
  }),
});

Triggering from Executors

Workflows can also be triggered from executors:
example/executors/dailyWorkflow.ts
import { createExecutor, scheduleTrigger } from "@tailor-platform/sdk";
import sampleWorkflow from "../workflows/sample";

export default createExecutor({
  name: "daily-workflow",
  description: "Scheduled workflow executor",
  trigger: scheduleTrigger({
    cron: "0 12 * * *",
    timezone: "Asia/Tokyo",
  }),
  operation: {
    kind: "workflow",
    workflow: sampleWorkflow,
    args: () => ({ orderId: "daily-workflow-order" }),
  },
});

File Organization

Recommended file structure for workflows:
workflows/
├── jobs/
│   ├── fetch-customer.ts    # export const fetchCustomer = createWorkflowJob(...)
│   └── send-notification.ts # export const sendNotification = createWorkflowJob(...)
└── order-processing.ts      # export const processOrder = createWorkflowJob(...)
                             # export default createWorkflow(...)
All jobs can be in a single file or split across multiple files, as long as they are named exports.

CLI Commands

Manage workflows using the CLI:
# List workflows
tailor-sdk workflow list

# Get workflow details
tailor-sdk workflow get <name>

# Start a workflow
tailor-sdk workflow start <name> -m <machine-user> -a '{"key": "value"}'

# List executions
tailor-sdk workflow executions

# Get execution details with logs
tailor-sdk workflow executions <execution-id> --logs

# Resume a failed execution
tailor-sdk workflow resume <execution-id>