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.

Executors are event-driven handlers that enable automatic execution in response to various triggers, making them ideal for background tasks, integrations, and event processing.

Overview

Executors provide:
  • Automatic triggers on record changes (create, update, delete)
  • Scheduled execution via cron expressions
  • Incoming webhook handlers
  • Post-resolver execution hooks
  • Multiple operation types (functions, webhooks, GraphQL, workflows)
For the official Tailor Platform documentation, see Executor Guide.

Creating an Executor

Define executors in files matching glob patterns specified in tailor.config.ts.
Definition Rules:
  • One executor per file: Each file must contain exactly one executor definition
  • Export method: Must use export default
  • Uniqueness: Executor names must be unique globally across your entire application
example/executors/userCreated.ts
import { createExecutor, recordCreatedTrigger } from "@tailor-platform/sdk";
import { user } from "../tailordb/user";

export default createExecutor({
  name: "user-created",
  description: "Triggered when a new user is created",
  trigger: recordCreatedTrigger({
    type: user,
    condition: ({ newRecord }) => newRecord.email.endsWith("@tailor.tech"),
  }),
  operation: {
    kind: "function",
    body: async ({ newRecord }) => {
      console.log("New user created:", newRecord.email);
      // Send welcome email logic here
    },
  },
});

Trigger Types

Record Triggers

Fire when records are created, updated, or deleted:
recordCreatedTrigger
function
Fires when a new record is created
recordUpdatedTrigger
function
Fires when a record is updated
recordDeletedTrigger
function
Fires when a record is deleted
Each trigger can include an optional filter function:
recordUpdatedTrigger({
  type: order,
  condition: ({ newRecord, oldRecord }) =>
    newRecord.status === "completed" && oldRecord.status !== "completed",
});

Schedule Trigger

Fires on a cron schedule:
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" }),
  },
});
scheduleTrigger({ cron: "*/5 * * * *" });

Incoming Webhook Trigger

Fires when an external webhook is received:
example/executors/testWebhook.ts
import { createExecutor, incomingWebhookTrigger } from "@tailor-platform/sdk";

export default createExecutor({
  name: "test-webhook",
  description: "Test executor for incoming webhook trigger",
  trigger: incomingWebhookTrigger<{
    body: { message: string };
    headers: Record<string, string>;
  }>(),
  operation: {
    kind: "function",
    body: (args) => {
      console.log("Webhook received:", args.body);
      console.log("Headers:", args.headers);
    },
  },
});

Resolver Executed Trigger

Fires when a resolver is executed:
resolverExecutedTrigger({
  resolver: createOrderResolver,
  condition: ({ result, error }) => !error && result?.order?.id,
});

Operation Types

Function Operation

Execute JavaScript/TypeScript functions:
createExecutor({
  operation: {
    kind: "function",
    body: async ({ newRecord }) => {
      console.log("New record created:", newRecord);
    },
  },
});

Job Function Operation

For long-running operations, use jobFunction which runs asynchronously and supports extended execution times. See Job Function Operation for details.
import { createExecutor, scheduleTrigger } from "@tailor-platform/sdk";
import { getDB } from "../generated/tailordb";

export default createExecutor({
  name: "daily-report-generator",
  description: "Generate daily reports",
  trigger: scheduleTrigger({ cron: "0 0 * * *" }),
  operation: {
    kind: "jobFunction",
    body: async () => {
      const db = getDB("tailordb");
      // Long-running report generation logic
      const records = await db.selectFrom("Order").selectAll().execute();
      // Process records...
    },
  },
});

Webhook Operation

Call external webhooks with dynamic data:
createExecutor({
  operation: {
    kind: "webhook",
    url: ({ typeName }) => `https://api.example.com/webhooks/${typeName}`,
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": { vault: "api-keys", key: "external-api" },
    },
    requestBody: ({ newRecord }) => ({
      id: newRecord.id,
      timestamp: new Date(),
      data: newRecord,
    }),
  },
});

GraphQL Operation

