Workflow configuration reference

Every key of a sanity.workflow.ts config: defineWorkflowConfig, deployments, partitions, resource aliases, reader-model acknowledgement, and runtime blocks.

This page lists every key a sanity.workflow.ts config accepts at Workflows 0.37: the object passed to defineWorkflowConfig, each deployment in its deployments array, and the runtime blocks a deployment, workflow, or effect can carry. It also lists the validation errors the config raises. For what a deployment, partition, and resource alias mean, read Deployments, partitions, and resources. To write and deploy a config step by step, follow Configure and deploy workflow definitions.

Example

A config with two deployments of the quick start's article-review. dev keeps engine documents in the content dataset. production keeps them in a separate dataset and binds the content alias to the dataset its articles live in.

import {defineWorkflowConfig} from '@sanity/workflow-engine/define'
import type {WorkflowDeploymentInput} from '@sanity/workflow-engine'

import {articleReview} from './workflows/article-review'

export const dev = {
  name: 'dev',
  partition: 'dev',
  expectedMinReaderModel: 10,
  workflowResource: {type: 'dataset', id: 'PROJECT_ID.DATASET_NAME'},
  definitions: [articleReview],
} satisfies WorkflowDeploymentInput

export const production = {
  name: 'production',
  partition: 'production',
  expectedMinReaderModel: 10,
  workflowResource: {type: 'dataset', id: 'PROJECT_ID.workflows'},
  resourceAliases: [{name: 'content', resource: {type: 'dataset', id: 'PROJECT_ID.production'}}],
  runtime: {kind: 'function'},
  definitions: [articleReview],
} satisfies WorkflowDeploymentInput

export default defineWorkflowConfig({deployments: [dev, production]})

The CLI imports the module's default export and validates it again with defineWorkflowConfig, so a plain object default export fails at the same point a malformed defineWorkflowConfig call does. Exporting each deployment by name lets scripts, Blueprints, and the Functions generator import the same object.

Config file

  • File name

    'sanity.workflow.ts' | 'sanity.workflow.js' | 'sanity.workflow.mjs'

    The CLI searches the current directory, then each parent, for the first of these names. --path points at a file or a directory to start the search from. A .ts file loads without a build step.

  • Default export

    WorkflowConfig

    The return value of defineWorkflowConfig. A missing file fails with No sanity.workflow.ts found in <dir> or any parent directory. A module that throws while loading fails with Failed to load <file>: and the error. A config that fails validation fails with Invalid config in <file>: and the issues listed under Validation errors.

WorkflowConfigInput

WorkflowConfigInput is the object you pass to defineWorkflowConfig, imported from @sanity/workflow-engine/define. Every entry in deployments is a WorkflowDeploymentInput.

  • deployments

    WorkflowDeploymentInput[], required

    The deployments this config defines. At least one. Every name must be unique, and every pair of workflowResource and resolved partition must be unique across the array.

  • telemetry

    WorkflowTelemetryLogger, optional

    A logger, an object with a log function, that receives every Workflows CLI telemetry event. Setting it replaces the CLI's built-in Sanity intake entirely: events flow to this logger unconditionally, CI and DO_NOT_TRACK included, and consent, environment suppression, and transport become your logger's responsibility. Omit it to keep the built-in behavior.

WorkflowDeploymentInput

