start
Start and enqueue a new workflow run.
Start/enqueue a new workflow run.
import { start } from "workflow/api";
import { myWorkflow } from "./workflows/my-workflow";
const run = await start(myWorkflow);API Signature
Parameters
Signature 1
| Name | Type | Description |
|---|---|---|
workflow | WorkflowFunction<TArgs, TResult> | WorkflowMetadata | The imported workflow function to start. |
args | unknown[] | The arguments to pass to the workflow (optional). |
options | StartOptionsWithDeploymentId | The options for the workflow run (optional). |
Signature 2
| Name | Type | Description |
|---|---|---|
workflow | WorkflowMetadata | WorkflowFunction<[], TResult> | |
options | StartOptionsWithDeploymentId |
Signature 3
| Name | Type | Description |
|---|---|---|
workflow | WorkflowMetadata | WorkflowFunction<TArgs, TResult> | |
args | TArgs | |
options | StartOptionsWithoutDeploymentId |
Signature 4
| Name | Type | Description |
|---|---|---|
workflow | WorkflowMetadata | WorkflowFunction<[], TResult> | |
options | StartOptionsWithoutDeploymentId |
StartOptions
| Name | Type | Description |
|---|---|---|
deploymentId | "latest" | (string & {}) | undefined | The deployment ID to use for the workflow run.
By default, this is automatically inferred from environment variables
when deploying to Vercel.
Set to 'latest' to automatically resolve the most recent deployment
for the current environment (same production target or git branch).
This is only meaningful in worlds with atomic, immutable deployments
(currently Vercel). In other worlds (local dev, Postgres) there is no
notion of multiple deployments to resolve between, so 'latest' has no
effect — a warning is logged and the run targets the current deployment.
**Note:** When deploymentId is provided, the argument and return types become unknown
since there is no guarantee the types will be consistent across deployments. |
world | World | The world to use for the workflow run creation, by default the world is inferred from the environment variables. |
specVersion | number | The spec version to use for the workflow run. Defaults to the latest version. |
region | string | Optional region identifier for the new run. Currently consumed only
by @workflow/world-vercel, which embeds the region into the tagged
run ID and routes the initial workflow message to the matching
regional queue. When omitted, the world falls back to its own
default (for world-vercel: the VERCEL_REGION environment
variable, then the server-side default region iad1 — a concrete,
routable region is always chosen).
Worlds without a regional dimension ignore this field. |
attributes | Record<string, string> | Plaintext attributes to seed on the run as it is created. Available for native-attributes runs (spec version 4 and later). |
allowReservedAttributes | boolean | Permit reserved $-prefixed keys in attributes. The $ namespace
is reserved for framework/library code built on top of the workflow
SDK (telemetry, agent metadata, platform-emitted tags, etc.); user
code MUST NOT write keys in it, and validation rejects them so
accidental collisions with tooling-owned keys can't slip through.
Only flip this to true if your caller is itself a framework or
library that owns a $-prefixed sub-namespace and knows the
conventions of any other tools writing into it. Same semantics as
the setAttributes option of the same name. |
replayedFromRunId | string | The ID of an existing run this run is being replayed from, if any.
Recorded on the new run's executionContext as replayedFromRunId so
tooling (e.g. the dashboard runs list) can show that a run originated as
a replay and link back to its source. Set automatically by
recreateRunFromExisting ; there's usually no reason to pass it
directly.
Must be a run ID: wrun_ followed by a 26-char ULID. It's a foreign key
to the source run, so start() validates the exact shape and rejects
anything else rather than persist a lineage link that points at garbage. |
namespace | string | Queue namespace of the target deployment. Scopes the workflow queue
topic to __{namespace}_wkf_workflow_* (e.g. 'eve') instead of the
default __wkf_workflow_*, and is also used for the cross-deployment
capability probe. Falls back to WORKFLOW_QUEUE_NAMESPACE in the
calling process.
Within a deployment the env fallback is correct. Cross-context callers
(e.g. the observability dashboard replaying a run) must pass the
TARGET deployment's namespace explicitly: the env fallback resolves in
the caller's process, and a run enqueued to a topic the target has no
consumer for is never picked up. |
Returns
Returns a Run object:
| Name | Type | Description |
|---|---|---|
#private | any | |
runId | string | The ID of the workflow run. |
wakeUp | (options?: StopSleepOptions | undefined) => Promise<StopSleepResult> | Interrupts pending sleep() calls, resuming the workflow early. |
cancel | (options?: CancelRunOptions | undefined) => Promise<void> | Cancels the workflow run. |
exists | Promise<boolean> | Whether the workflow run exists. |
status | Promise<"pending" | "running" | "completed" | "failed" | "cancelled"> | The status of the workflow run. |
returnValue | Promise<TResult> | The return value of the workflow run. Polls the workflow return value until it is completed. |
workflowName | Promise<string> | The name of the workflow. |
createdAt | Promise<Date> | The timestamp when the workflow run was created. |
startedAt | Promise<Date | undefined> | The timestamp when the workflow run started execution. Returns undefined if the workflow has not started yet. |
completedAt | Promise<Date | undefined> | The timestamp when the workflow run completed. Returns undefined if the workflow has not completed yet. |
readable | WorkflowReadableStream<any> | The readable stream of the workflow run. |
getReadable | <R = any>(options?: WorkflowReadableStreamOptions | undefined) => WorkflowReadableStream<R> | Retrieves the workflow run's default readable stream, which reads chunks written to the corresponding writable stream getWritable . The returned stream has an additional WorkflowReadableStream.getTailIndex getTailIndex() helper that returns the index of the last known chunk. This is useful when building reconnection endpoints that need to inform clients where the stream starts. |
Learn more about WorkflowReadableStreamOptions.
Good to Know
- The
start()function is used in runtime/non-workflow contexts to programmatically trigger workflow executions. - This is different from calling workflow functions directly, which is the typical pattern in Next.js applications.
- The function returns immediately after enqueuing the workflow - it doesn't wait for the workflow to complete.
- Each call to
start()creates a new workflow run. If retried requests must route to one active workflow, have the workflow create a deterministic hook token and usegetHookByToken()to reuse an already-registered active hook. The lookup is not atomic withstart(), so concurrent callers can still create extra runs before the hook is registered; handle that race inside the workflow by checkingawait hook.getConflict()before duplicate-sensitive work — on a conflict it resolves with the run that owns the token, so the duplicate can return the active owner to the caller. If duplicates must be rejected before a workflow body runs, keep a durable request record until native atomic start-and-hook registration exists. See Idempotency. - All arguments must be serializable.
- When
deploymentIdis provided, the argument types and return type becomeunknownsince there is no guarantee the workflow function's types will be consistent across different deployments.
If start() throws 'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive., the passed function was not transformed as a workflow. The two most common causes are a missing "use workflow" directive or missing framework integration. See start-invalid-workflow-function.
Examples
With Arguments
import { start } from "workflow/api";
import { userSignupWorkflow } from "./workflows/user-signup";
const run = await start(userSignupWorkflow, ["user@example.com"]);With StartOptions
import { start } from "workflow/api";
import { myWorkflow } from "./workflows/my-workflow";
const run = await start(myWorkflow, ["arg1", "arg2"], {
deploymentId: "custom-deployment-id"
});Using deploymentId: "latest"
Set deploymentId to "latest" to automatically resolve the most recent deployment for the current environment. This is useful when you want to ensure a workflow run targets the latest deployed version of your application rather than the deployment that initiated the call. For when to use this and how it fits with default run pinning, see Versioning.
import { start } from "workflow/api";
import { myWorkflow } from "./workflows/my-workflow";
const run = await start(myWorkflow, ["arg1", "arg2"], {
deploymentId: "latest"
});The deploymentId option is currently a Vercel-specific feature. Other Worlds may implement this option differently to match their own deployment runtimes, and the World spec may rename it from deploymentId to version in a future SDK version. On Vercel, "latest" resolves to the most recent deployment matching your current environment — the same production target for production deployments, or the same git branch for preview deployments.
In Worlds without atomic, immutable deployments (such as local development or self-hosted Postgres), there is no notion of multiple deployments to resolve between, so deploymentId: "latest" has no effect: the SDK logs a warning and the run targets the current deployment. This means a workflow that opts into "latest" on Vercel still runs unchanged in local development.
When using deploymentId: "latest", the workflow run will execute on a potentially different deployment than the one calling start(). Be mindful of forward and backward compatibility:
- Workflow identity: The workflow ID is derived from the function name and file path. If the latest deployment has renamed the workflow function or moved it to a different directory, the workflow ID will no longer match and the run will fail to start.
- Input and output compatibility: The arguments passed to
start()are serialized by the calling deployment but deserialized by the target deployment. Similarly, the workflow's return value is serialized by the target deployment but deserialized by the caller. If the workflow's expected arguments or return type have changed (e.g. added required fields, removed fields, or changed types), the run may fail or behave unexpectedly. Ensure that input and output schemas remain backward-compatible across deployments.