Execute GraphQL queries and mutations:
example/executors/salesOrderCreated.ts
import { createExecutor, recordCreatedTrigger } from "@tailor-platform/sdk";
import { salesOrder } from "../tailordb/salesOrder";

export default createExecutor({
  name: "sales-order-created",
  description: "Triggered when a new sales order is created",
  trigger: recordCreatedTrigger({
    type: salesOrder,
    condition: ({ newRecord }) => (newRecord.totalPrice ?? 0) > 100_0000,
  }),
  operation: {
    kind: "graphql",
    query: /* gql */ `
      mutation createSalesOrderCreated($input: SalesOrderCreatedCreateInput!) {
        createSalesOrderCreated(input: $input) {
          id
        }
      }
    `,
    variables: ({ newRecord }) => ({
      input: {
        salesOrderID: newRecord.id,
        customerID: newRecord.customerID,
        totalPrice: newRecord.totalPrice,
        status: newRecord.status,
      },
    }),
  },
});

Workflow Operation

Trigger workflows from executors. See Workflow documentation for how to define workflows.
import { createExecutor, recordCreatedTrigger } from "@tailor-platform/sdk";
import { order } from "../tailordb/order";
import processOrderWorkflow from "../workflows/process-order";

export default createExecutor({
  name: "order-processor",
  description: "Process new orders via workflow",
  trigger: recordCreatedTrigger({ type: order }),
  operation: {
    kind: "workflow",
    workflow: processOrderWorkflow,
    args: ({ newRecord }) => ({
      orderId: newRecord.id,
      customerId: newRecord.customerId,
    }),
  },
});
You can also pass static arguments:
createExecutor({
  operation: {
    kind: "workflow",
    workflow: dailyReportWorkflow,
    args: { reportType: "summary" },
  },
});

Authentication for Operations

GraphQL and Workflow operations can specify an authInvoker to execute with machine user credentials:
import { defineAuth, createExecutor, scheduleTrigger } from "@tailor-platform/sdk";

const auth = defineAuth("my-auth", {
  // ... auth configuration
  machineUsers: {
    "batch-processor": {
      attributes: { role: "ADMIN" },
    },
  },
});

export default createExecutor({
  name: "scheduled-cleanup",
  trigger: scheduleTrigger({ cron: "0 0 * * *" }),
  operation: {
    kind: "graphql",
    query: `mutation { cleanupOldRecords { count } }`,
    authInvoker: auth.invoker("batch-processor"),
  },
});

Event Payloads

Each trigger type provides specific context data in the callback functions.

Record Event Payloads

Record triggers receive context based on the operation type:

Created Event

interface RecordCreatedContext<T> {
  workspaceId: string; // Workspace identifier
  appNamespace: string; // Application/namespace name
  typeName: string; // TailorDB type name
  newRecord: T; // The newly created record
}

Updated Event

interface RecordUpdatedContext<T> {
  workspaceId: string;
  appNamespace: string;
  typeName: string;
  oldRecord: T; // Previous record state
  newRecord: T; // Current record state
}

Deleted Event

interface RecordDeletedContext<T> {
  workspaceId: string;
  appNamespace: string;
  typeName: string;
  oldRecord: T; // The deleted record
}

Schedule Event Payload

Schedule triggers receive minimal context:
interface ScheduleContext {
  scheduledTime: string; // ISO 8601 timestamp
}

Incoming Webhook Payload

Webhook triggers receive HTTP request data:
interface WebhookContext<T = unknown> {
  body: T; // Parsed request body
  headers: Record<string, string>; // Request headers
  method: "POST" | "GET" | "PUT" | "DELETE"; // HTTP method
  rawBody: string; // Raw request body as string
}

Resolver Executed Payload

Resolver triggers receive the resolver’s result or error:
interface ResolverExecutedContext<TResult> {
  workspaceId: string; // Workspace identifier
  appNamespace: string; // Application/namespace name
  resolverName: string; // Name of the executed resolver
  result?: TResult; // Return value (on success)
  error?: string; // Error message (on failure)
}