WorkflowDeploymentInput is the authored shape of one deployment, exported as a type from @sanity/workflow-engine. Annotate a named export with satisfies WorkflowDeploymentInput to check it where you write it and reuse it from configuration, scripts, and Blueprint entry points.

  • name

    string, required

    The deployment's identity, unique across the config. --deployment matches it, and generated Functions derive their names from it. Lowercase ASCII letters, digits, and dashes, starting with a letter or digit, with no dots.

    Renaming a deployment that generates Functions replaces those Functions; run npx sanity@latest blueprints plan and review every replacement before deploying.

  • partition

    string, optional

    The storage partition every engine document of this deployment is scoped to. Defaults to default (the DEFAULT_PARTITION export). Same grammar as name.

    Omit it only when this is the only deployment on its workflowResource. When several deployments share a resource, each must set a distinct partition; set partition: 'default' on the first one when you add a second, so its stored address does not change. Separate resources may each use default. The check reads this config only; it does not discover deployments in the Content Lake or in other configs.

    Stored definitions and instances carry the partition in a field named tag, so raw GROQ filters on tag == $tag.

  • tag

    string, deprecated

    The pre-0.37 name for partition. The config loads with a deprecation warning, which the CLI prints to stderr, and the value is used as the partition. Rename the key to partition and keep the same value: deleting it instead moves the deployment to default. A tag that is not a valid partition, is not a string, or differs from a partition set on the same deployment fails validation. See the release notes.

  • workflowResource

    WorkflowResource, required

    The Sanity resource that stores this deployment's engine documents: deployed definitions and instances. The CLI derives its client's project and dataset from it. One of {type: 'dataset', id: '<projectId>.<dataset>'}, {type: 'canvas', id}, {type: 'media-library', id}, or {type: 'dashboard', id}. A dataset id without the dot fails validation.

    Guard documents are not stored here; a guard is deployed beside the content it protects.

  • resourceAliases

    {name: string; resource: WorkflowResource}[], optional

    Binds each @<name>: reference a definition makes to a physical resource. Needed only for content outside workflowResource; bare ids resolve against workflowResource. Names use lowercase letters, digits, and dashes with no leading dash, and must be unique within the deployment.

    At deploy, every @<name>: reference expands to the bound resource before the definition is fingerprinted, so a rebind deploys as a new version. A definition that references an unbound alias fails to deploy. The CLI also serves every bound resource to the engine through deploymentResourceClients, so bound resources accept reference writes even when no definition uses the alias.

  • definitions

    DefinedWorkflow[], required

    The definitions this deployment ships, each the return value of defineWorkflow. At least one. Order does not matter: deploy orders the batch so children deploy before the parents that spawn them. A spawn reference must resolve inside the batch or to an already-deployed definition.

  • expectedMinReaderModel

    number, required to submit definitions

    The reader model you have verified across every runtime that shares this workflowResource, written as a reviewed integer literal. The config loads without it, so read-only commands work, but deploy and definitions diff reject the deployment until it is present.

    Those commands require an integer from the submitted definitions' floor up to the installed writer's maximum (11 at 0.37). Below the floor, above the maximum, missing, or non-integer values throw ReaderModelAcknowledgementError (see Reader-model acknowledgement). Upgrading a package does not by itself require changing it. Follow Upgrade Workflows packages before raising it.

  • runtime

    RuntimeBlock, optional

    Default hosting for this deployment's workflows: {kind: 'function'}, {kind: 'durableFunction'}, or {kind: 'selfHosted'}. Omitted, workflows host on function. A deployment-level block accepts no function budget. See Runtime blocks.

Unknown keys on a deployment are ignored and dropped from the parsed result.

Runtime blocks

A deployment and a workflow (defineWorkflow) accept RuntimeBlock. An effect accepts EffectRuntimeBlock, which adds the function budget. A workflow inherits its deployment's kind and each effect inherits its workflow's kind; a block at a lower level overrides the inherited value. With no block at any level, the kind is function. The block is authoring metadata: deploy strips it before storing the definition, so changing it creates no definition version. Regenerate and redeploy the runtime after changing it.

  • kind

    'function' | 'durableFunction' | 'selfHosted', required

    Required when a block is present; omit the whole block to inherit. function: generated Sanity Functions run effects and reevaluate time-based conditions. durableFunction: the generator reports the workflow or effect but emits no durable execution function. selfHosted: your own process runs it. Any other value fails with Invalid option: expected one of "function"|"durableFunction"|"selfHosted".

    Hosting is not an execution restriction: any engine with a registered handler can drain an effect. See Runtime hosting configuration.

  • timeout

    integer, 1 to 900, optional

    Effect blocks with kind: 'function' only. Seconds available to the effect's Function. Setting it gives the effect its own drain Function. Omitted, the platform default applies. A value outside the range fails at defineWorkflow; on a deployment or workflow block, the key fails as an unknown key.

  • memory

    integer, 1 to 10, optional

    Effect blocks with kind: 'function' only. Gigabytes allocated to the effect's Function. Setting it gives the effect its own drain Function. Omitted, the platform default applies. A value outside the range fails at defineWorkflow.

