# Temporal workflow [Temporal](https://temporal.io/) is a durable execution platform for orchestrating long-running, fault-tolerant workflows. The `@mastra/temporal` package lets you author workflows with the standard Mastra API and run them on a Temporal cluster. > **Warning:** `@mastra/temporal` is experimental and not ready for production use. The API may change between releases. See the [package README](https://github.com/mastra-ai/mastra/tree/main/workflows/temporal) for the current state. ## How Temporal works with Mastra Mastra workflows authored with `createWorkflow()` and `createStep()` map onto Temporal's workflow and activity model. The `MastraPlugin` for the Temporal worker compiles your Mastra entry file at bundle time: - Each `createStep()` handler is extracted into a Temporal activity. - Each `createWorkflow()` is rewritten into a Temporal workflow that invokes those activities. - The plugin registers the generated activities and workflows with the worker automatically. When a run starts through `mastra.getWorkflow(...).createRun().start(...)`, the Mastra client hands control to Temporal. Temporal then drives durable execution, retries, and state persistence on the worker. ## Setup Install the required packages: **npm**: ```bash npm install @mastra/temporal@latest @temporalio/client @temporalio/worker @temporalio/envconfig ``` **pnpm**: ```bash pnpm add @mastra/temporal@latest @temporalio/client @temporalio/worker @temporalio/envconfig ``` **Yarn**: ```bash yarn add @mastra/temporal@latest @temporalio/client @temporalio/worker @temporalio/envconfig ``` **Bun**: ```bash bun add @mastra/temporal@latest @temporalio/client @temporalio/worker @temporalio/envconfig ``` You also need access to a Temporal cluster. For local development, you can run one with Docker (see [Running locally](#running-locally)). ## Building a Temporal-backed workflow This guide walks through creating a workflow with Temporal and Mastra, demonstrating a counter application that increments a value. ### Temporal initialization Initialize the Temporal integration to obtain Mastra-compatible workflow helpers. The `createWorkflow()` and `createStep()` functions are bound to a Temporal client and a task queue. ```ts import { init } from '@mastra/temporal' import { Client, Connection } from '@temporalio/client' import { loadClientConnectConfig } from '@temporalio/envconfig' const config = loadClientConnectConfig() const connection = await Connection.connect(config.connectionOptions) const client = new Client({ connection }) export const { createWorkflow, createStep } = init({ client, taskQueue: 'mastra', }) ``` `loadClientConnectConfig()` reads standard Temporal environment variables such as `TEMPORAL_ADDRESS`, `TEMPORAL_NAMESPACE`, and mTLS settings. See the [Temporal envconfig docs](https://docs.temporal.io/develop/typescript/temporal-clients) for the full list. ### Creating steps Define the individual steps that will compose your workflow. Each step becomes a Temporal activity. ```ts import { z } from 'zod' import { createWorkflow, createStep } from '../temporal' const incrementStep = createStep({ id: 'increment', inputSchema: z.object({ value: z.number(), }), outputSchema: z.object({ value: z.number(), }), execute: async ({ inputData }) => { return { value: inputData.value + 1 } }, }) ``` ### Creating the workflow Compose the steps into a workflow. The workflow `id` must be a static string literal so the build-time transformer can derive its Temporal export name. ```ts const workflow = createWorkflow({ id: 'increment-workflow', steps: [incrementStep], inputSchema: z.object({ value: z.number(), }), outputSchema: z.object({ value: z.number(), }), }).then(incrementStep) workflow.commit() export { workflow as incrementWorkflow } ``` ### Configuring the Mastra instance Register the workflow with Mastra. The execution is driven by the Temporal worker. ```ts import { Mastra } from '@mastra/core' import { PinoLogger } from '@mastra/loggers' import { incrementWorkflow } from './workflows' export const mastra = new Mastra({ workflows: { incrementWorkflow }, logger: new PinoLogger({ name: 'Mastra', level: 'info' }), }) ``` ## Running the worker The worker is a long-lived Node.js process that polls a Temporal task queue. Install `MastraPlugin` and point its `src` option at the Mastra entry file that registers your workflows. ```ts import { MastraPlugin } from '@mastra/temporal/worker' import { NativeConnection, Worker } from '@temporalio/worker' const connection = await NativeConnection.connect({ address: 'localhost:7233', }) const mastraPlugin = new MastraPlugin() await mastraPlugin.prebuild({ entryFile: import.meta.resolve('./index.ts'), }) const worker = await Worker.create({ connection, namespace: 'default', taskQueue: 'mastra', plugins: [mastraPlugin], }) await worker.run() ``` `MastraPlugin` rewrites the entry file into a workflow-only bundle and wires step handlers in as Temporal activities. You do not need to pass `activities` or `workflowsPath` to `Worker.create()` manually. ## Running workflows ### Running locally 1. Start a local Temporal server. The simplest option is the `temporalio/auto-setup` Docker image: ```bash docker run --rm -p 7233:7233 -p 8080:8080 temporalio/auto-setup:latest ``` 2. Open the Temporal UI at to inspect namespaces, workflows, and activities. 3. Start the worker. In a new terminal, run: ```bash npx tsx src/mastra/worker.ts ``` 4. Trigger a workflow run from a script or any process that imports your Mastra instance: ```ts import { mastra } from '../src/mastra' const run = await mastra.getWorkflow('incrementWorkflow').createRun() const result = await run.start({ inputData: { value: 5 } }) console.log(result) ``` 5. Monitor execution in the Temporal UI under **Workflows** to see step-by-step activity progress and retry history. ### Running in production For production, use [Temporal Cloud](https://temporal.io/cloud) or a self-hosted Temporal cluster. Configure the client and worker connections through environment variables read by `@temporalio/envconfig`: ```bash TEMPORAL_ADDRESS=your-namespace.tmprl.cloud:7233 TEMPORAL_NAMESPACE=your-namespace TEMPORAL_API_KEY=your-api-key ``` See the [Temporal Cloud connection docs](https://docs.temporal.io/cloud/get-started) for mTLS and API key options. > **Warning:** The Temporal worker must run as a long-lived process. Do not deploy it to serverless platforms with short execution limits, such as AWS Lambda or Vercel functions. Use a container, VM, or worker-friendly platform such as Fly.io, Railway, or Kubernetes. ## Configuration options ### `taskQueue` Required. Identifies the Temporal task queue your worker polls. The same value must be passed to `init()` (used by the client to start runs) and to `Worker.create()` (used by the worker to receive them). ### `startToCloseTimeout` Optional. Sets the maximum time a single activity (step) is allowed to run before Temporal cancels it and applies the retry policy. Defaults to `1 minute`. ```ts export const { createWorkflow, createStep } = init({ client, taskQueue: 'mastra', startToCloseTimeout: '5 minutes', }) ``` ## Constraints and notes - Workflow ids must be static string literals. The build-time transformer reads the literal value to derive Temporal workflow export names. - Activities are generated automatically from `createStep()` handlers. Do not pass them in `Worker.create({ activities })`. ## Related - [Workflow runners](https://mastra.ai/docs/deployment/workflow-runners) - [Workflows overview](https://mastra.ai/docs/workflows/overview) - [Temporal documentation](https://docs.temporal.io/)