Skip to main content
Travel operations are full of long-running, multi-step processes: reserving and confirming a booking across several suppliers, sending a sequence of payment reminders, syncing a supplier catalog, or running a nightly reconciliation. Voyant Workflows let you write these as durable orchestrations that survive restarts and resume exactly where they left off. A workflow is plain TypeScript. You break the process into steps, and the runtime records the result of each step. If the process is interrupted, it resumes from the last completed step rather than starting over. You can sleep for hours or days, retry on failure, and wait for external events, all without managing your own queue or state machine.

Authoring a workflow

Workflows are authored with the @voyant-travel/workflows package. You define a workflow with an id, a typed input, and a run function that receives the input and a context object:
import { workflow } from "@voyant-travel/workflows";
import { z } from "zod";

export const sendBookingReminders = workflow({
  id: "send-booking-reminders",
  input: z.object({ bookingId: z.string() }),

  async run(input, ctx) {
    const booking = await ctx.step("fetch", () =>
      db.bookings.findById(input.bookingId),
    );

    await ctx.sleep("24h");

    await ctx.step("send-reminder", async () => {
      await email.send(booking.customerEmail, "Reminder...");
    });
  },
});
The building blocks on ctx:
  • ctx.step(name, fn) runs a unit of work and records its result. On resume, a completed step returns its saved result instead of running again, so steps must be idempotent in spirit.
  • ctx.sleep(duration) durably pauses the workflow. The runtime wakes it when the duration elapses, even if that is days later.
  • trigger.on(...) lets a workflow react to external events.

Triggering workflows

Application code triggers workflows through a separate, app-safe entry point so your app bundle never has to import workflow definitions or runner code:
import { workflows } from "@voyant-travel/workflows/client";

await workflows.trigger("send-booking-reminders", { bookingId: "bkg_123" });
The @voyant-travel/workflows/client subpath is the managed Cloud client. It is safe to import from app and server code because it only knows how to trigger and forward events, not how to execute workflow bodies.

SDK subpaths

The authoring package exposes focused subpaths so each runtime imports only what it needs:
SubpathPurpose
@voyant-travel/workflowsAuthoring API: workflow, trigger, conditions, errors.
@voyant-travel/workflows/clientApp and server-safe managed Cloud client.
@voyant-travel/workflows/testingIn-process test harness (runWorkflowForTest, resumeWorkflowForTest).
@voyant-travel/workflows/handlerNode-side step handler for the wire protocol.
@voyant-travel/workflows/authPaired HMAC signer and verifier for dispatch authentication.
@voyant-travel/workflows/errorsTyped errors: FatalError, RetryableError, TimeoutError.

Where workflows run

The same workflow definition runs in two modes:
  • Self-host. Use the @voyant-travel/workflows-orchestrator engine with the Node and Postgres driver to run workflows on your own infrastructure.
  • Managed Cloud. Voyant Cloud runs your workflow bundles in a hosted Node runtime. Cloud creates releases from your deployments, artifacts, hashes, and environment snapshots, and injects the runtime configuration your app needs (VOYANT_CLOUD_WORKFLOWS_URL, a trigger token, the app slug, and the environment).
You author once and choose the runtime at deploy time.

Developing and inspecting workflows

The CLI drives the full workflow lifecycle locally. Watch and hot-reload definitions while you build:
voyant dev --file ./src/workflows.ts
List, run, inspect, and self-host workflows with the workflows subcommands:
voyant workflows list --file ./src/workflows.ts
voyant workflows run send-booking-reminders --file ./src/workflows.ts --input '{"bookingId":"bkg_123"}'
voyant workflows runs --status running
voyant workflows run-detail <run-id>
voyant workflows tail <run-id>
voyant workflows replay <run-id> --file ./src/workflows.ts
See the CLI command reference for the complete set, including build, deploy, manifest, doctor, trigger, and prune.

Inspecting runs in the UI

The @voyant-travel/workflows-react package ships hooks and an importable admin UI for inspecting workflow runs, so you can surface run status and step history inside your own admin console.

Next steps

CLI commands

Every workflow subcommand and flag.

Deploy to Cloud

Run workflows on the managed hosted runtime.