Effects with the same name in one deployment must declare the same kind and budget: one effect name has one handler. The generator rejects a mismatch and names both definitions.

Parsed config types

defineWorkflowConfig validates its input and returns the parsed shapes below. Read them when you write tooling that loads a config; author with WorkflowConfigInput and WorkflowDeploymentInput.

WorkflowConfig

The return value of defineWorkflowConfig. Every deployment carries a resolved partition, default when the author omitted it, and expectedMinReaderModel may still be missing until a command that submits definitions selects that deployment.

  • deployments

    WorkflowDeployment[]

    The parsed deployments, in input order.

  • warnings

    readonly string[]

    One deprecation message per deployment that named its partition with tag. Nothing prints them; the CLI writes them to stderr, and other hosts show them where their user reads them.

  • telemetry

    WorkflowTelemetryLogger | undefined

    The logger passed in, unchanged.

WorkflowDeployment

One parsed deployment: name, partition (always set), workflowResource, definitions, and the optional resourceAliases, runtime, and expectedMinReaderModel. A deprecated tag is already migrated to partition. Do not pass it back to an API that requires WorkflowDeploymentInput.

AcknowledgedWorkflowDeployment

A WorkflowDeployment whose expectedMinReaderModel has been checked against the definitions a command will submit, so the field is a number. The CLI's deploy and definitions diff produce it, and Workflows Blueprint resources require it.

Reader-model acknowledgement

Deploy compares a deployment's expectedMinReaderModel with the highest floor its submitted definitions require. These @sanity/workflow-engine exports compute and check that floor. The rollout that justifies raising the value is in Upgrade Workflows packages.

ReaderModelAcknowledgementError has kind reader-model-acknowledgement and code WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH, and carries expectedMinReaderModel, requiredMinReaderModel, engineMaxReaderModel, and documentationUrl. Its message, for a deployment named dev that acknowledges 3:

Deployment dev acknowledges reader model 3; the submitted definitions require at least 10, and this writer supports acknowledgements through 11.
Use a reviewed numeric literal in that range. Before raising it, ensure every runtime sharing the workflow resource can read the required model.
Rollout guide: https://www.sanity.io/docs/workflows/prerelease

Deployment tooling exports

Exports from @sanity/workflow-engine for scripts that load a config and act on its deployments. The CLI uses the same functions.

  • deploymentResourceClients({client, deployment})(): ResourceClientResolver | undefined

    Builds a resourceClients resolver that serves every resource deployment.resourceAliases binds, so references to them pass the write-surface check and reads route to them. Each client is derived from client with withConfig, keeping its token, API host, and request-tag prefix; those credentials must reach every bound resource. Returns undefined when the deployment binds nothing beyond workflowResource. Throws ContractViolationError when a foreign resource is bound and client has no withConfig. A runtime-supplied reference to an unbound resource is still rejected with RefResourceUndeclaredError. See Read routing and the write surface.

  • resourceAliasesToMap(resourceAliases)(): ResourceAliases

    Collapses a deployment's resourceAliases array into the alias-to-resource map that deploy expands @<name>: references against.

  • expandResourceAliases(definition, resourceAliases)(): WorkflowDefinition

    Returns the definition with every @<alias>: reference expanded to the bound physical GDR. Fails, naming the definition and alias, when an alias is unbound or a standalone reference is malformed (for example @content:a:b or an empty id). A no-op when the definition references no aliases.

  • refsOf(definition)(): LogicalRef[]

    The definition's outgoing spawn references, each {name: string, version?: number | 'latest'}. Deploy ordering and the delete referrer check use the same walk.

  • validateDefinitionInputs(definitions)(): ValidateDefinitionInputsResult

    Checks definitions in authoring or stored shape for structure, cross-field rules, and GROQ syntax without a client. Returns {valid, results} with one result per definition. Deploy also checks duplicate names, spawn dependencies, resource bindings, project roles, and the reader-model acknowledgement, so a valid result does not guarantee a deploy succeeds. sanity-workflows definitions validate and the MCP workflows_validate_definition tool return the same report.

  • deployedPartitionsGroq()(): string

    A GROQ query listing the distinct partitions that hold a deployed definition in the resource, sorted ascending. Run it with a client scoped to the workflow resource. It reports what is deployed, so a partition with nothing deployed is absent. It reads the stored tag field.

  • definitionPartitionsGroq()(): string

    The same query narrowed to one definition; pass {definition} as the query parameters. A definition deployed under several partitions returns several results, and the caller must choose one.

  • DEFAULT_PARTITION(): 'default'

    The partition a deployment resolves to when it omits partition.

Validation errors

defineWorkflowConfig throws defineWorkflowConfig failed validation (N issues): followed by one line per issue, each prefixed with the path of the failing key. The CLI prints the same text after Invalid config in sanity.workflow.ts:. An invalid partition value throws ContractViolationError with its message directly. Each line below is the issue text for one problem, for a deployment named dev, exactly as 0.37 prints it.

# No deployments
deployments: a config needs at least one deployment

# Invalid name
deployments[0].name: invalid name — ASCII lowercase + digits + dashes, no leading dash, no dots

# Invalid partition (thrown as ContractViolationError)
partition: invalid partition "Prod" — must match ^[a-z0-9][a-z0-9-]*$ (ASCII lowercase + digits + dashes, no leading dash, no dots)

# Duplicate name
deployments: duplicate deployment name "dev" — each deployment must use a unique name

# Shared resource, omitted partition
deployments: deployment "dev" shares its workflow resource with another deployment; set an explicit partition (use "default" to keep an omitted partition's address)

# Same resource and partition
deployments: deployments "dev" and "prod" share workflow resource + partition "x" — both would write into the same partition; change one deployment’s partition or resource

# Dataset id without a dot
deployments[0].workflowResource.id: invalid dataset resource id — expected "<projectId>.<dataset>"

# Unknown resource type
deployments[0].workflowResource.type: Invalid type: Expected ("dataset" | "canvas" | "media-library" | "dashboard") but received "bucket"

# Empty definitions
deployments[0].definitions: a deployment needs at least one definition

# Not a definition
deployments[0].definitions[0]: expected a workflow definition (an object with a string `name`)

# Invalid alias name
deployments[0].resourceAliases[0].name: invalid resource handle name — lowercase letters, digits and dashes only, no leading dash

# Duplicate alias name
deployments[0].resourceAliases: duplicate resource handle name "c" — each binding name must be unique within a deployment

# tag and partition differ
deployments[0]: Deployment "dev": "tag" and "partition" disagree. Remove the deprecated "tag" and keep the partition that addresses your stored workflows.

# tag not a valid partition
deployments[0]: Deployment "dev": "tag" is not a valid partition (ASCII lowercase + digits + dashes, no leading dash, no dots). Rename it to "partition" with the value that addresses your stored workflows.

# tag not a string
deployments[0]: Deployment "dev": "tag" must be a string. Rename it to "partition" and keep the existing value to retain access to stored workflows.

# Unknown runtime kind
deployments[0].runtime.kind: Invalid option: expected one of "function"|"durableFunction"|"selfHosted"

# Budget on a deployment runtime block
deployments[0].runtime.timeout: Invalid key: Expected never but received "timeout"

# Invalid telemetry logger
telemetry: expected a telemetry logger (an object with a `log` function)

Was this page helpful?

sanity.ioAll Systems Operational© Sanity 2026
Change site theme